* docs: add skills-extension-candidates tracker Scaffold a candidates list for MCP servers, dev tools, SDKs, and skills repositories that could adopt SEP-2640. Initial entries: FastMCP 3.0 Skills, chrome-devtools-mcp, hf-mcp-server, Hugging Face skills library, github-mcp-server (PR #2428 demo), Azure Skills Plugin. Cross-link from related-work.md and add a row to the README docs table. * docs: add Issue/PR tracker column to candidates table * docs: add client-mcp-support survey alongside candidates tracker * docs: link Azure MCP Server source in candidates table * docs: remove gemini-cli from client MCP support survey * docs: verify hermes-agent, switch source refs to main-branch links, refresh takeaways - Promote hermes-agent from first-pass to verified; note its per-server tool pattern (`mcp_{server}_read_resource` + `mcp_{server}_list_resources`) and confirm end-user docs exist - Drop stale line numbers throughout; convert path refs to GitHub source-file links on `main` (commit-pinned URLs decayed once files moved) - Goose: PR #8989 has landed, so describe current `(extension_name, uri)` required signature and drop the now-closed issue/PR tracking - Takeaways: collapse to three implementation patterns (Goose now fits the `(server, uri)` bucket), fix open-source count to fourteen, drop the smolagents name-drop (not in survey), add strands-agents alongside mastra for the internal-SDK-only pattern, and reframe the signature recommendation around server-resolution reliability rather than URI portability * docs: verify remaining first-pass clients, flip cline/Roo-Code to Yes Verified adk-python, agent-framework, crewAI, mastra, cline, Roo-Code against local source clones. Two corrections to prior state: - cline and Roo-Code both expose access_mcp_resource(server, uri) as a model-facing tool via McpHub.readResource. Flipped from No to Yes. - adk-python's load_mcp_resource takes resource_names: array[string] in a single call (not two-shot); opt-in via use_mcp_resources flag. Headline count updated from six to eight of fourteen open-source clients satisfying #2527. Cross-cutting observations and takeaways adjusted for the new (server, uri) family members and the four-pattern signature breakdown. Trust-model list extended. * docs: add Figma and Adobe MCP as SEP-2640 testing candidates * docs: update FastMCP 3.0 Skills entry with detailed notes on SEP-2640 compliance * docs: drop unconfirmed Cursor SEP-2640 entry, track latest SEP-2640 wire-contract PRs Remove the Cursor row + deep dive (reported WIP never confirmed). Add the in-flight PRs realigning to the 2026-06-05/06-09 SEP-2640 schema (frontmatter + archives[] index, resources/directory/read): hf-mcp-server#174, fast-agent#825, huggingface/skills#172. * docs: add Slack (interested) and Bloomberg (internal use) as SEP-2640 candidates * docs: remove archived Roo-Code from client survey, update strands repo to harness-sdk * docs: re-verify SEP-2640 implementations against current upstream main Both reference implementations have migrated to the July 2026 v1 shape, verified against fresh clones rather than the prior June commit pins: - hf-mcp-server (d794b10, v0.4.6): skills/list + skills/get, per-file {uri,digest} resources manifest, directoryRead:true, no index.json or archives. Migrated in #219 (merged 2026-08-03). Also records the snapshot/TTL model and HTTP-transport-only constraint. - fast-agent (79b903c, 0.10.1): pins SEP-2640 revision d7490ec, treats legacy index.json skill-md/archive entries as unsupported. Requires --prerelease=allow (pins fastmcp-slim 4.0.0b1), per @evalstate. Corrects the earlier note claiming implementations lagged the SEP: the #174/#825/#172 round merged 2026-06-19 and was never in flight, and a second realignment followed the v1 rework. Also fixes drift found while re-checking fast-agent's resource tool: smart_agent.py is gone (now core/harness_tools.py), get_resource is opt-in via harness_tools (default False, was unconditional), and server_name is now optional - the one surveyed client where the model may omit server identity. Runtime skill loading is still unshipped; #816 remains open. 🦉 Generated with [Claude Code](https://claude.com/claude-code) * docs: track SEP revision 0eb05fe and add mcpkit to the candidates tracker The SEP moved from d7490ec to 0eb05fe (2026-08-05). The delta is editorial for the wire contract -- skills/list, skills/get, and the per-file resources manifest are unchanged -- so d7490ec-pinned implementations stay compatible. Records what it does change: a soft reg-name constraint on the first skill-path segment, the skill root URI fixed as skill://<skill-path> with no trailing slash, whether skills/get carries ttlMs/cacheScope reopened, and normative host obligations in the security section. Adds mcpkit (panyam/mcpkit, Go, v0.3.0) from #118 as a candidate. It implements the pre-v1 index.json catalog shape with per-file digests, so the ecosystem is now split across draft revisions rather than uniformly caught up. 🦉 Generated with [Claude Code](https://claude.com/claude-code) * docs: refine mcpkit entry — deliberate tracking, partial v1 migration Checked mcpkit's issues and PRs rather than inferring alignment from code shape. Its lag is a tracked decision, not drift: - #1185 (merged 2026-08-04) implements origin-tagging and per-origin resolve citing SEP L179/L183/L185 -- the host obligations 0eb05fe made normative -- so it is already on v1 for the security section. #1187 adds a SEP-2640 security/conformance harness as a WG demo. - #780 is an explicit index-schema tracking issue that has absorbed the archives removal and the resources:[{uri,digest}] direction but waits on WG confirmation; its conformance fork pins provenance at 556154c. - The carrier change is still unbooked: nothing references skills/list or skills/get. - Archives are kept as a non-spec extended surface rather than deleted, unlike fast-agent -- a counter-case for whether deferring a feature removes it from the ecosystem. Sharpens the callout accordingly: the draft split runs within an implementation, not only between them, so "which draft does X implement" often has no single answer. 🦉 Generated with [Claude Code](https://claude.com/claude-code)
46 KiB
Client Research: Model-facing MCP Resource & SEP-2640 Support
Scope. This page tracks two related areas of client support:
- Model-facing MCP resource loading — does the client expose a tool that lets the model trigger an MCP
resources/read? This is the SHOULD proposed in modelcontextprotocol/modelcontextprotocol#2527 (which phrases it as "by URI"); for survey purposes we also count by-name variants where the framework resolves a model-supplied name to a URI before callingresources/read(adk-python is the one such case found). The bulk of this page is this survey.- SEP-2640 skills extension support — as clients ship SEP-2640 implementations, this page tracks them. fast-agent is the first surveyed client to ship one (registry/install scope — see its deep dive), verified live against the Hugging Face MCP server, which is the first server-side implementation we've interoperated with. SEP-2640-related issues, PRs, and shipped implementations are tracked per-client in the "Open issues/PRs to watch" column rather than via a separate status field.
ℹ️ SEP-2640 claims here are pinned to a draft revision. The July 8–15, 2026 v1 rework (2026-07-16 decision record) removed archives, replaced
skill://index.jsonwith askills/listmethod, replaced the single per-entry digest with a per-fileresourcesmanifest, addedskills/get, and gatedresources/directory/readbehind adirectoryReadcapability. fast-agent has since realigned to that shape — its docs pin draft revisiond7490ecand explicitly drop the older index/archive path — as has its server counterpart, both confirmed by @evalstate in Discord (2026-08-04). Note the client side ships behind a prerelease install (--prerelease=allow; see its deep dive). This is the second realignment (the first was 2026-06-19); since the SEP is still a draft under review, expect further churn and re-verify against the SEP's current revision. The SEP is now at0eb05fe(2026-08-05), but that delta leaves the wire contract intact, sod7490ecpins remain compatible — see skills-extension-candidates.md for what it does change.Why these are tracked together. SEP-2640 layers skills on top of MCP resources. If a host's progressive-disclosure flow involves the model itself loading L2/L3 skill content from
skill://…or related resource URIs, then the resource-read affordance for the model becomes critical for skills. A client's resource-loading shape today is a strong predictor of how it'll fit SEP-2640 tomorrow.See also skills-extension-candidates.md for the matching server-side tracker: MCP servers, dev tools, SDKs, and skills repositories that are candidates for adopting SEP-2640.
At-a-glance comparison
Category values: Framework = SDK/library you build agents on top of · CLI = end-user coding agent or CLI · IDE = editor-embedded chat surface.
| Client | Category | Tool exposed to model? | Tool name(s) | Tool signature | Calls resources/read on connected server? |
Enablement gate | End-user docs? | Open issues/PRs to watch |
|---|---|---|---|---|---|---|---|---|
| codex (OpenAI) | CLI | Yes | read_mcp_resource, list_mcp_resources, list_mcp_resource_templates |
(server, uri) — server explicitly named |
Yes — handler calls session.read_resource() |
Any MCP server is configured (params.mcp_tools.is_some()) |
No — only the LLM-visible tool description; an internal steer tells the model to prefer tool_search |
none yet — add as found |
| goose (Block) | CLI | Yes | read_resource, list_resources |
(extension_name, uri) on read_resource — extension_name required; list_resources takes an optional extension_name filter |
Yes — ExtensionManager::read_resource → client.read_resource(...) |
≥1 enabled extension reports ServerCapabilities::resources |
Yes — extension-manager-mcp.md |
none yet — add as found |
| fast-agent | Framework | Yes (multiplexed) | get_resource (no model-facing list_resources) |
(uri, server_name=None) — server_name optional; also handles bundled internal:// URIs through the same tool |
Yes for MCP URIs — _read_resource() → agent.get_resource(resource_uri=uri, namespace=server_name); internal:// URIs short-circuit to bundled resources |
Opt-in — config.harness_tools, default False (also stripped when tool_only) |
Partial — skills-over-mcp.md covers the SEP-2640 install flow; the get_resource tool itself has no dedicated docs section |
SEP-2640 v1 shipped (registry/install scope) — consumes the io.modelcontextprotocol/skills extension to install skills via skills/list / skills/get + per-file digest-verified resources/read (skills_extension.py, mcp_registry.py, skills-over-mcp.md); pins draft d7490ec and treats legacy skill://index.json skill-md/archive entries as unsupported; still does not read skill resources at model runtime. Verified live against hf-mcp-server. Watch: #816 (still open) adds MCP-served skill runtime loading (URI-backed manifests, SkillReader resource reads, untrusted-content wrapping) |
| vscode (GitHub Copilot) | IDE | Yes (FS-provider indirection) | copilot_readFile, copilot_listDirectory (general-purpose, not MCP-specific) |
(path) — accepts mcp-resource://… URIs as paths; the FS provider routes to MCP RPC |
Yes — mcp-resource:// URIs route via IFileService → McpResourceFilesystem provider → r.readResource(...) MCP RPC (mcpResourceFilesystem.ts) |
Server must advertise McpCapability.Resources; model needs a URI to pass (typically obtained from a user attachment — the earlier Copilot Chat resource_link→mcp-resource:// pre-wrap has since been removed; see deep dive) |
No explicit doc, but mechanism is operational. Connor Peet's comment on #2527 is the clearest write-up | none yet — add as found |
| opencode | CLI | No | — (internal readResource only) |
— | Internal only — readResource() exists in packages/opencode/src/mcp/index.ts but is invoked only when the user attaches a resource via file picker; mcp.tools() in prompt.ts forwards MCP tools but never a resource-read tool |
n/a | Docs (mcp-servers.mdx) advertise tool forwarding only |
none yet — add as found |
| deepagents (LangChain) | Framework | No | — | — | n/a — delegates MCP wiring to langchain-mcp-adapters (via convert_mcp_tool_to_langchain_tool() / _build_cached_mcp_tool() in mcp_tools.py); that adapter only converts MCP tools, not resources |
n/a | No mention in README | Upstream-blocked: needs a change in langchain-mcp-adapters (or a deepagents wrapper around client.read_resource()) |
| strands-agents (AWS) | Framework | No (internal SDK only) | — | — | Internal only — MCPClient.read_resource_sync() and list_resources_sync() in mcp_client.py call MCP resources/read / resources/list, but MCPAgentTool (the only adapter) wraps mcp.types.Tool only and MCPClient.load_tools() (the ToolProvider interface) returns tools only |
n/a | No — docs/MCP_CLIENT_ARCHITECTURE.md and AGENTS.md do not mention MCP resources |
none yet — add as found |
| Claude Code (closed source, reference) | CLI | Yes | ReadMcpResourceTool |
(server, uri) per public docs |
Documented; source not verifiable | n/a | Yes — public tools reference page | n/a |
| adk-python (Google ADK) | Framework | Yes (by name, not URI) | load_mcp_resource |
(resource_names: array[string]) — model passes catalog names; framework resolves each to a URI and calls session.read_resource(uri=…). The catalog is injected into the model's context by _append_resources_to_llm_request() rather than via a separate list call |
Yes — McpToolset.read_resource() calls session.read_resource(uri=…) (mcp_toolset.py) |
Opt-in via use_mcp_resources=True on McpToolset (default False) |
No — no user-facing docs found | none yet — add as found |
| agent-framework (Microsoft) | Framework | No (tools-only client bridge) | — | — | n/a — MCPTool / MCPStdioTool / MCPStreamableHTTPTool / MCPWebsocketTool in _mcp.py materialize MCP tools into the agent's tool registry; no read_resource callsite found in client code (only in a test) |
n/a | Samples cover MCP tool integration only | none yet — add as found |
| cline | IDE | Yes | access_mcp_resource |
(server_name, uri) |
Yes — McpHub.readResource(serverName, uri) calls resources/read; invoked from AccessMcpResourceHandler |
Server's resources capability surfaces in system prompt context via the mcp.ts formatter |
No dedicated user-facing docs found | none yet — add as found |
| crewAI | Framework | No | — | — | n/a — crewai-tools MCP adapter (mcp_adapter.py) is built on mcpadapt and converts MCP tools only — same upstream-blocked pattern as smolagents |
n/a | MCP adapter docs cover tools only | Upstream-blocked by mcpadapt (shared with smolagents) |
| hermes-agent (Nous Research) | CLI | Yes | mcp_{server}_read_resource, mcp_{server}_list_resources (one pair per connected server) |
(uri) — server is encoded in the tool name |
Yes — _make_read_resource_handler() in tools/mcp_tool.py calls session.read_resource(uri) and registers the tool per server |
Two gates: tools.resources config flag (default on) AND server's advertised capabilities.resources |
Yes — features/mcp.md and guides/use-mcp-with-hermes.md |
none yet — add as found |
| mastra | Framework | No (internal SDK only) | — | — | Internal only — resource.ts exposes a read(uri) SDK method that calls client.readResource(uri), but it is not registered as an LLM-facing tool; the model-facing tool bridge converts MCP tools only |
n/a | SDK docs cover the action; no LLM-tool exposure | none yet — add as found |
Cross-cutting observations
-
Three implementation patterns for model-facing MCP resource access.
- Dedicated MCP resource tools — Codex, Goose, Claude Code, Cline: explicit
read_mcp_resource/read_resource/access_mcp_resource(+ optionallist_*) registered alongside other MCP tools. Most discoverable by the model; closest literal reading of #2527. adk-python is a near-relative — itsload_mcp_resourcetakes a batch ofresource_namesin one call rather than a single URI, but the affordance shape is the same. - Multiplexed resource tool — fast-agent: one
get_resourcetool handles both bundled (internal://) and MCP URIs behind a single name. Simpler surface for the model; relies on URI scheme to disambiguate. - FS-provider indirection via namespaced URIs — VS Code: no MCP-specific tool. A dedicated URI scheme (
mcp-resource://) is registered with the filesystem service so the genericreadFile/listDirectorytools transparently reach MCPresources/read. Reuses the agent's existing file-reading affordance; costs nothing in tool-count budget. Downside: nolistequivalent — the model can only read URIs it's been handed.
- Dedicated MCP resource tools — Codex, Goose, Claude Code, Cline: explicit
-
Dedicated-tool implementers converge on
(server, uri). Codex, Goose, Claude Code, and Cline all take an explicit required server identifier alongside the URI. fast-agent takes the same pair but withserver_nameoptional — the one surveyed implementation where the model may omit server identity entirely, which is the failure mode the takeaways flag below. hermes-agent is the remaining variant in pattern (1)'s family: it encodes server-in-tool-name (one tool per server) and takes only(uri). adk-python is the outlier — it takes(resource_names: array[string])and resolves URIs via a model-visible catalog injected into context. -
Trust models diverge. Per-server enablement (Goose), unconditional-when-MCP-configured (Codex), capability-gated FS provider (VS Code), capability-gated dedicated tool (Cline), or framework opt-in flag (adk-python,
use_mcp_resources=True, default off). For skills-over-MCP this matters because the "who can read what" boundary is currently set by each host individually — a portable skill that depends onresources/readwill work or not based on whether the host considers MCP resource access a model-grade affordance. -
Discoverability differs sharply between patterns — and within them. Within pattern (1), discovery shapes diverge: Codex, Goose, hermes-agent (per server), and Claude Code pair
read_*with alist_*tool so the model can enumerate resources on its own; Cline instead injects each server'sresourcesandresourceTemplatesinto the system prompt via itsmcp.tsformatter; adk-python injects an in-context catalog of resource names via_append_resources_to_llm_request(). Pattern (2) (fast-agent) has no model-facinglist_resourceson current main — of its two harness tools onlyget_resourcereads resources;list_resourcesexists on the agent/aggregator but is never registered as a tool. Pattern (3) (VS Code) has no list equivalent — the model can only read a URI it's been handed (user attachment → chat context, or an MCP tool returning aresource_link). For skills this matters less than it once did: v1 moved enumeration to askills/listmethod, which the host calls directly rather than routing through the model's resource-read tool — so a client's missinglist_resourcesno longer blocks skill discovery. It still matters for the L2/L3 step, where the model reads specific skill files by URI. -
VS Code's FS-provider pattern is worth its own consideration for skills. Because
mcp-resource://URIs are first-class in the file service, any tool that takes a path argument in VS Code can transparently read MCP resources — including, in principle, a skill loader. The skills-over-MCP design could lean on this by treatingskill://server/name/SKILL.mdas just another URI scheme registered with the host's file abstraction. This is closer to a registry-style integration (cf. how VS Code surfaces skills viaChatSessionCustomizationProviderrather than as system-prompt content).
Per-client deep dives
Agent SDKs / frameworks
fast-agent
Verified at commit 79b903c (0.10.1, 2026-08-04). Restructured since the prior 10a996b (2026-06-02) check: smart_agent.py is gone and the smart tool with it; the model-facing harness tools now live in core/harness_tools.py.
- Model-facing tool:
get_resource, registered viaagent.add_tool(...)inset_harness_tools()alongsideslash_command(the two members ofHARNESS_TOOL_NAMES)._read_resource()routesinternal://to bundled resources; everything else hits the connected MCP server viaagent.get_resource(resource_uri=uri, namespace=server_name)→ MCPresources/read. - Signature:
(uri, server_name=None)— multiplexed across bundled and MCP URIs by scheme, andserver_nameis now optional, so the model can omit the server identifier (see the server-identity point in the takeaways). - Enablement changed — now opt-in, default off. Gated on
agent.config.harness_tools, which defaults toFalse(agent_types.py:115); harness tools are also stripped whentool_onlyis set. This page previously recorded fast-agent as unconditional for everySmartAgent— that is no longer accurate, and it moves fast-agent into the same opt-in category as adk-python'suse_mcp_resources=True. - No model-facing
list_resources: unchanged —list_resourcesexists on the agent/aggregator but is not registered as a tool, so the model can only read a URI it's been handed.
SEP-2640 v1 skills extension (shipped — registry/install scope). Verified at commit 79b903c. fast-agent is the first surveyed client to ship a SEP-2640 implementation, and has now realigned to the v1 shape.
- Pinned draft revision.
skills-over-mcp.mdpins compatibility to SEP-2640 revisiond7490ecand states plainly that this is "draft compatibility, not support for a ratified MCP standard." Legacy servers publishingskill://index.jsonwithskill-mdor archive artifacts are explicitly unsupported — the older path was removed, not kept alongside. Pinning the SEP revision in user-facing docs is a practice worth noting for other implementers. - What it implements: the registry and installation portion of the SEP, not model-facing resource loading. When a connected server advertises the
io.modelcontextprotocol/skillsextension capability (server_supports_mcp_skills()checkscapabilities.extensionsinmcp_registry.py), fast-agent treats it as an MCP-backed skills registry. - Flow (v1):
/skills registrycalls paginatedskills/list; installing an entry refreshes it viaskills/get, then fetches every file named in itsresourcesmanifest throughresources/readand requires each to match its declared SHA-256 before writing the local copy. Sidecar metadata records host-assigned server identity, skill URI, and the manifest. Entries omittingresources(dynamically generated skills) are listed but not installable — no complete digest manifest means no integrity check and no update revision. - Exercises v1's unlisted-skill path.
/skills add skill://acme/example/SKILL.mdinstalls a skill absent from the listing, with the server confirming the URI viaskills/get— the exact gap the 2026-07-15skills/getdecision was written to close, now with a working implementation behind it. Name-collision handling is implemented per v1 too: same-named listing entries are preserved and disambiguated by URI, though the local managed directory still admits only one skill per name. - Integrity ≠ trust. The docs carry an explicit warning that a passing SHA-256 check only means the bytes match the manifest that server supplied — it does not authenticate server or publisher, nor vouch for the skill's instructions. Useful framing for the threat model.
- Provisional wire models. The pinned MCP Python SDK ships no typed SEP-2640 models, so fast-agent carries its own for
skills/list,skills/get, andresources/directory/read(skills_extension.py). A concrete data point on what adopting the extension costs while SDK support lags. - Install requires opting into prereleases. Per @evalstate (fast-agent's author) in Discord, v1 support must be installed as
uv tool install -U --prerelease=allow fast-agent-mcp—fast-agent-mcp0.10.1 is published on PyPI, but it pinsfastmcp-slim[server]==4.0.0b1(plusmcp==2.0.0/mcp-types==2.0.0), and uv refuses prerelease dependencies unless told otherwise. So the first end-to-end SEP-2640 v1 client stack is reachable only through a prerelease install path — worth knowing before treating "shipped" as "generally available." - Still not model-facing at runtime. Active skills do not read supporting files from the MCP server during a session; PR #816 ("Add MCP-served skill runtime support") remains open. The SEP-2640 path is still host-driven install, distinct from the model-facing
get_resourcetool above. (TheSkillReaderin main serves local skill files in non-ACP contexts, not MCP-served ones.) - Realignment history: two rounds. #825 (merged 2026-06-19, with #831 hardening) moved it to the 2026-06-05 contract; the v1 migration landed later inside the 0.10 release series (#892/#905) rather than as a standalone skills PR.
- Verified against a live server: the Hugging Face MCP server is the server-side counterpart, which migrated to v1 in #219 (merged 2026-08-03); see its row in skills-extension-candidates.md. fast-agent's docs walk through
/mcp connect --name hf https://huggingface.co/mcp→/skills registry hf→/skills add.
adk-python (Google ADK)
Verified at commit 61a3933 (2026-06-03).
- MCP integration:
src/google/adk/tools/mcp_tool/package —McpToolset(lowercase c;MCPToolsetis a deprecated alias) is the entry point used by callers to connect an ADK agent to an MCP server. - Resource RPC wired:
mcp_toolset.pyexposesasync def read_resource(self, name, readonly_context=None)which callssession.read_resource(uri=resource_info["uri"]). - Model-facing tool:
load_mcp_resource_tool.pydefinesload_mcp_resource. Not two-shot — the tool's input schema isresource_names: array[string](one call returns the contents of N resources). The catalog of available resources is exposed to the model via_append_resources_to_llm_request()injecting it into the LLM context, rather than via a separatelisttool. - Enablement: opt-in via the
use_mcp_resources=Trueconstructor flag onMcpToolset(defaultFalse). When set,get_tools()appendsLoadMcpResourceToolto the toolset alongside the dynamically discovered MCP tools. - End-user docs: none found in
README.mdor the docs folder — the affordance is undocumented for end users despite being implemented. - Why interesting: ADK is the client with the most rigorous skill validation in the parallel skills survey, so this is where the spec extension and the resource-tool extension converge. The batch
resource_namesshape is a distinct fourth signature among dedicated-tool implementers.
agent-framework (Microsoft)
Verified at commit c3901a4 (2026-06-03).
- MCP integration: Multi-transport client tools —
MCPToolplusMCPStdioTool,MCPStreamableHTTPTool,MCPWebsocketToolin_mcp.py. The client-facing methods areload_tools(),call_tool(),load_prompts(),get_prompt()— no resource methods. .NET equivalents (e.g.DefaultMcpToolHandler) underdotnet/src/exposeInvokeToolAsync()only. - Resource RPC wired: No MCP resource RPC at the model boundary. The only production
read_resourcecallsites are in_skills.pyand refer to skill resources, not the model-facing MCPresources/read. All MCPresources/readreferences are confined to tests. - Update: upstream has since added MCP-based skills discovery (recent commits use MCP resources internally for skill metadata /
skill://index.jsonlookups via_skills.py) — but this is still not exposed to the model as a resource-read tool. - Why on the list: dual-stack Python/.NET framework with rich skills metadata in the parallel skills survey. The asymmetry — skills support without a model-facing MCP resource tool — is the kind of gap a #2527-aligned PR would close.
crewAI
Verified at commit 051fa0c (2026-06) of the main crewAI repo, which vendors crewai-tools under lib/crewai-tools/ (the adapter is now under lib/crewai-tools/src/crewai_tools/).
- MCP integration:
mcp_adapter.pyimportsmcp(StdioServerParameters,CallToolResult,TextContent,Tool) andmcpadapt.core(MCPAdapt,ToolAdapter);CrewAIToolAdapter.adapt(func, mcp_tool: Tool)converts MCP tools to CrewAIBaseToolobjects. - Resource RPC wired: No —
adapt()is typed to accept onlymcp_tool: Tool; zero matches forresource/Resourceanywhere in the adapter file or directory._run()extractsCallToolResultcontent only. - Model-facing tool: None.
- Why on the list: Same upstream block as smolagents — both depend on
mcpadapt(mcpadapt>=0.1.9declared as optional dep inlib/crewai-tools/pyproject.toml), which is tools-only. A single upstream change inmcpadaptflips both clients. This is the highest-leverage adapter-library target identified so far.
deepagents (LangChain)
Verified at commit 436409f (2026-06-03). Note the repo has since been restructured into a monorepo — the MCP code now lives under libs/code/deepagents_code/.
- MCP wiring is outsourced to
langchain-mcp-adapters—mcp_tools.pycallsconvert_mcp_tool_to_langchain_tool()/_build_cached_mcp_tool()(the olderload_mcp_tools()entry point is no longer used). The adapter does not exposeresources/readas a tool — zero hits for resource-read in deepagents source; sessions only calllist_tools()/call_tool(). - What it would take: either upstream adds a resource-read tool, or deepagents wraps
client.read_resource()outside the adapter.
mastra
Verified at commit f82cc72 (2026-06).
- MCP integration:
packages/mcp/src/client/client.tsimportsClientfrom@modelcontextprotocol/sdk/client/index.js.actions/resource.tsexposespublic async read(uri: string)which directly returnsthis.client.readResource(uri). - Resource RPC wired: Yes, but internal SDK only.
ResourceClientActionsis mounted asthis.resourceson the client — an SDK surface for callers, not registered as an LLM-facing tool. - Model-facing tool: No. The model-facing bridge is
tools()atclient.tswhich callsthis.client.listTools()and iterates only the returned tools array — resources are never traversed. - Why on the list: Mastra's skill versioning architecture (content-addressable BlobStore, draft→publish lifecycle) is the most sophisticated. Unlocking resource-read at the model boundary would be a small change relative to the rest of the framework — the SDK plumbing already exists.
strands-agents
Verified at commit 0e0035f (2026-06). Strands matches the mastra pattern: resource RPC wired in the SDK, but no model-facing tool. The Python SDK lives in the strands-py/ package of the strands-agents/harness-sdk monorepo.
- Resource RPC wired but unbridged:
MCPClient.read_resource_sync(),list_resources_sync(), andlist_resource_templates_sync()inmcp_client.pyare SDK-public methods, butMCPAgentToolonly wrapsmcp.types.Tooland delegates tocall_tool_async(...). Outside tests, nothing in the repo invokes the resource methods. - Why on the list: Strands has its own local-filesystem skills implementation at
agent_skills.py, so the framework already does progressive disclosure. Wiring resource-read to the model is the obvious next step for an MCP-backed skill story.
Coding agents / CLIs
codex (OpenAI)
Verified at commit ad2012d. (The handlers were reorganized from the single codex-rs/tools/src/mcp_resource_tool.rs file into a per-tool module directory since the prior 67849d9 check.)
- Model-facing tools:
read_mcp_resource,list_mcp_resources,list_mcp_resource_templates, each a handler module undercodex-rs/core/src/tools/handlers/mcp_resource/; registered unconditionally viaadd_mcp_resource_toolsinspec_plan.rs, gated oncontext.mcp_tools.is_some(). The read handlerread_mcp_resource.rscallssession.read_resource(&server, …). - Signature:
(server, uri)— model names the server explicitly. No user-facing doc; an internal steer (inapps_instructions.rs) tells the model to prefertool_search.
goose (AAIF)
Verified at commit 45d8bf8.
- Model-facing tools:
read_resource,list_resourcesregistered inext_manager.rswhen at least one extension reportsServerCapabilities::resources. Dispatch flows throughextension_manager.rs→client.read_resource(...)→ MCPresources/read. Documented atextension-manager-mcp.md. - Signature:
(extension_name, uri)onread_resource—extension_nameis required.list_resourcestakes an optionalextension_namefilter; the tool description directs the model to calllist_resourcesfirst when ownership is unknown.
hermes-agent (Nous Research)
Verified at commit 03ba06e (2026-06). No drift across the 376 commits since the prior 72ff3e9 check.
- MCP integration: Full integration in
tools/mcp_tool.py. - Resource RPC wired: Yes —
_make_read_resource_handler()callsawait server.session.read_resource(uri); the per-server schemas are built in_build_utility_schemas(). - Model-facing tools: Yes — both
mcp_{safe_name}_read_resource(takinguri) andmcp_{safe_name}_list_resources(no parameters) registered per connected server via_build_utility_schemas(). Conditionally registered when the server advertisescapabilities.resourcesAND the per-servertools.resourcesconfig flag is on (default). - Signature:
(uri)— server is encoded in the tool name (one tool per server), so the model implicitly selects the server by selecting the tool. Distinct from every other pattern surveyed: not(server, uri), not(resource_names: array[string])batch, not(uri)-with-probing, not URI-virtualized — it's one tool per server. The matchinglist_resourcesper server gives the model a discovery affordance without cross-server probing. - End-user docs:
features/mcp.mdandguides/use-mcp-with-hermes.mdboth document the utility wrappers. (Minor doc/code mismatch: the user-facing docs name the tools as bareread_resource/list_resources, but the actual model-facing names include themcp_{server}_prefix.) - Why interesting: The per-server-tool naming is a candidate disambiguation pattern for skills-over-MCP — the model can't pick the wrong server because each tool only binds to one.
Claude Code (closed source — reference only)
Claude Code is closed source so we cannot verify the loader, but the public tools reference documents ReadMcpResourceTool accepting server and uri parameters. Listed here as a reference data point for the (server, uri) signature shape also adopted by Codex, Goose, fast-agent, and Cline.
opencode
Verified at commit 2a33add on the canonical dev default branch.
- Tools forwarded to the model in
packages/opencode/src/mcp/index.tsviaclient.callTool(); tool naming convention{server_name}_{tool_name}(sanitized, underscore-separated —sanitize(clientName) + "_" + sanitize(mcpTool.name)). The model-tool bridge inpackages/opencode/src/session/tools.tsforwards onlymcp.tools(). - Resource-read is UI-only:
readResource()in the same file is invoked only from the file picker (session/prompt.tsattachment path), never registered as an LLM tool. Docs (mcp-servers.mdx) advertise tool forwarding only.
IDE extensions
vscode (GitHub Copilot)
Verified at commit ebb335f (vscode core, 2026-06-03); the Copilot Chat extension was re-checked against current microsoft/vscode-copilot-chat main. VS Code is the unique pattern here: no MCP-specific tool — generic copilot_readFile / copilot_listDirectory tools transparently reach MCP servers via filesystem-provider indirection on a custom URI scheme.
- URI scheme + FS provider:
McpResourceURIdefinesmcp-resource://URIs that encode the MCP server's definition ID in the authority — self-routing.McpResourceFilesystemis registered for that scheme;_readURIInnerdecodes the URI, looks up theMcpServer, and callsr.readResource(...)— the MCPresources/readRPC. Capability-gated onMcpCapability.Resources. resource_linkpre-wrap — removed: the doc previously describedmcpLanguageModelToolContribution.tsconverting an MCP tool'sresource_linkinto anmcp-resource://URI for later re-reading viacopilot_readFile. As of current main that file is gone andmicrosoft/vscode-copilot-chatno longer references themcp-resource://scheme at all. The core scheme + FS provider in vscode itself remain intact, but the extension no longer auto-wrapsresource_links — so the model now has fewer built-in ways to obtain such a URI (the live forwarding path observed in the local clone rendersresource_links as plain text). Worth re-confirming the current intended mechanism upstream.- Caveat — discoverability: the model can only read a URI it has been handed (e.g. a user attachment). No
list_mcp_resources-equivalent for the model. Note vscode core does now exposeIMcpServer.resources()/resourceTemplates()(mcpTypes.ts), but these feed a user-facing resource quick-pick (mcpResourceQuickAccess.ts), not a model tool. Connor Peet on PR #2527 is the clearest write-up of this pattern.
cline
Verified at commit 81792d2 (2026-06-04). Note the repo restructured into a monorepo — the VS Code extension source now lives under apps/vscode/src/ (was src/).
- MCP integration: Depends on
@modelcontextprotocol/sdk^1.25.1perapps/vscode/package.json. - Resource RPC wired: Yes.
McpHub.readResource(serverName, uri)issues a rawresources/readrequest against the named connection's client and decodes withReadResourceResultSchema. - Model-facing tool: Yes.
AccessMcpResourceHandlercallsmcpHub.readResource(...)from the model-tool execution pipeline. The model seesaccess_mcp_resourceas a registered tool taking(server_name, uri). - Discoverability: The system-prompt formatter enumerates each connected server's
resourcesandresourceTemplatesinformatMcpServersList(). Populated byfetchResourcesList()andfetchResourceTemplatesList()inMcpHub.ts. - End-user docs: none found in
README.md; nodocs/directory in the repo root. - Why interesting: Cline has the most extensive skills implementation in the parallel survey (incl. the admin-locked enterprise
globalSkillsprimitive), so the presence of full resource-read support, in-prompt enumeration, and dedicated handler is the natural complement.
Takeaways for SEP-2640 (skills extension)
-
v1's protocol surface has a working client/server pair, and realignment is fast but not free. fast-agent and hf-mcp-server have both migrated to the July v1 shape (fast-agent pinning revision
d7490ec; hf-mcp-server via #219, 2026-08-03), soskills/list,skills/get, per-file digest verification, anddirectoryReadgating are all exercised end-to-end — including v1-specific paths like installing an unlisted skill by URI throughskills/get. Two observations for the WG: (a) this pair has now realigned twice in seven weeks (2026-06-19, then early August), and each round was a breaking change — both implementations dropped the old shape rather than supporting both, and fast-agent's archive download/extract hardening was discarded outright when archives became a deferred feature; (b) neither can lean on the SDK — fast-agent carries provisional local wire models because the pinned MCP Python SDK has no typed SEP-2640 models, which is a standing cost for every adopter until the SDKs catch up. Implementation experience is real evidence for the SEP's readiness here, but it is evidence about a pinned revision, so it should be re-dated whenever the draft moves — and about a prerelease install path on the client side, not a generally-available one. -
First shipped client + server pair. fast-agent is the first surveyed client to ship a SEP-2640 implementation — but scoped to registry/install: it consumes the
io.modelcontextprotocol/skillsextension to install digest-verified skills into its managed skills directory, and does not (yet) read skill resources at model runtime (#816 still open). It was verified live against the Hugging Face MCP server, the first server-side implementation we've interoperated with (advertises the extension withdirectoryRead: trueplusresources: { subscribe: false, listChanged: false }; tracked in skills-extension-candidates.md). One deployment detail worth carrying into the SEP discussion: HF serves skills over HTTP transports only, not over long-lived STDIO. Notably, the first real-world wrinkle was operational, not protocol-level: a client that retry-loopsresources/subscribe(cursor-vscode) flooded the HF server, prompting a client-denylist mitigation (hf-mcp-server#164) — a reminder that serving skills as resources inherits the resource subsystem's failure modes. -
Seven of thirteen open-source clients surveyed (Codex, Goose, fast-agent, VS Code, hermes-agent, adk-python, Cline) satisfy #2527's SHOULD; closed-source Claude Code's public docs confirm it does too. Goose and hermes-agent also satisfy the implicit expectation that this be documented for end users; the other implementers ship the affordance with no user-facing documentation.
-
Four implementation patterns for model-facing MCP resource access — all support the layering Peter sketches in his #2640 comment, but with different costs:
- Dedicated tools,
(server, uri)(Codex, Goose, Claude Code, fast-agent, Cline — fast-agent is also multiplexed acrossinternal://): explicitread_resource/access_mcp_resourceregistered alongside other MCP tools. Most discoverable; closest literal reading of #2527. By volume, this is the dominant pattern. - Dedicated tool,
(resource_names: array[string])(adk-python): batch read; the available resources are surfaced to the model via context injection rather than a separate list tool. Same affordance shape as the(server, uri)family but with the server identifier embedded in the catalogued resource name rather than passed as a parameter. - One tool per server,
(uri)(hermes-agent): server is encoded in the tool name (mcp_{server}_read_resource), so the model selects the server by selecting the tool. Trades catalog tokens for unambiguity. Pairs withmcp_{server}_list_resourcesso the model has a per-server discovery affordance. - FS-provider indirection via namespaced URIs (VS Code): no MCP-specific tool.
mcp-resource://URIs are registered with the file service; genericreadFile/listDirectorytools transparently reachresources/read. Costs nothing in tool-count budget; loseslistaffordance.
Reliability implication: each pattern enforces server identity differently — explicit parameter (
(server, uri)), tool choice (per-server tool), catalog-name lookup (adk-python), or URI authority (mcp-resource://<server-id>/...). The spec should nudge implementations to keep server identity mandatory so a skill always resolves to its owning server. Otherwise the host has to probe every connected server when the model omits it — either silently picking the wrong one, or iterating through all of them at the cost of latency and tokens. fast-agent's optionalserver_nameis the live instance of this: notably, its SEP-2640 install path does not inherit the ambiguity, since/skills registry <server>binds a specific server and skill provenance is recorded per install — a useful signal that skill-scoped operations want stronger server binding than a general resource-read tool. - Dedicated tools,
-
Adapter libraries block two "no" rows. crewAI depends on
mcpadapt; deepagents depends onlangchain-mcp-adapters. Both adapters are tools-only — the unlock for either client lives in the adapter, not the client repo. -
Internal SDK without LLM-tool exposure (mastra, strands-agents) is its own pattern: the resource RPC is wired in the SDK but not bridged to the model. Closing this gap is typically smaller-scope than wiring the RPC from scratch.