Support the Skills extension (SEP-2640)
メンテナーはふだん 3 日以内に返信
評価
この issue はまだ評価されていません。
説明
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.
- 主要言語
- Rust
- スター
- 4.1k
- フォーク
- 680
- 平均マージ
- 4日 1時間
- マージ済み PR(30日)
- 35
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
modelcontextprotocol/rust-sdk のほかの issue
-
auth: refresh_token() requests offline_access that was never granted, so refreshes fail with invalid_scope対応中かも @jstar0 が 19 日前に担当しました。 オープンbug P1 ready for work T-security T-transport
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
modelcontextprotocol/rust-sdk#1330 ·
メンテナーはふだん 3 日以内に返信
-
stdio transport: a request over the maximum line length gets no answer対応中かも @gocamille が 1 日前に担当しました。 オープンbug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1395 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 3 日以内に返信
-
docs: ClientHandler list_changed callbacks don't mention Peer::listen (2026-07-28)対応中かも @DaleSeo が 3 日前に担当しました。 オープンenhancement P2 ready for work T-documentation
modelcontextprotocol/rust-sdk#1394 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 3 日以内に返信
-
reqwest Streamable HTTP client matches response Content-Type by case-sensitive prefix対応中かも @DaleSeo が 4 日前に担当しました。 オープンbug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1389 · コメント 2 件 · 担当者 1 名 ·
メンテナーはふだん 3 日以内に返信
-
Streamable HTTP server: Accept and Content-Type are matched case-sensitively and by substring/prefix対応中かも @DaleSeo が 7 日前に担当しました。 オープンbug P1 ready for work T-transport
modelcontextprotocol/rust-sdk#1381 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 3 日以内に返信
modelcontextprotocol/rust-sdk の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
plrigaux/sysd-manager#85 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
dsx-ai-factory/infra-controller#8341 ·
メンテナーはふだん 1 日以内に返信
-
enhancement triage:deciding
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
open-telemetry/otel-arrow#4540 ·
メンテナーはふだん 2 日以内に返信
-
benchmark: CSV report files contain blank records on Windows対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンcomponent:benchmark
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
agentic-os-org/ANOLISA#9177 ·
メンテナーはふだん 1 日以内に返信
-
area/mcp area/modeling effort/s impact/few priority/p3 severity/low triaged type/bug urgency/this-quarter
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
cristim/AztecCraft#336 ·
メンテナーはふだん 1 日以内に返信