An open paper folio connected by red thread to folded blue paper pieces on an ivory field
All posts

MCP skills vs tools: what the Skills Extension (SEP-2640) adds

An MCP tool is an action; a skill is the procedure that says when and how to use it. SEP-2640 lets a server ship that procedure next to its tools while the host keeps the decision to load it, but few clients support it yet.

Take a finance MCP server with two tools, lookup_invoice and create_adjustment. The tools are enough for an agent to fix a disputed invoice, and they are also enough for it to issue a refund without looking at the purchase order. What the tools cannot carry is the procedure your finance team follows: pull the invoice and the PO, compare the disputed lines, record the evidence, and get a person to approve before any adjustment. That procedure is a skill.

Tools and skills sit at different layers. A tool is a callable action with a schema. A skill, in the Agent Skills format, is a SKILL.md with a name, a description and instructions, plus optional supporting files, that tells the model when and how to use the actions it has. Until recently the two travelled separately: the tools came from the MCP server, and the skill had to be copied into every host that used it, a .claude/skills/ folder here, a system prompt there. The MCP Skills Extension, SEP-2640, lets the server ship the procedure next to its tools.

The server publishes the procedure as resources

The extension does not add a new kind of content to MCP. It serves the skill through the Resources primitive the protocol already had. A server that declares resources and the optional io.modelcontextprotocol/skills capability must answer skills/list, which returns one entry per skill, and skills/get, which resolves a skill by URI even if it was not listed. Each entry carries the skill URI, its frontmatter (name and description included), and either a complete file manifest or the string "dynamic" for content without a fixed manifest. The extension specification defines delivery only; how to write the skill is still the Agent Skills spec.

For the invoice server, that means an invoice-dispute-review entry whose description tells the host when the workflow applies. The host can list it without downloading anything else. When a dispute arrives, it picks the entry, reads SKILL.md through resources/read, checks the bytes against the manifest, and fetches the review checklist only if the instructions call for it. The skill's identity is the server plus the URI, so two servers that both publish skill://invoice-dispute-review are publishing two different skills.

Reading a skill is not running it

This is the part of the extension I find most useful, and it is all about the host. Reading a resource shows the model what a file says. Activating a skill goes through the host's own skill-loading path and its approval rules, and the extension's user interaction model keeps the two apart; even reading a nested SKILL.md as supporting material does not activate the nested skill.

For a fixed manifest, every file has a byte size and a SHA-256 digest. While it acts on a skill, the host keeps the entry, reads only the URIs it lists, verifies the bytes before using them and checks that the frontmatter in SKILL.md matches what was advertised. An approval that the host stores binds to the full set of URIs and digests, so a server that changes one file loses the approval. A matching digest proves the content is what the server advertised, which is a different question from whether the instructions are safe to follow. Dynamic skills cannot carry a stored approval at all, and the host may refuse them.

The tool boundary survives too. The dispute skill can tell the model to call create_adjustment, but prose cannot grant tool permissions. Code execution and permissions such as allowed-tools need explicit approval from the host, reads stay tied to the server the skill came from, and a skill from one server cannot quietly cause reads from another without a per-call approval that names both servers.

Few hosts load skills from MCP servers yet

SEP-2640 is Final in the MCP Extensions Track. That does not make skills part of the core protocol: the current core specification lists Resources, Prompts and Tools as server features and treats extensions as optional additions that client and server negotiate. A host can support MCP tools completely and ignore skills.

Most of them do, for now. In the extension support matrix, the Skills column is marked supported for Glean, MCPJam and the mcpc CLI, and partial for ChatGPT, fast-agent and MCP Inspector. Claude Code, Claude Desktop, Cursor and VS Code GitHub Copilot have no mark for skills, although several of them have their own local skills. Claude Code, for example, loads SKILL.md folders from disk and keeps only each skill's description in context until it is invoked, which is the same idea delivered a different way. If your audience is mostly in those editors, publishing a skill from your server today reaches few of them, and the safe plan is to ship the tools and document the procedure where each host expects it.

How AIVAX handles skills from an MCP source

AIVAX has gateway skills of its own: the gateway puts each skill's name and description in front of the model, and the model calls read_skill to load the instructions when it decides it needs them. An MCP source attached to a gateway exposes the server's tools as functions, and by default it also imports skills from a server that negotiates the extension.

The support is narrow, and the docs call it a limited compatibility integration. AIVAX calls skills/list, reads only the root SKILL.md of each fixed-manifest entry, checks its size, digest and frontmatter against the entry, and skips dynamic skills, supporting files and skills/get. A mismatch fails discovery for that source instead of silently dropping the skill. Each imported skill gets a slug derived from the source and the URI, so it cannot overwrite an account skill or a skill from another server, and its frontmatter grants no tool permissions. Discovery also happens through initialize, so a server that advertises the extension only through the newer server/discover flow is not picked up; moving an MCP server to the stateless 2026-07-28 spec covers that transition.

The part to decide deliberately is approval. AIVAX downloads the SKILL.md at discovery, and an imported skill sits behind read_skill next to your own skills with no per-skill approval step: it reaches the model when the model asks for it, not when a person signs off. That fits a server you control. For anything else I would set allowRemoteSkills to false on the source and copy the skills you have reviewed into the gateway, the same way you would review a third-party server before connecting it to an agent. Skills also interact with context size: hiding tools and loading procedures on demand is covered in how to cut MCP tool-definition tokens.

AIVAX's own MCP servers do not publish skills through the extension. They expose tools only, and the closest thing is a convention: the Collections MCP used as agent memory stores files such as skills/auth.md that the agent finds by search, which is a document store, not SEP-2640. If I were building the invoice server today, I would still publish the dispute review as a skill rather than pack it into the create_adjustment description, because the extension lets the host approve the procedure separately from the tool.

Checked against the SEP-2640 page, the Skills Extension overview, the MCP extension support matrix, Claude Code's skills documentation and the AIVAX source and documentation on 10 November 2026. The AIVAX import path was verified in code and in its unit tests, not against a live third-party server.