skills: add SEP-2640 protocol support - #1
Open
vijaydeepsinha wants to merge 6 commits into
Open
Conversation
Wire types, request/result models, and SEP-2640 conformance validation (name/URI/frontmatter rules, resource-manifest completeness, digest and size verification) for the Skills extension, shared by the server and client surfaces. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Skills extension (io.modelcontextprotocol/skills): serves skills/list, skills/get, and the optional resources/directory/read behind the directoryRead capability setting. Handlers are supplied by the server author; the extension validates results against SEP-2640 before they reach the wire and gates the SEP-2549 ttlMs/cacheScope fields to protocol version 2026-07-28+. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Thin client wrappers for skills/list, skills/get, resources/directory/read, and resources/read: list_skills and read_directory follow nextCursor to completion, all four validate the server's response before returning it, and verify_skill_resource checks a read's bytes against a held skill's manifest entry. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the Skills page under Advanced, with a runnable server/client example, and tests proving every claim the page makes against the real SDK. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Parametrize the digest-format rejection test over near-miss cases (uppercase, wrong length, missing/wrong prefix), and add explicit JSON round-trip tests for both shapes of the resources union type (a static array and the "dynamic" marker) to prove neither collapses or mistags on the wire. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_resource_uri_in_skill reads like a boolean predicate but returns None and raises; rename to _validate_resource_uri_in_skill to match its sibling validators (validate_skill, validate_list_result, validate_directory_result) and signal that it asserts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #
Summary
Adds Python SDK support for SEP-2640 (Skills Extension):
skills/list,skills/get, andresources/directory/readas protocol primitives, SEP-2640 conformance validation, and capability negotiation. This SDK does not provide filesystem discovery, catalog indexing, or caching/refresh policy — those belong to a higher-level provider built on top of this.Motivation and Context
SEP-2640 defines a convention for serving Agent Skills over MCP using the Resources primitive. The Python SDK has no support for it today. This PR adds the extension using the SDK's existing
Extension/MethodBindingmechanism (the same one backing the shippedAppsextension, SEP-2133) — no schema or codegen changes, no new required dependencies.What's included
src/mcp/shared/skills.py— wire types (Skill,SkillResource, params/results), SEP-2640 conformance validation (name/URI/frontmatter consistency, digest format, resource-manifest completeness, the 512-entry/16 MiB limits), andverify_skill_resource(digest+size integrity check for content already read).src/mcp/server/skills.py— theSkillsextension: handler-based (list_skills,get_skill, optionalread_directory), validates results against SEP-2640 before they hit the wire, gates the SEP-2549ttlMs/cacheScopefields to protocol version 2026-07-28+.src/mcp/client/skills.py—list_skills/get_skill/read_directory(auto-paginating, with cursor-repeat detection),read_skill_uri(a thin, discoverableresources/readalias),verify_skill_resourcere-exported for client use.docs/advanced/skills.md+docs_src/skills/— a new doc page with a runnable example, explicitly scoping what the SDK does and doesn't do.Server usage
Client usage
Protocol version / compatibility notes
capabilities.extensions(SEP-2133) andttlMs/cacheScope(SEP-2549) are 2026-07-28+-only wire fields in this SDK's existing type surface — this is pre-existing, documented SDK behavior (docs/advanced/extensions.md), not something this PR changes.Skillsgates its own cache fields to match.-32602error returns HTTP 200 on the classic (pre-2026-07-28) wire and HTTP 400 on the modern (2026-07-28+) wire. This is existing, spec-mandated (SEP-2575) SDK-wide transport behavior — every handler in the SDK gets it automatically via the sharedERROR_CODE_HTTP_STATUStable; nothing Skills-specific.mkdocs.yml(one nav entry).How Has This Been Tested?
tests/{shared,server,client,docs_src}/test_skills.py— 100% line+branch coverage on all three new modules (shared/skills.py,server/skills.py,client/skills.py), verified viacoverage report --fail-under=0../scripts/test→ 6000+ passed, 0 failed, 100% total coverage,strict-no-coverclean.ruff format/ruff check,pyright,markdownlint,mkdocs build --strict(Zensical), README-snippet check: all clean.uv run --python 3.10 pytest tests/*/test_skills.pypasses.Conformance
Ran the modelcontextprotocol/conformance PR #330 SEP-2640 scenarios end-to-end against a real server and client built on this implementation (server scenarios exercise this PR's server; client scenarios exercise this PR's client against a hostile server the harness stands up):
sep-2640-skills-enumeration(skills/list+skills/get)sep-2640-skills-manifest(SKILL.mdresource metadata)sep-2640-skills-directory(resources/directory/read)sep-2640-client-no-prefetchsep-2640-client-verify-digestsep-2640-client-verify-sizesep-2640-client-verify-frontmattersep-2640-client-verify-unlisted43 wire checks + 5 client checks, 0 failures, 0 warnings.
Also manually verified via a live server against a Postman collection covering both the session-based (2025-11-25) and stateless (2026-07-28) wires.
Breaking Changes
None. New files only; no existing public API is modified.
Deliberate scope exclusions (and why)
Skills,list_skills, andget_skill.SKILL.md's YAML frontmatter and compare it field-by-field against the held entry. This SDK does not ship that comparison, to avoid adding a new required YAML dependency to the core SDK for a check any host already has the means to do with whatever YAML library it uses elsewhere.verify_skill_resourcecovers the digest/size half (no new dependency needed for that). Documented explicitly indocs/advanced/skills.md's "What this SDK doesn't do".mcp-typesinstead ofmcp.shared:mcp-typesis generated from the official, versioned MCP JSON Schema; SEP-2640 is an extension, not core spec vocabulary, so its types are hand-written and live alongside the extension code — the same placement the existingAppsextension (SEP-2133) uses.Types of changes
Checklist
help wanted, or I'm a maintainer) — N/A while targeting my own fork; will file/link before retargeting to upstreamAdditional context
Implemented with AI assistance (Claude Code / Claude Sonnet 5) — commits carry
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>. I've reviewed the implementation, reasoning, and conformance results directly and can walk through any part of it.