MCP Servers Can Now Ship Their Own Manual

On September 13 the MCP maintainers merged SEP-2640, the Skills Extension, as Final. It lets a server hand an agent two things over one connection: the tools, and the skill that explains how to use them. Read it expecting a new primitive and you will be surprised by how little it adds on the wire: one URI convention, two required methods, one optional method. Most of the document is spent on something else. It is a careful answer to a hard question: what should a host believe about instructions that a remote server wrote?


The gap it closes

A skill, in the Agent Skills specification, is a directory with a SKILL.md at its root: YAML frontmatter with a name and a description, a Markdown body of instructions, and optional scripts/, references/, and assets/. Hosts load it in stages. The name and description, about 100 tokens, sit in context from startup. The body, which the spec recommends keeping under 5,000 tokens and 500 lines, loads when the agent decides the skill applies. Supporting files load only when a step needs them.

MCP had no standard way to ship any of that. The SEP's motivation section lists three problems. First, distribution was split: a server and the skill that teaches an agent to drive it were versioned, discovered, and installed separately, so a user installing a server from a registry had no signal that a companion skill existed. Second, the only built-in channel for guidance is the instructions field returned by server/discover, which is practically bounded in size. The SEP's example is an 875-line skill that does not fit there. Third, several projects had already invented their own skill:// URIs, each with different rules for what the host, path, and sub-resources meant.

If you read the post-stateless roadmap, you saw the catalog tax: every tool schema a server exposes costs context whether the agent uses it or not. Skills attack the other half of that cost. A tool schema says what a function accepts. A skill says when to call it, in what order, and what to do when it fails, and it can carry that knowledge without paying for all of it up front.

Resources, not a new primitive

The working group had a competing design on the table, SEP-2076, which made skills a first-class protocol primitive. The rationale document explains why it lost: a new primitive would flatten skills to "name-addressed blobs," losing the directory model that makes progressive disclosure work. Mapping skills onto the existing Resources primitive keeps the directory and inherits URI addressing, resources/read, subscriptions, and every client that already browses resources.

So each file in a skill directory becomes one resource, conventionally at skill://<skill-path>/<file-path>. The rules are precise and worth knowing:

Three methods, and a manifest in every listing

A server opts in through the extension negotiation defined by SEP-2133, by declaring io.modelcontextprotocol/skills in the extensions field of its capabilities. It must also declare the ordinary resources capability. Declaring the extension commits the server to two methods.

skills/list enumerates the skills the server serves. Each entry is a full manifest, not a summary: the skill's frontmatter copied verbatim as JSON, and a resources array listing every file in the skill with its SHA-256 digest and byte size. A host can build its whole registry, show the user what they are approving, and later verify every file it reads, all from one paged pass. On protocol 2026-07-28 and later, the result also carries the base protocol's ttlMs and cacheScope list-caching attributes. The listing may be empty or partial. A documentation server that synthesizes one skill per API endpoint, or a gateway fronting an external index, cannot enumerate everything, and hosts must not read an empty list as proof of no skills.

skills/get takes one SKILL.md URI and returns the same entry shape. It exists for two cases: refreshing a single skill's digests after a mismatch without re-listing the catalog, and verifying a skill whose URI arrived by some other route, such as the server's instructions, another skill, or the user. An unknown URI gets error -32602, the same code resources/read uses.

The third method is optional. resources/directory/read lists the direct children of a directory resource, for instructions like "pick the right template from templates/". It is gated behind a directoryRead: true setting on the capability, and clients must not call it otherwise. Everything else rides on resources/read. The SEP also fixes two per-skill limits that every conforming host must accept: 512 files and 16 MiB in total, both checkable from the manifest before a single byte of content moves.

Fig. 1 · the wire, message by message

The agent's task: fill the EU invoice template from the pdf-processing skill. Flip what the server declares and how complete its listing is, and the transcript rebuilds itself. File names and byte sizes are the SEP's own example catalog.

