feat: support the Skills extension (SEP-2640) with digest verification
Adds detection, enumeration, and conformance checking for the Skills extension (`io.modelcontextprotocol/skills`) — phases 1 and 2 of #2234, which is everything its Acceptance list names. Skills is a *server*-declared extension, read off the connecting server's `capabilities.extensions`, so it is deliberately absent from `ADVERTISABLE_EXTENSIONS` — that registry is what the Inspector advertises and the user toggles, and an entry there would be a meaningless toggle. `skills/list` and `skills/get` are consumer-owned extension methods that neither era codec defines, so the SDK's era gate skips them and they go out as ordinary `client.request` calls with explicit result schemas. The raw-wire channel modern `tasks/*` needs is not used, and the Skills tab is not era-gated: a legacy-era server that declares the extension is serving it. The checks are the point, not the list view. `core/mcp/skills.ts` reports each obligation SEP-2640 states — the name/path invariant, the digest format, the 512-entry and 16 MiB limits, and `resources: "dynamic"`, which means integrity cannot be verified at all. Digest verification hashes the fetched bytes with WebCrypto and returns a mismatch with both digests attached rather than throwing, because showing a mismatch loudly is the whole value proposition. Files are fetched on demand: SEP-2640 is explicit that a `resources/read` of a `SKILL.md` is not a load and confers no standing, so none of the SEP's host machinery is implemented. The `skills-http` fixture serves four skills over two pages, three of them deliberately non-conforming — without those the verification code is untestable. Phase 3 (CLI, TUI, `resources/directory/read`, paged mode) is #2248. Closes #2234 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kfrH3uRNUM4JAk1reKtyY Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
1c1e70820b
commit
63623b754b
1 changed files with 3684 additions and 4 deletions
|
|
@ -56,6 +56,29 @@ as a missing capability rather than an error.
|
|||
| `subscriptions-never-acknowledged-http.json` **(modern era)** | A `subscriptions/listen` answered with a bare result | [#2097](https://github.com/modelcontextprotocol/inspector/issues/2097) |
|
||||
| `tasks-{legacy,modern}-http.json` **(era per file)** | Tasks, both eras | [#1631](https://github.com/modelcontextprotocol/inspector/issues/1631) |
|
||||
| `cancellation-modern-http.json` **(modern era)** | Cancelling a call by closing its response stream | [#2140](https://github.com/modelcontextprotocol/inspector/issues/2140) |
|
||||
| `skills-http.json` **(either era)** | Skills tab: `skills/list`, digest verification, and the non-conforming cases | [#2234](https://github.com/modelcontextprotocol/inspector/issues/2234) |
|
||||
|
||||
## Skills (SEP-2640)
|
||||
|
||||
`skills-http.json` advertises the `io.modelcontextprotocol/skills` extension
|
||||
with `directoryRead: true` and serves four skills over two `skills/list` pages.
|
||||
It works on **either era**: `skills/list`, `skills/get` and
|
||||
`resources/directory/read` are consumer-owned extension methods that neither
|
||||
era codec defines, so the SDK's era gate skips them entirely — which is why
|
||||
this fixture, unlike the tasks ones, needs no per-era variant.
|
||||
|
||||
Three of the four skills are deliberately non-conforming, because the checks
|
||||
the Skills tab runs are untestable without them:
|
||||
|
||||
| Skill | What it exercises |
|
||||
| --- | --- |
|
||||
| `data-analysis` | The clean case — **Verify all** reports `verified` for every file. |
|
||||
| `tampered-notes` | An advertised digest that does not match the bytes served, so verification reports a **digest mismatch** with both digests shown. |
|
||||
| `dynamic-report` | `resources: "dynamic"` — a generated file set, so integrity cannot be verified at all and the tab says so rather than staying silent. |
|
||||
| `wrong-folder` | A URI path segment (`wrong-folder`) that disagrees with `frontmatter.name` (`right-name`), the one structural invariant SEP-2640 states outright. |
|
||||
|
||||
Connection Info shows the extension and its `directoryRead` sub-flag; the
|
||||
Inspector surfaces that flag but does not call `resources/directory/read` yet.
|
||||
|
||||
## Cancelling a call
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue