MCP Skills
mcp-devtools can publish curated workflows as
Agent Skills through the MCP Skills
extension (io.modelcontextprotocol/skills), conforming to the released specification at ext-skills revision
ff22433.
The extension’s lifecycle stage is Beta (SEP-3392), so a later revision
may make breaking changes; each adoption is reviewed in the ADR.
The design record is ADR: MCP Skills extension.
Enabling
Section titled “Enabling”Set MCP_SKILLS_ENABLED=true (see configuration),
or toggle it in the admin console.
The setting is off by default, accepts exactly true or false, and is
read per request: a configuration reload that turns it off also refuses
reads that follow earlier discovery. A malformed value refuses startup.
When on, a 2026-07-28 client sees, in server/discover:
{"capabilities": {"resources": {}, "extensions": {"io.modelcontextprotocol/skills": {}}}}directoryRead is not offered and resources/directory/read is not
implemented; every skill carries a complete manifest instead.
Compatibility
Section titled “Compatibility”| Client | Behavior |
|---|---|
| Skills-aware, protocol 2026-07-28 or later | skills/list, skills/get, resources/list, resources/read. |
| Extension-unaware, 2026-07-28 or later | Skill files are ordinary resources in resources/list and resources/read. |
initialize session on an older protocol |
Unchanged: no resources capability, empty resources/list, -32601 for resources/read and skills/*. A single request may opt into 2026-07-28 with its own _meta. |
| Any client, feature off | Unchanged, as above. |
Over HTTP every request still needs a valid bearer token; the client’s
_meta (clientInfo, capabilities) is never treated as identity. Over
stdio the local identity applies, as it does for tools.
What is served
Section titled “What is served”| Skill | Files | Tools it calls |
|---|---|---|
skill://github-pr-readiness/SKILL.md |
SKILL.md, references/review-checklist.md |
github_get_pull_request, github_get_pull_request_diff, github_list_workflow_runs, github_list_workflow_jobs |
github-pr-readiness assesses whether a pull request is ready to merge: it
reads the pull request, its changed files (bounded pagination, explicit
reporting of missing patches and incomplete coverage) and the CI runs and
jobs for the pull request’s current head.sha (runs for other commits are
stale and never count as passing), then produces a readiness report with
evidence links. It is read-only and never approves, merges, comments or
re-runs anything. It treats pull request text and diff content as untrusted.
A skill is visible to a session only when every tool it calls is on that
session’s tool surface; with GitHub not enabled (MCP_ENABLED_VENDORS),
github-pr-readiness is absent from listings and unknown by URI.
Publication model and provenance
Section titled “Publication model and provenance”- Embedded only. Skills are repository files under
skills/, listed in an explicit allowlist insrc/skills/mod.rsand compiled into the binary. The server never scans the workspace or an operator directory, and never fetches skills remotely. There is no install, upload or execution path. - Immutable per build. Content and SHA-256 digests change only with a release. Every skill is shared product content: identical for every authorized principal and tenant, with no credentials, configuration or vendor data interpolated.
- Provenance. Each
SKILL.mdfrontmatter names its publisher (metadata.publisher: mcp-server-devtools) and distribution, and its body opens with a statement of origin and limits. Supporting files are described inresources/listas bundled with mcp-devtools. - Reviewed content. Adding or changing a skill is a code change: the
files, the allowlist entry, and
tests/skills_packaging_tests.rs, which keeps the allowlist andskills/identical, refuses symlinks, and scans for secret-shaped content.
Bounds
Section titled “Bounds”| Bound | Value |
|---|---|
| Resource URI | 1024 bytes, at most 16 /-separated segments of 1–128 bytes [A-Za-z0-9._-], no leading . |
| Cursor | 2051 bytes |
| Files per skill | 512 (specification limit) |
| Bytes per skill | 16 MiB (specification limit) |
| Bytes per file | 1 MiB |
| Frontmatter | 16 KiB; fields name, description, license, compatibility, metadata only |
| Skills per catalog | 256; 32 MiB in total |
| Page size | 32 skills per skills/list page, 128 files per resources/list page |
| Media types | .md → text/markdown, .txt → text/plain, .json → application/json |
Malformed URIs (traversal, percent-encoding, dotfiles, other schemes,
userinfo, ports, queries, fragments, over-long input) and unknown files are
refused with -32602 without touching a filesystem or network. A malformed
cursor is -32602. Results carry ttlMs: 60000 and cacheScope: "private".
Server enforcement versus client responsibility
Section titled “Server enforcement versus client responsibility”The server enforces: the opt-in, protocol gating, authentication and session ownership, tool-scoped visibility, exact bounded lookups, bounded validated content, and normal admission, credential selection, policy and approvals for every tool call made while following a skill. Reading or activating a skill grants no permission on this server.
The host (client) is responsible, per the specification’s security considerations, for:
- Activation and consent. Loading a skill only through its skill-loading
path, with the user’s approval; a
resources/readalone is not activation. - Origin binding. Tagging skill content with this server’s identity, never letting it shadow a same-named skill from another origin, and never letting it drive reads against another server.
- Integrity verification. Checking each file’s size and digest against the held manifest and the frontmatter against the entry, and re-prompting when a manifest changes. Digests show the content is what the server described; they are unsigned and do not establish trust.
- No implicit permissions or execution. This server ships no
allowed-toolsor scripts; hosts must still not honor permission-widening frontmatter from any MCP server.
Interoperability
Section titled “Interoperability”Automated wire coverage (tests/skills_wire_tests.rs) exercises stdio and
authenticated HTTP with raw JSON-RPC. That is not a client interoperability
walkthrough.
| Client | Version | Discovery | skills/list / skills/get |
Reads | Workflow | Status |
|---|---|---|---|---|---|---|
MCP Inspector CLI (official) |
2.13.0 | Pass (--protocol-era modern and auto) |
Pass: --verify on both reports 1 skill, 2 files, digests and sizes match, no conformance or frontmatter findings |
Pass: both files over resources/read, bytes identical to the repository |
Partial: the four workflow tools are listed; not executed | Verified over stdio, 2026-10-29, spec @ff22433 |
Walkthrough, 2026-10-29, macOS, stdio, debug build of this branch, with
MCP_ENABLED_VENDORS=github, MCP_SKILLS_ENABLED=true and an empty HOME
(no operator configuration or credentials):
mcp-inspector --cli --protocol-era modern … --method skills/list --verify→ exit 0, “Verified 1 skill and 2 files: no conformance errors.”; the same with--protocol-era auto.--method skills/get --uri skill://github-pr-readiness/SKILL.md --verify→ exit 0, both filesverified.--method resources/list→ both files,text/markdown.--method resources/readon the checklist → bytes identical toskills/github-pr-readiness/references/review-checklist.md.--method resources/read --uri 'skill://github-pr-readiness/../../etc/passwd'→ refused, “Malformed skill URI”.- With
MCP_SKILLS_ENABLED=false,skills/list --verify→ the Inspector reportsskills_unsupported: the extension is not declared. --method tools/list→github_get_pull_request,github_get_pull_request_diff,github_list_workflow_runsandgithub_list_workflow_jobsare all present, so the skill is visible.
Deviations and limits:
- The Inspector’s default
--protocol-era legacyconnects withinitializeand reportsskills_unsupported. That is the documented behavior for pre-2026-07-28 sessions (see Compatibility above), not a defect; a Skills client must negotiate 2026-07-28. - The Inspector’s
resources/listoutput shows onlyresources. A raw 2026-07-28 request to the same binary returnsresultType: complete,ttlMs: 60000andcacheScope: private, asskills_wire_testsasserts. - Authenticated HTTP was not exercised with a client; it is covered only by
skills_wire_tests::http_*. - The workflow was not run end to end: that needs an agent host following the skill and a GitHub token. Its tool calls are ordinary tool calls under normal admission and policy.
Record further walkthroughs (an agent host, HTTP) as new rows, keeping them distinct from the automated evidence.