Add experimental MCP skills extension support (SEP-2640)#207
Open
Add experimental MCP skills extension support (SEP-2640)#207
Conversation
Implements the experimental `io.modelcontextprotocol/skills` extension as sugar over the existing Resources primitive. Skills are markdown documents (SKILL.md + YAML frontmatter) served under `skill://` URIs, with optional discovery via `skill://index.json`. - `skills-list` reads the well-known index, falling back to scanning resources for `skill://*/SKILL.md` URIs (per spec, an absent index does not imply zero skills) - `skills-get <name>` reads the SKILL.md; `--raw` prints just the markdown for piping to LLMs or files - Session overview surfaces `skills` under capabilities when the server advertises `capabilities.extensions["io.modelcontextprotocol/skills"]` - JSON output is documented for both commands so AI agents can consume it
Coverage: - Unit: parseIndex (well-formed, malformed, drops bad entries, JSON errors), skillsFromResources (URI matching, nested paths, ignores non-skill-md files), resolveSkillUri (bare names, nested paths, full URIs, trailing slashes), extractTextContent, discoverSkills (index path, fallback path, paginated resource scan) - Unit: formatSkills (count, descriptions, types, empty state), formatSkillDetail (markdown body, missing MIME, blob fallback, truncation), formatServerDetails capability surfacing under both `capabilities.extensions` (per spec) and `capabilities.experimental` (SDK-preserved escape hatch) - Unit: parser suggests `skills-list` for `skills`/`list-skills` - E2E: opt-in `WITH_SKILLS=true` server flag exposes skill:// resources and advertises the extension capability. Three scenarios covered: index-path discovery, no-index fallback (`SKILLS_NO_INDEX=true`), and no-extension server. Verifies --json shapes, --raw mode, nested skill paths, full-URI input, and that --json+--raw still emits the full ReadResourceResult so `jq -r '.contents[0].text'` works. Implementation tweak: capability detection now also accepts `capabilities.experimental[skills]` since current MCP SDKs strip unknown capability fields like `extensions`. Test server advertises under both keys for forward compatibility. Internal helpers (parseIndex, skillsFromResources, extractTextContent, discoverSkills) are exported with `@internal` markers for testability.
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.
Summary
Implements support for the experimental MCP skills extension (
io.modelcontextprotocol/skills, SEP-2640), adding two new CLI commands (skills-listandskills-get) that provide sugar over the existing resources primitive for discovering and reading Agent Skills.Key Changes
New
skillscommand module (src/cli/commands/skills.ts):skill://index.jsonwith fallback to resource scanning forskill://*/SKILL.mdURIslistSkills(): Discovers and lists skills exposed by the servergetSkill(): Reads a skill's SKILL.md content by name or URIresolveSkillUri(): Converts user-friendly skill names to fullskill://URIsCLI integration (
src/cli/index.ts):skills-listcommand with discovery strategy documentationskills-get <name>command with--rawflag for markdown-only outputKNOWN_SESSION_COMMANDSOutput formatting (
src/cli/output.ts):formatSkills(): Renders skill list with names, descriptions, and typesformatSkillDetail(): Displays skill content with URI and MIME type metadataformatServerDetails()to advertise skills capability when server declares the extensionDocumentation:
--rawmodeImplementation Details
skill://index.jsonindex; if unavailable, falls back to scanning all resources forskill://**/SKILL.mdpatterns (per spec requirement to not treat absent index as proof of no skills)git-workflow), nested paths (acme/billing/refunds), and full URIs--rawflag enables piping skill markdown directly to other tools without formatting overheadhttps://claude.ai/code/session_01PyzCAbMiMXTbLrFXUP3nQJ