Skip to content

Feature/issue 66 skill resource loading prototype - #116

Open
tobi-oye wants to merge 8 commits into
modelcontextprotocol:mainfrom
tobi-oye:feature/issue-66-skill-resource-loading-prototype
Open

Feature/issue 66 skill resource loading prototype#116
tobi-oye wants to merge 8 commits into
modelcontextprotocol:mainfrom
tobi-oye:feature/issue-66-skill-resource-loading-prototype

Conversation

@tobi-oye

@tobi-oye tobi-oye commented Aug 1, 2026

Copy link
Copy Markdown

Adds an experimental-findings.md entry for issue #66 — implementing skill:// discovery in VS Code and running it against a live MCP server.

Docs-only. The implementation lives in tobi-oye/vscode#1; this is a docs repo, so only the write-up belongs here.

Motivation and Context

Issue #66 asks for a prototype of skill resource loading in a major open-source client. This is that prototype, plus what it taught us.

The short version: VS Code already had almost everything needed. It has the full progressive-disclosure loop — discover skills, put just their names and descriptions in the model's context, give the model a tool to load the full text on demand. The only missing piece was that a skill could never come from an MCP server. And the loading half needed no new code at all, because mcp-resource:// is already registered with VS Code's filesystem service.

So the work was small. The findings are the valuable part.

Screenshots

image

How Has This Been Tested?

Against the live Hugging Face MCP server (https://huggingface.co/mcp, anonymous) from a source build of VS Code:

  • 8 skills discovered and offered to the model with no manual attachment
  • tsc --noEmit over VS Code's src/ — clean
  • 10 unit tests, including a skill://mcp-resource:// round trip and index parsing against verbatim live server output
  • 112 existing promptSyntax tests still pass

Not tested: the model actually choosing to load an MCP-served skill. Source builds of VS Code can't reach the Copilot service, and the available model was a small auto-routed one. Called out as open in the entry — discovery is verified by observation, loading only by mechanism.

Breaking Changes

None. Docs-only.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Four findings that seem worth other implementers' time.

1. "Where a skill came from" is written down in more than one place.
VS Code encodes it in four: a storage enum, a parallel string union, an ext-host protocol DTO, and a proposed extension API type. All four must agree. I updated two and missed two — which produced a runtime crash that broke chat entirely, while tsc stayed perfectly green. Budget for more than a one-line enum change.

2. A server doesn't have to list its skills, and it's easy to forget.
The SEP makes enumeration optional: a skill is readable by URL whether or not it appears in any index. A client that only reads skill://index.json will silently see nothing on a server that doesn't publish one. Try both the index and resources/list, and never read "index missing or empty" as "this server has no skills."

3. Skill names are one global namespace, and the SEP doesn't say who wins a clash.
If a local skill and an MCP skill are both called deploy, one disappears. Same if two connected servers both serve deploy. The SEP ties a skill's URL to its name but says nothing about precedence, so every host invents its own rule. I chose local-over-MCP — a server shouldn't be able to shadow a skill on your disk — but server-vs-server ends up as whatever order discovery happened to run in. This seems worth stating explicitly in the SEP.

4. Re-running discovery on every context computation is an accidental DoS.
findAgentSkills() runs each time the model's context is rebuilt, and discovery costs two round trips per server. A naive version issued 20 index reads for a single chat turn. That's the same shape as the incident behind hf-mcp-server's client denylist (#164, ~100k req/min). Cache the promise, not just the result, and key it on connection state — keying on server id alone pins an empty result from a lookup made while the server was stopped.

tobi-oye and others added 8 commits July 21, 2026 21:51
…discovery/loading)

Builds a from-scratch MCP server + client per the merged SEP-2640 draft
(resources + skill://index.json, no custom methods), exercising flat and
nested skill paths, relative sub-resource references, and the
"enumeration is optional but direct read must still work" baseline.
Findings recorded in docs/experimental-findings.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Inline the four skill fixture files into server.mjs (the prototype
demonstrates the transport binding, not filesystem loading) and drop the
prototype README, whose content is already in the PR description.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records what implementing skill:// discovery in VS Code proper surfaced:
the client already had the full progressive-disclosure loop and only
lacked an MCP source, its mcp-resource:// FS provider means the loading
half needs no code at all, and a new skill source touches more type
surfaces than expected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
experimental-ext-skills is a working-group docs repo, so a runnable
Node server/client pair did not belong in it. The actual client-side
implementation for issue modelcontextprotocol#66 now lives in VS Code, and what belongs
here is the write-up of what that surfaced.

Folds the still-transferable observations from the removed prototype
(URI- vs metadata-based identification per modelcontextprotocol#54, and the index digest
doc inconsistency) into the VS Code findings entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records what surfaced once the implementation was run from a source
build against the Hugging Face MCP server, rather than only
type-checked: the index wire format had already moved past the
checked-in draft, per-context-computation discovery is an easy
accidental DoS, a new skill source touches four type surfaces that must
agree, and cross-server name collisions are unspecified by the SEP.

None of the three defects were caught by tsc or the unit tests.

Also corrects the previous entry, which said the work was not verified
against a running server — it now is, for discovery. Model invocation
remains undemonstrated and is called out as such.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cut ~half the words to match the length of neighbouring entries and
make it reviewable at a glance. Same findings, less prose.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…he digest point

Issue modelcontextprotocol#66 asks explicitly for a URI- vs metadata-based identification
evaluation, so that belongs in the entry. The digest note is reframed
from a doc nitpick into the actionable version: the live server sends a
digest and this client ignores it, so nothing verifies skill integrity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@tobi-oye
tobi-oye requested a review from a team as a code owner August 1, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant