Repository navigation
feat: serve skills over the MCP Skills extension (SEP-2640) - #295
Open
mattpodwysocki wants to merge 7 commits into
Open
mattpodwysocki wants to merge 7 commits into
mattpodwysocki wants to merge 7 commits into
Conversation
Adds two skills, mapbox-map-display and mapbox-reachability-analysis, served through skills/list, skills/get and skill:// resources, with manifest digests computed from the served bytes. A skill is only served when all its tools are enabled. Also exported from @mapbox/mcp-server/skills for the hosted server. Part of #259 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 21, 2026
SDK 2.4.0 ships SEP-2640 support, so the hand-rolled skills/list and skills/get handlers go away. loadSkills() builds a SkillCatalog from our Skill objects and installSkillsTo() attaches it, which also declares the capability. Tests read every skill through the SDK's SkillsClient, which checks sizes, digests and frontmatter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The skills now live only in mapbox-agent-skills (mapbox-agent-skills#94 adds the two this PR introduced). agent-skills.json pins a commit and maps each served skill to the tools it needs; scripts/fetch-agent-skills.mjs, run by prepare (npm ci, npm run build), generates the gitignored src/skills/agentSkills.generated.ts, so the skills ship in the package and nothing is fetched at runtime. Also serves mapbox-location-grounding and mapbox-search-patterns. Tests check the generated file matches the pin, every skill loads strictly, and no skill names a tool this server lacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For plugins that already ship their own copies of the same skills. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ctufts
previously approved these changes
Oct 28, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ctufts
approved these changes
Oct 28, 2026
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.
Part of #259
What
The server now supports the MCP Skills extension (SEP-2640, Final,
io.modelcontextprotocol/skills). A client can list our skills and load one when a task calls for it, so the model doesn't have to work the steps out from tool descriptions.Four skills, all from mapbox/mapbox-agent-skills:
mapbox-map-display(new, added in Add mapbox-map-display and mapbox-reachability-analysis skills mapbox-agent-skills#94): passing refs torender_map_tool, several results on one map, hand-placed markers withmapbox_idfor the results panel, base map restyling, and when a static image is right instead.mapbox-reachability-analysis(new, same PR): isochrone, thenbbox_tool, then category search in that box, thenpoints_within_polygon_toolto drop places in the box's corners, then one map with the area and only the places inside it. This goes further than theshow-reachable-areasprompt, which maps the area only.mapbox-location-grounding: answering location questions from live data with citations instead of training data.mapbox-search-patterns: choosing the right search tool and parameters.Where the skills come from
The skills repo is the only copy; nothing is duplicated here.
agent-skills.jsonpins a commit (full SHA) and maps each served skill to the tools it needs.scripts/fetch-agent-skills.mjsdownloads that commit and generates the gitignoredsrc/skills/agentSkills.generated.ts. It runs fromprepare, sonpm ciandnpm run buildboth run it, and it skips the download when the generated file already matchesagent-skills.json.distand ship in the npm package (ESM and CommonJS), so nothing is fetched at runtime and hosted gets them through the package.evals/andAGENTS.mdaren't served;SKILL.mdandreferences/are.refhere.point_in_polygon_tool, the DevKit'sbounding_box_tool, static maps instead ofrender_map_tool).refcurrently pins that PR's head commit; I'll bump it to the merge commit once Add 8 offline geospatial tools using Turf.js #94 merges, before this one does.How
@modelcontextprotocol/server/ext/skills, typescript-sdk#3047), which shipped in 2.4.0 (chore: bump MCP TypeScript SDK to 2.4.0 #303). It declares the capability undercapabilities.extensions(where ChatGPT reads it), answersskills/listandskills/get, and serves theskill://files with their sha256 digests and byte sizes. Our code just hands it each skill's files withmemorySkillFiles.public(sent on 2026-07-28 connections).--disable-tools isochrone_tooldrops the reachability skill, and with no skills left the extension isn't declared at all.--disable-skillsorDISABLE_SKILLS=trueserves none, for a plugin that already ships its own copies of the same skills. Hosted doesn't attach skills yet either; that waits until we can confirm how the ChatGPT plugin handles skills from both places.@mapbox/mcp-server/skillsexports the skills,installSkillsTo(server, skills)andloadSkills(skills). Hosted builds a server per request, so it shouldloadSkillsonce andattach()the catalog to each server.Updated after #296 and #303: this first hand-rolled
skills/listandskills/geton SDK v1, with the two skills inline in TypeScript. It's now on SDK v2 with the SDK's implementation, and the skills come from mapbox-agent-skills.Client support
Testing
SkillsClient, which checks sizes, digests and frontmatter the way hosts do (including a multibyte character and a colon and quotes in the description).agent-skills.json(catches a forgottennpm run fetch-skills).SKILL.mdunder 256 KiB.npm cigenerates the skills, then typecheck, build and the full suite pass.npm packincludes the compiled skills in both builds.SkillsClientover stdio against the builtdist: all four skills read backverified. Withisochrone_tooldisabled, reachability and location-grounding drop out. Withrender_map_tool,isochrone_toolandsearch_and_geocode_tooldisabled, none are served and the extension isn't declared.initializedeclaresio.modelcontextprotocol/skillsby default and no extension with--disable-skillsorDISABLE_SKILLS=true.mcp-inspector --cli node dist/esm/index.js --method skills/list --verify --require-digests(Inspector 2.11.0): "Verified 4 skills and 7 files: no conformance errors."Not done yet
directoryReadisn't declared. Supporting files likemapbox-search-patterns' references are listed in the skill's entry, so clients still reach them.🤖 Generated with Claude Code