extension
directoryRead
listing

    Sizes are raw file bytes from the SEP-2640 skills/list example (catalog of 3 skills, 9 files, 38,866 bytes). JSON-RPC envelopes are not counted. "Verified" means the bytes were checked against a digest the host already held.

    Two things in that transcript are easy to miss. Without the extension, the skill is still readable: a URI in the server's instructions is enough for resources/read to return the bytes. What the host loses is everything around the bytes, the digest to check them against, the frontmatter to show the user, and any way to tell a skill from an ordinary Markdown resource. And the partial listing costs exactly one extra round trip, because skills/get turns a URI the host was handed into the same manifest a listing would have carried.

    Progressive disclosure, stretched over a network

    On a local filesystem, progressive disclosure is a context budget. Over MCP it becomes a network budget too, and the SEP writes that down as a rule: hosts must not retrieve a skill's files ahead of need, whether on connection, on listing, or at approval. A SKILL.md is fetched when the skill is loaded. A supporting file is fetched when it is read. The stated reason is load. A server may publish many skills with many files, and a host that downloaded everything on connect would put load on the server in proportion to the catalog rather than to use.

    The digests make the laziness cheap. A host should cache what it does fetch, and a cached file whose digest still matches the current manifest can be served without another request. A mismatch forces a fresh fetch. The same property explains why the maintainers cut the archive form from an earlier draft. Shipping a whole skill as a tarball would have saved round trips, but safely unpacking a server-supplied archive means defending against decompression bombs, path traversal, symlinks escaping the directory, Unicode collisions that overwrite SKILL.md, and setuid bits. With lazy retrieval, the round trips you pay scale with the files a session actually opens, which the SEP judged the better trade.

    Fig. 2 · disclosure tiers across a task

    Rows are the SEP's three example skills plus copies from other servers you connect. Columns are the three Agent Skills tiers. Scrub the task forward and watch which cells turn on. The verdict compares the lazy session with a host that loads every body and file up front.

    4

    Tier 1 is about 100 tokens per skill (Agent Skills spec). Body and file tokens use the SEP example byte sizes at an assumed 4 bytes per token, a rough heuristic for English Markdown. Extra servers are modeled as copies of the same 3-skill catalog.

    The ratio in that verdict is the argument for the whole design. The first tier grows with the number of skills you have connected. The second and third tiers grow only with the work. An agent connected to a dozen servers pays for a dozen short descriptions, not a dozen manuals.

    Most of the spec is a threat model

    Here is the part that justifies the SEP's length. A tool call runs on the server. A skill runs on the host: it is server-authored text placed straight into the model's context, and it can tell the model to execute a bundled script with the host's own shell. The SEP says so directly, and requires hosts to treat MCP-served skills as a higher-risk surface than remote tool invocation. The rules that follow are specific:

    The rule I expect to matter most is content-bound approval. When a host persists a user's approval, it must bind it to the whole resources set observed at that moment, every URI and every digest. Per-file digests exist because an earlier draft carried one digest per skill, and the rationale spells out the attack that left open: get approval for a benign skill, then rotate references/GUIDE.md. With the full set bound, any rotated, added, or removed file revokes the approval, and a file read while the host is acting on the skill fails verification if it no longer matches.

    Fig. 3 · manifest tamper bench

    The user approved pdf-processing against the manifest below. Now play the server, or the network in between. Each move changes what the server serves, and the host applies the SEP's rules to decide what happens next.

    Manifest from the SEP-2640 example, digests shortened. Verdicts follow the Integrity and Security Implications sections: digest mismatch, unlisted read, frontmatter mismatch, content-bound approval, allowed-tools, and "digests are not a security boundary."

    The last move on that bench is the honest one, and the SEP is honest about it too. Digests are unsigned and come from the same server as the content. They prove the listing and the bytes agree. They cannot prove either is safe, and an intermediary that rewrites both passes every check. Approval-time trust still rests on the user reading what they approve, which is why the SEP asks hosts to let users inspect a skill before it loads and to show provenance everywhere. Caching gets the same treatment: a host must either keep cached skills where nothing but the host can write, or rehash the bytes on every access, and cached content never graduates to local-skill trust by sitting on disk.

    Who has built it

    An Extensions Track SEP needs a reference implementation in an official SDK before review, and this one lists three: Python, C#, and Go. The conformance scenarios for enumeration, manifests, and directory reads merged on September 11, two days before the SEP itself. On the host side the SEP cites prototypes in forks of gemini-cli and Codex, in fast-agent, and inside Anthropic for Claude Code, which it notes is not yet public. On the server side there is a GitHub MCP Server prototype. The authors are Peter Alexander of Anthropic, Ola Hungerford, Sambhav Kothari, and Aditya Kumar, writing for the Skills Over MCP Working Group, and the design history lives in the ext-skills repository.

    One migration is already called out by name. FastMCP's widely used SkillsProvider serves skills with a different URI structure, a per-skill manifest resource instead of a central listing, and different metadata mapping. The SEP calls these mechanical changes, and coordinating them is a stated near-term priority for the working group. If your server uses it, expect your skill URIs to change.

    The division of labor is the durable result. The Agent Skills specification owns the content format, and the SEP delegates to it completely, including future revisions. MCP owns transport, discovery, and verification. Neither project had to win.

    What to do with it

    If you maintain an MCP server with a nontrivial workflow, the ask is small:

    If you build a host, the checklist is longer and every item is a MUST: key everything on server plus URI, fetch on demand, verify every read against the held manifest, tag origin in context, ignore allowed-tools from remote skills, bind approval to the full digest set, and keep the cache where nothing else can write. The implementation guidelines sketch a single read_skill tool keyed by server and URI that does all of this, and a read_resource tool for supporting files, and the stateless revision it sits on means none of it needs a session.

    The Skills Extension is small on the wire because resources already did most of the work. It is long on paper because it takes seriously the idea that a server's manual is code the host may run. Both are the right size.

    rg
    Rohit Ghumare

    CNCF Ambassador and Google Developer Expert. I build agent infrastructure and write about the fundamentals underneath the AI stack. Every protocol detail here comes from the SEP-2640 text as published on modelcontextprotocol.io, its rationale document, and the Agent Skills specification, read on September 14, 2026. Merge dates are from the GitHub pull requests. The SEP is a historical record once Final, so check the current specification before you implement.

    Related: Stateless MCP · MCP's New Roadmap · More posts · X