Skills — minimal (SEP-2640)

The scoped-down core skills shape: a skills file served as skill:// resources. Experimental.

examples/skills-core

⚠ Experimental - the minimal SEP-2640 (Skills) shape, a draft SEP. Wire format may change.

The minimal SEP-2640 shape: a skills file served over MCP’s Resources
primitive, plus tool handling, consumed load-on-demand. This is the
scoped-down core the Skills Over MCP Working Group blessed at its
2026-06-30 meeting (discussion 2994).

If you want the full surface, meaning archives (.tar.gz / .zip), remote source
adapters (GitHub, archive directories, multi-source mounts), and
fsnotify-driven index invalidation, see examples/skills. Those
are the deferred / extended features and are deliberately left out here.

What this shows

  1. resources/list - every file under a skill directory is a skill:// resource.
  2. skill://index.json - the discovery catalog, generated from the live provider (never on disk), each entry carrying a SHA-256 digest.
  3. Read a SKILL.md. A skill is data: YAML frontmatter (name, description) plus a markdown body of instructions. mcpkit delivers it over resources/read; it is never staged to disk and never executed.
  4. Tool handling - the bundled commit-helper skill instructs the host to call the format_commit tool. The walkthrough reads the skill, then calls the tool. Skills make ordinary tools easier to use well.

Run it

Terminal 1:  just serve   # skills-core server, file mode, :8080
Terminal 2:  just demo    # this walkthrough (interactive TUI)

Or drive it non-interactively:

just serve            # in one terminal
go run . --non-interactive

Wire mode: mcpkit’s server defaults to dual-wire (SEP-2575). The first step
lets you pick adaptive (probe server/discover, fall back to initialize),
stateless, or legacy; the rest of the walkthrough is identical either way.

The skill

skills/commit-helper/SKILL.md describes a task and points the host at a
tool:

---
name: commit-helper
description: Turn a change description into a Conventional Commits subject line using the format_commit tool
---
...call the `format_commit` tool with type / scope / summary...

The server registers format_commit alongside the skill provider
(main.go). That pairing of a skills file plus the tool it references is the
minimal shape in one example.

Safety posture

ext/skills treats a skill as data delivered over resource primitives, never
as code to run: it does not import os/exec and never writes skill content to
disk. That invariant is enforced by TestNoCodeExecutionSurface in the
ext/skills package.

See WALKTHROUGH.md for the generated step-by-step (run
just readme to regenerate).

Next steps


Walkthrough

MCP Skills, the minimal shape (SEP-2640, scoped down)

The minimal SEP-2640 shape the WG blessed on 2026-06-30: a skills file served over MCP’s Resources primitive plus tool handling, consumed load-on-demand. No archives, no remote sources, no fsnotify. Those are the deferred / extended surface (see examples/skills for the full walkthrough).

What you’ll learn

  • Choose the client wire mode - mcpkit’s server defaults to dual-wire (SEP-2575): one URL answers both the legacy initialize handshake and the server/discover probe. The rest of the walkthrough is identical either way.
  • Read skill://index.json, the discovery catalog - mcpkit generates index.json from the live provider catalog on each cache miss, so it is not a file on disk. Each entry carries a SHA-256 digest over the skill’s SKILL.md.
  • Read the commit-helper SKILL.md, the skill file - A skill is data: markdown with YAML frontmatter. Its body tells the host which tool to call and how. mcpkit delivers it over resources/read, never staged to disk and never executed.
  • Tool handling, calling the tool the skill points at - This is the ’tool handling’ half of the minimal shape. The skill guided the host to format_commit; the host calls it and returns the result. Skills make ordinary tools easier to use well, the pattern Paul Withers raised in-channel on 2026-07-01.

Flow

sequenceDiagram
    participant Host as MCP Host (this client)
    participant Server as MCP Server (just serve)

    Note over Host,Server: Step 1: Choose the client wire mode

    Note over Host,Server: Step 2: Connect to the skills server
    Host->>Server: server/discover (stateless) OR initialize (legacy)
    Server-->>Host: serverInfo + capabilities.extensions.skills

    Note over Host,Server: Step 3: resources/list, where each skill file is a skill:// resource
    Host->>Server: resources/list
    Server-->>Host: [ skill://index.json, skill://commit-helper/SKILL.md ]

    Note over Host,Server: Step 4: Read skill://index.json, the discovery catalog
    Host->>Server: resources/read uri=skill://index.json
    Server-->>Host: { $schema, skills:[{name,url,digest}] }

    Note over Host,Server: Step 5: Read the commit-helper SKILL.md, the skill file
    Host->>Server: resources/read uri=skill://commit-helper/SKILL.md
    Server-->>Host: frontmatter (name, description) + body

    Note over Host,Server: Step 6: Tool handling, calling the tool the skill points at
    Host->>Server: tools/call name=format_commit {type:"feat", scope:"skills", summary:"..."}
    Server-->>Host: feat(skills): ...

Steps

Setup

Terminal 1:  just serve   # skills-core server, file mode, :8080
Terminal 2:  just demo    # this walkthrough (--tui interactive)

What ‘minimal’ means

Serve each file under a skill directory as a skill:// URI, enumerate them at skill://index.json with a SHA-256 digest, and let a skill’s instructions point the host at a real tool. That is the whole blessed core: skills file + tool handling, consumed load-on-demand. Archives, remote sources, and fsnotify invalidation are deferred/extended and live in examples/skills.

Step 1: Choose the client wire mode

mcpkit’s server defaults to dual-wire (SEP-2575): one URL answers both the legacy initialize handshake and the server/discover probe. The rest of the walkthrough is identical either way.

Step 2: Connect to the skills server

Reproduce

c := client.NewClient(serverURL+"/mcp",
    core.ClientInfo{Name: "skills-core-host", Version: "1.0"},
    client.WithClientMode(wireMode),
)
if err := c.Connect(); err != nil { /* run: just serve */ }

Step 3: resources/list, where each skill file is a skill:// resource

Step 4: Read skill://index.json, the discovery catalog

mcpkit generates index.json from the live provider catalog on each cache miss, so it is not a file on disk. Each entry carries a SHA-256 digest over the skill’s SKILL.md.

Reproduce

body, _ := c.ReadResource(skills.IndexURI)
var idx skills.Index
json.Unmarshal([]byte(body), &idx)
entries, _ := sc.ListSkillEntries(ctx)
for _, e := range entries {
    fmt.Printf("%s files=%d\n", e.Name(), len(e.Resources.Files))
}

Step 5: Read the commit-helper SKILL.md, the skill file

A skill is data: markdown with YAML frontmatter. Its body tells the host which tool to call and how. mcpkit delivers it over resources/read, never staged to disk and never executed.

Step 6: Tool handling, calling the tool the skill points at

This is the ’tool handling’ half of the minimal shape. The skill guided the host to format_commit; the host calls it and returns the result. Skills make ordinary tools easier to use well, the pattern Paul Withers raised in-channel on 2026-07-01.

Reproduce

out, _ := c.ToolCall("format_commit", map[string]any{
    "type": "feat", "scope": "skills", "summary": "add commit-helper skill",
})

Run it

go run ./examples/skills/

Pass --non-interactive to skip pauses:

go run ./examples/skills/ --non-interactive