Support the Skills extension (SEP-2640)
Les mainteneurs répondent en général sous 3 jours
Évaluation
Cette issue n'a pas encore été évaluée.
Description
Summary
Add support for the Skills extension (SEP-2640, io.modelcontextprotocol/skills) to rmcp. The extension adds three methods: skills/list, skills/get, and the optional resources/directory/read. This issue covers both the server side and the client side.
- Spec: https://github.com/modelcontextprotocol/ext-skills/blob/main/specification/stable/skills.mdx
- Extension tracking issue: modelcontextprotocol/ext-skills#155
- Downstream: aaif-goose/goose#12068 needs the client side.
Requirements
A server built with rmcp can:
- Declare the extension in
capabilities.extensions, withdirectoryReadonly when it servesresources/directory/read. - Answer
skills/listandskills/getwith typed results, andresources/directory/readwhen declared. - Serve the files of a skill through
resources/read, so that the bytes match the size and digest in the manifest. - Return the error codes that the spec defines:
-32601for a method it does not serve,-32602for an unknown skill or a non-directory URI. - Send
ttlMsandcacheScopeto peers on protocol version 2026-07-28.
A client built with rmcp can:
- Detect the extension and its
directoryReadsetting from the server capabilities. - Call the three methods through typed
Peermethods, and receive server errors unchanged. - Verify a fetched file against the size and digest in the manifest.
Both sides pass the sep-2640-* conformance scenarios.
The spec targets protocol revision 2026-07-28 or later. rmcp also serves the methods to peers on an older revision and removes the cache hints from those responses, the same as the TypeScript, Python, and Go SDKs do. This needs the legacy strip helper to clear ttlMs and cacheScope as well as resultType, which also closes the same gap for the existing list results.
Proposal
This is how I plan to design and implement it. The choices below are open for discussion.
PR 1: protocol surface
Everything the spec defines, wired the same way as the tasks extension and without a feature flag.
- Model types for the skill manifest and the three methods in
model/skill.rs, with the matchingClientRequestandServerResultvariants.ReadResourceDirectoryResultis a type alias forListResourcesResult, andServerResultreuses the existingListResourcesResultvariant for it. No new directory variant: the two schemas are identical and the untaggedServerResultcannot tell them apart (see #771). - Three
ServerHandlermethods with capability-gated dispatch. Dispatch checks what the result object alone can show: the skill URI matches the request, the name matches the last URI segment, the manifest containsSKILL.mdand no duplicate URIs, and every digest has thesha256:form. A result that fails these checks returns-32603. Whether the bytes behind each URI match the manifest is checked by the catalog (PR 2) and by the host that reads them, not by dispatch. enable_skills()andenable_skills_with_directory_read()on the capability builder, with the matchingsupports_*getters. Whether the builder rejects skills withoutresourcesor only documents it is open.- The matching
Peermethods for the client. They accept a 2026-07-28 response that omits the cache hints, the same aslist_toolsdoes today; the TypeScript and Go clients reject such a response, rmcp does not.SkillResource::verify(&[u8])checks the size and thesha256:digest of one file. Frontmatter verification againstskills/getis left to the host.sha2becomes a regular dependency of rmcp: it is pure Rust, already in the tree forrequest-state, and a client must not have to enable a filesystem feature to verify a download. - Integration tests through
Peerover a real transport: pagination acrossskills/list, a-32602fromskills/getarriving unchanged,read_resource_directorynot sent whendirectoryReadis absent, the directory result arriving asListResourcesResult, andverifyfailing on a wrong size and on a wrong digest. - Conformance fixtures with a nested skill, a subdirectory, and a
"dynamic"skill, and the scenarios inconformance.yml.
PR 2: filesystem catalog
Behind a skills-fs feature. SkillCatalog::from_dir walks a directory tree and builds the manifests.
- The catalog is a snapshot. It holds the file bytes and their digests, so
resources/readserves the same bytes that the manifest describes, even if the files change on disk later. reload()builds a new snapshot and swaps it in. If the rebuild fails, the old snapshot stays.- The walk rejects paths that leave the root, including through symlinks, and validates that each skill name matches its directory name. It warns at 512 files or 16 MiB.
- A nested skill appears in the listing on its own, and its files also appear in the manifest of the parent skill.
Follow-ups, not blocking
- PR 1 adds the two new results to the hand-written lists in
strip_result_type_for_legacy_peerandfill_missing_cache_hints. A non-breaking refactor right after PR 1 replaces both lists with a trait on each cacheable result and a dispatch thatts_union!generates, since the macro already enumerates everyServerResultvariant. - A
ResultEnvelope { result_type, meta, ttl_ms, cache_scope }flattened into each cacheable result, with the result structs marked#[non_exhaustive], so that the next mixin field from the spec is not a major release. Breaking, so it waits for the next major batch. - An
Extensiontrait for declaring and reading extension capabilities, so that each extension adds one impl instead of four functions. Skills and tasks move onto it. Non-breaking.
Acceptance
- The
sep-2640-*conformance checks pass on the fixture server. The PR body lists the numbers. - Goose can list, fetch, and verify remote skills through
Peerwithout custom requests. - For PR 2: a file served through
resources/readalways matches the manifest, a path outside the root is never served, and the files of a nested skill are listed in both manifests.
- Langage dominant
- Rust
- Étoiles
- 4.1k
- Forks
- 680
- Merge moyen
- 4 j 1 h
- PR mergées (30 j)
- 35
Préparer son environnement
Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de modelcontextprotocol/rust-sdk
-
auth: refresh_token() requests offline_access that was never granted, so refreshes fail with invalid_scopePeut-être pris @jstar0 l’a pris il y a 18 jours. Ouvertebug P1 ready for work T-security T-transport
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
modelcontextprotocol/rust-sdk#1330 ·
Les mainteneurs répondent en général sous 3 jours
-
stdio transport: a request over the maximum line length gets no answerPeut-être pris @gocamille l’a pris aujourd’hui. Ouvertebug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1395 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 3 jours
-
docs: ClientHandler list_changed callbacks don't mention Peer::listen (2026-07-28)Peut-être pris @DaleSeo l’a pris il y a 3 jours. Ouverteenhancement P2 ready for work T-documentation
modelcontextprotocol/rust-sdk#1394 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 3 jours
-
reqwest Streamable HTTP client matches response Content-Type by case-sensitive prefixPeut-être pris @DaleSeo l’a pris il y a 4 jours. Ouvertebug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1389 · 2 commentaires · 1 personne assignée ·
Les mainteneurs répondent en général sous 3 jours
-
Streamable HTTP server: Accept and Content-Type are matched case-sensitively and by substring/prefixPeut-être pris @DaleSeo l’a pris il y a 6 jours. Ouvertebug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1381 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 3 jours
Toutes les issues de modelcontextprotocol/rust-sdk
Issues similaires
-
QuartoHub: have the Document name before the filename in the browser tabPeut-être pris @cscheid l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
quarto-dev/q2#930 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
muse P3
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
HerringtonDarkholme/hd-lang#923 · 1 commentaire ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
longbridge/gpui-kit#3712 ·
Les mainteneurs répondent en général sous 1 jour
-
documentation enhancement SIEM
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
ADORSYS-GIS/wazuh-agent-status#265 ·
Les mainteneurs répondent en général sous 2 jours