SEP-2640: Skills Extension - #2640
Conversation
1f35055 to
7b35855
Compare
2216f34 to
8d51b62
Compare
* Align resource layer with SEP-2640 (Skills Extension)
Replace legacy `skill://{name}` and `skill://{name}/` URIs with the SEP-2640
shape: `skill://<skill-path>/SKILL.md` for skill markdown, individual files
addressable as siblings, and a new `skill://index.json` discovery resource.
Declares the `io.modelcontextprotocol/skills` extension in initialize
capabilities, and adds `getSkillPath` / `buildSkillResourceUri` /
`parseSkillResourceUri` / `buildSkillIndex` helpers in skill-discovery.ts.
This is a breaking change to the URI scheme; pre-1.0, draft SEP, no shims.
SEP: modelcontextprotocol/modelcontextprotocol#2640
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Update CLAUDE.md for SEP-2640 resource layer
Document the new URI shapes, the `extensions["io.modelcontextprotocol/skills"]`
capability, and the four SEP helpers in skill-discovery.ts. Note the explicit
`skill://index.json` update notification fired from `refreshSkills()`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Hey folks - we recently rolled out support for a bounded subset of this draft in ChatGPT’s plugin submission flow, and it’s now broadly available. Our current behavior is documented here. Sharing this mainly to open the conversation - we’d be happy to compare notes as the proposal evolves |
Co-authored-by: Den Delimarsky <53200638+localden@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
||
| This section sketches one way a host might wire MCP-served skills into an existing skills implementation. It is illustrative, not prescriptive — hosts are free to structure tools, naming, and routing however suits their architecture. The goal is that an MCP-served skill flows through the same loading and reading mechanics as a filesystem skill — while remaining origin-tagged, per [Security Implications](#security-implications). | ||
|
|
||
| **Registry.** At startup and on connection change, the host assembles a single internal skill registry from every origin it supports: filesystem skill directories, and `skills/list` results from each connected MCP server that declares the `io.modelcontextprotocol/skills` extension. Each registry entry records the skill's `name` and `description` (from the entry's `frontmatter`) and its origin — for a filesystem skill, the local directory; for an MCP skill, the server identity and the `SKILL.md` resource URI. Because names collide within and across origins ([Names](#names)), the registry keys entries by origin and name together, qualifying colliding names for display and invocation rather than dropping either entry. |
There was a problem hiding this comment.
This all makes sense, Caching becomes really important here to minimize startup costs, and etags can also help. I do think this will also cause folks to start asking for versions on Skills themselves to assist with not having to download these files every time, but outside the scope of MCP
There was a problem hiding this comment.
In think the etag adjacent work we are doing in transports should be broadly able to cover this.
The problem with versioning is perhaps that it is at least mildly in conflict with server deploy/versioning considering a key benefit of skills over MCP is that they can correctly reference the server they describe and be always up to date.
Then again if the broader concept of versioning arrives, skills being part of that makes complete sense.
## Summary #206 Adds a `tachyon-extensions` module implementing the MCP [SEP-2640](modelcontextprotocol/modelcontextprotocol#2640) **Agent Skills** extension: serve `SKILL.md`-based skills as `skill://` resources and answer `skills/list`, `skills/get`, and `resources/directory/read`. Also introduces a shared, classpath-driven `MimeTypes` table in `tachyon-core` and fixes Kotlin DSL builders to default `mimeType` from the resource URI/filename instead of `null`. ## What's new ### `SkillsExtension` (`tachyon-extensions`) - `SkillsExtension.builder().registry(...)` wires one or more `SkillsRegistry` sources (filesystem via `PathSkillsRegistry`, classpath via `ClasspathSkillsRegistry`, or a custom implementation) and registers every skill file as an extension-owned `skill://` resource. - Handlers: `skills/list` (no pagination — catalogs are bounded), `skills/get`, `resources/directory/read` (walks nested skill directories, including subdirectories inside a skill, not just skill roots). - `CompositeSkillsRegistry` merges multiple registries, rejecting duplicate skill paths instead of silently overwriting them. - `FrontmatterParser` parses the YAML frontmatter of `SKILL.md` using a `SafeConstructor`-based SnakeYAML loader (no arbitrary object instantiation), requiring non-blank `name`/`description`. - Filesystem-backed skill files are re-read from disk on demand rather than cached at scan time, so on-disk edits are reflected without a restart; classpath-backed files stay cached. - `docs/extensions/mcp-skills.md` documents the extension end to end (directory layout, registries, methods, SEP-2133 negotiation). ### `MimeTypes` (`tachyon-core`, new) - Classpath-bundled `mime-types.csv` drives filename → MIME type + a per-type `isText` flag, replacing ad hoc suffix checks (`.json`, `.yaml`, `.toml`, `.csv`, `.html`, images, etc. now resolve correctly instead of falling back to `application/octet-stream`/base64 blobs). - `MimeTypes.isText(mimeType)` consults the table first, falling back to a `text/` prefix check only for unknown types (e.g. caller-supplied overrides). - Kotlin DSL factories/builders (`Icon`, `TextResourceContents`, `BlobResourceContents`, `ResourceLink`, `ResourceDescriptor`, and their scope equivalents) now default `mimeType` to `MimeTypes.guess(uri)` instead of `null`, matching the Java builders. --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Proposal: a dependencies field for declaring a skill's tool prerequisitesHi all - wanted to add a comment (and suggestion) here related to the interrelatedness of skills and tools. Sometimes a skill doesn't require a skill (here's how to think about X), but more often than not, skills are put in place because they fit naturally on the interplay of tools themselves (you first fetch an order to then be able to know what to update the status to, etc). The real problem (from a production MCP server)We run an MCP server whose tools are often gated per-user and per-location: individual tools are enabled/disabled based on feature flags, product entitlements (ie are they paying for that product), and permissions. Two users connected to the same server see different tools/list results. Skills over MCP is exactly what we want for packaging our multi-step workflows — but as drafted, a skill is listed and loaded independent of whether the tools it orchestrates are actually available to that user. The failure mode kind of stinks: a user loads a "process a refund" skill, the agent reads the whole workflow into context, then hits an entitlement denial on the first tool call. It's wasted context, confusing dead-end - and as we've seen it happen, the llm will actually hallucinate that it can do something (often because the language of the skill describes a capability that the llm supposedly now has).
Proposed shapeA dependencies field in frontmatter, type-tagged, with all/any groups, with a concrete example:
The any group isn't hypothetical: versioned tool pairs are common (get_order/get_order_v2, and similar). A skill needs the capability, satisfiable by either version — any expresses that directly. I'd love if we could consider this - I was in an auth WG meeting last week and Max and team framed the concept well - is what we're sending over the wire optional or necessary for clients to implement to conformant. I think this is a necessary level of support to make skills truly effective at scale, in particular in any environment where tools/list is dependent on the caller's privileges. We know for a fact that if a skill is exposed to the llm but does not have the requisite tools, its a degraded experience full-stop and erodes trust in the product. |
|
I second this problem emphatically. This is something that I think skills have been materially lacking... but this unfortunately might not be the right surface to solve it. Changes to the frontmatter speak more broadly to the standard as a whole. I think skills over MCP gives some relief to the "batteries not included" problem. I've been searching for a method for a while to make an agent loop fail fast when it doesn't have access to a tool needed within a skill. We don't get import errors like we do when libraries are missing in the code, often your agent says "let me try this instead..." which is so much worse than failing completely. I'm very much in favor of the front matter changes proposed here but they probably need more broad adoption amongst clients and not just within MCP. For what its worth, you probably also need to provide server urls along with the tools as "get_orders" might be a tool present on multiple servers. You could validate exclusively against tools within the server where the skills is being served over MCP but then you have the limiting aspect of not using tools from other servers. "https://www.example.com/mcp:get_orders" might be a better convention for tools.
|
|
@jamespbrink yeah i'm literally drafting a similar comment up for agentskills repo as a proposal to your point about broader adoption. |
@danteoh-toast please reference this thread... I'd love to follow along with that. |
|
@jamespbrink posted here: agentskills/agentskills#485 |
dsp-ant
left a comment
There was a problem hiding this comment.
I have to comment iwth some old review comments since the diff renderer in Github now says the diff is too large and I can't add comments anymore.
| "description": "Extract, fill, and assemble PDF documents", | ||
| "metadata": { "version": "2.1.0" } | ||
| }, | ||
| "resources": [ |
There was a problem hiding this comment.
We are not suggesting any limitations . I assume that any client wants to limit the read on files like this. I wonder if we should suggest a limit, e.g. Client implementors SHOULD limit reads of individual files 1024kb and the amount of files to 256 when choosing limits. This way we encourage some form of consistency in the ecosystem and give a bit more predictability to server authors.
| { | ||
| "uri": "skill://pdf-processing/templates/regional/eu-invoice.md", | ||
| "digest": "sha256:c0d1e2f3..." | ||
| } |
There was a problem hiding this comment.
I am still not sure if we shouldn't include a size to limit the read.
| - When present, `resources` MUST be complete: it lists every file of the skill, each exactly once, including an entry matching the skill's top-level `uri` — that entry carries the digest of `SKILL.md` itself. | ||
| - Each `uri` MUST be the skill's `SKILL.md` or a file within the skill's directory. | ||
| - Completeness extends to nested skills: from the enclosing skill's perspective their files are supporting files ([Nested skills](#nested-skills)), so the enclosing skill's `resources` lists them too, and the same file may appear in both the enclosing and the nested skill's entries. A change to a nested skill is therefore a change to the enclosing skill's set. | ||
| - `resources` MAY be omitted only when a skill's content is generated dynamically, such that stable digests cannot be published. A skill without `resources` offers no content integrity and cannot be content-bound ([Security Implications](#security-implications)). Hosts MAY decline to load such skills, and server authors SHOULD expect that some hosts will. |
There was a problem hiding this comment.
I personally prefer to be somewhat explicit about these, e.g. either send resources: [...] or resources: "dynamic" or resources and dyanmicResources or something. This way, a few months down the line, a person or agent looking at the trace can easily understand the meaning without having to know from the spec what a missing resources means. The principle here is being self-documenting.
…e doc The full rationale text was migrated to the Working Group repository in modelcontextprotocol/experimental-ext-skills#121 (docs/rationale.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Credit for prompting skills/get and sustained design review. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: olaservo <olahungerford@gmail.com>
Extensions Track SEP defining the
skill://resource convention for serving Agent Skills over MCP. Developed by the Skills Over MCP Working Group; transports the design from experimental-ext-skills#69 with archive distribution per experimental-ext-skills#83.Extension identifier:
io.modelcontextprotocol/skills.Reference implementations: TypeScript SDK wrappers, host prototypes in gemini-cli/fast-agent/goose/codex/Claude Code, and the GitHub MCP Server.