simhacker/moollm/mapbox
Claude Code and agent skill by simhacker/moollm
- community
Checking that the SKILL.md file is still in the repository.
Route Mapbox work to the twenty official Mapbox Agent Skills instead of restating them, and own what they cannot know — key locations, measured token-restriction behaviour, and the choice between CLI, REST, MCP and SDK. Use when working with maps, tokens, geocoding, routing, styles, or tiles.
Install
npx vskill@latest install simhacker/moollm/mapboxSKILL.md
Mapbox
Mapbox wrote twenty skills. This one decides which two you need.
Mapbox publishes twenty Agent Skills under MIT at mapbox/mapbox-agent-skills — 6,128 lines of SKILL.md, each with an AGENTS.md quick reference, an evals/evals.json, and a references/ directory. They are good. This skill does not replace them and does not copy them.
It exists because of three things they do not do.
They ship no router. Twenty skills with no "which one?" layer means the honest default is loading too much, and attention is the scarce resource, not Mapbox knowledge.
They never say referer or 403 — zero occurrences across all 6,128 lines. They tell you to set URL restrictions but never document the mechanism or its symptom, so the most common token failure is undiagnosable from their text.
They cannot know your machine: which vault holds which token, which of your tokens is safe in a browser and which is safe in a shell, and which of your frameworks bakes secrets into a build artifact.
Quick start
The script is its own documentation (sister-script): imports, globals, CLI definition, implementation. Read the top for the interface.
Mounting upstream
The relationship is endosymbiotic in the sense moollm already uses the word — Margulis, by way of soul-city and the korz designs. The official repo is an organelle: engulfed, but keeping its own genome. It has its own remote, its own license and its own release cadence, and the host supplies only the envelope — routing, local keys, measured behaviour. Vendoring would be the opposite operation, copying the DNA into the nucleus and inheriting its maintenance forever.
Clone it beside your other repos and add it to the workspace. Nothing is vendored, so a refresh is one pull.
The resolver tries, in order: $MAPBOX_AGENT_SKILLS, then ~/GroundUp/git/, ~/git/, ~/src/, then ./, ../, ../../ for a sibling checkout, then ~/.agents/skills and ~/.claude/skills where npx skills add mapbox/mapbox-agent-skills installs them. If all miss, every command still answers and points at the URL rather than failing.
Four other install routes exist and all deliver the same content: npx skills add mapbox/mapbox-agent-skills, /plugin marketplace add mapbox/mapbox-agent-skills (which also wires up the three MCP servers), mapbox agent-skills install, or a plain clone.
ROUTE
Give the question in plain words; get two or three skill names.
Routing is coarse keyword matching on purpose. The goal is loading three skills instead of twenty, not cleverness. When nothing matches, it says so and points at list rather than guessing.
When the subject is one upstream does not cover, it says that too, and names the surface that does. Tilesets, fonts, sprites, accounts, Atlas and the licensed data products have no skill; they have CLI commands.
DIAGNOSE
A Mapbox 403 is almost always the URL restriction, and the decision tree is short. Run doctor, which probes a passing origin, the dev port, the preview port, an unrelated origin, and no referer at all.
Read the result like this. No referer is 403 for any restricted token, which means that token is dead from curl, CI, a server-side fetch, and every MCP server — they all send none. Keep an unrestricted token for those and never ship it in a bundle. An unrelated origin answering 200 means the restriction is not in force; check the list actually saved. The dev port passing while the preview port fails means the entry is an exact port, and each origin has to be listed explicitly. You cannot fix it the documented way: the console rejects http://localhost:* with "Wildcard characters (\*) are not supported in URL restrictions", so the patterns upstream's mapbox-token-security lists as recommended cannot be entered at all. The field accepts a comma-separated list, and an apex entry covers the www host for free.
Three measured traps will otherwise cost you an afternoon.
Enforcement is per-endpoint. Tile and data requests enforce the restriction; style metadata at /styles/v1/<user>/<id> answered 200 from every origin tried. A passing metadata call proves nothing — probe a tile.
Edits take minutes to reach the edge, and the intermediate state is per-variant. For several minutes after one save, http://localhost:5173 answered 200 while http://localhost:5173/ answered 403. That reads exactly like a matching bug and is not one. Re-probe a few minutes later before concluding anything, and never write a finding from a single probe — three runs minimum.
SURFACE
Four ways in. MCP is rarely the right one, and the ordering below is by composability.
REST with curl and jq is the most composable and needs nothing installed. Every service is plain HTTP with a token parameter. Note the geocoding v6 path is /search/geocode/v6/forward — geocoder returns 404.
The official CLI is unified and explicitly agent-first, covering auth, accounts, fonts, geocoding, search, sprites, static, styles and tilesets. It ships as an install script, not npm or brew or PyPI, which is why package searches miss it. mapbox generate-skills writes a skill describing its own command surface — point it at a directory and read what it writes.
Three MCP servers, not two. @mapbox/mcp-server is the runtime one, wrapping the location APIs for agents answering questions about the world. @mapbox/mcp-devkit-server is the authoring one, wrapping your account — 23 tools across styles, tokens, validation and conversion. @mapbox/mcp-docs-server looks up documentation. The clean way to hold them apart: the runtime server queries the world, the devkit server mutates your account. The devkit needs secret scopes, and it can create tokens, which is a meaningful privilege to hand an agent.
You do not need an MCP client to call one. A stdio server speaks newline-delimited JSON-RPC, so a shell pipe is enough — which makes devkit tools usable from a sister-script without the client overhead.
SDKs last. mapbox-gl for the browser, @mapbox/mapbox-sdk for node. The Python client last shipped in 2022 and the old mapboxcli in 2018; neither is where the work is.
KEYS
Tokens are resolved by role from 1Password, never pasted. Roles differ by where the code runs, not by who owns them.
| Role | Reference | Where it may run | |
|---|---|---|---|
| prod | op://Employee/Mapbox/ebike-safari-token | browser only — 403 without a referer | |
| dev | op://Employee/Mapbox/token | CLI, MCP, CI, scripts — never in a bundle |
The item is in vault Employee; there is no Personal vault on that account. Public scopes and URL restrictions are editable in place and leave the pk. string unchanged, so changing them needs no redeploy. Secret scopes are different: they produce an sk. token displayed once, which must never reach a browser.
The framework trap worth naming, because it is silent: a SvelteKit app prerendered with ssr=false compiles any PUBLIC_* variable into the static bundle at build time, so the token is baked into the Docker image and rotating it means rebuilding. Name it MAPBOX_TOKEN, read it in a +server.ts via $env/dynamic/private, and hand it to the browser at runtime — then rotation is a container restart.
MEASURE
The measured table in scripts/mapbox_router.py is the part of this skill that cannot be borrowed, so it has an entry rule: probe first, claim second, three runs minimum.
Record the endpoint and the date with the finding. Prefer a tile endpoint, since that is where enforcement lands. When a probe contradicts an earlier entry, replace the entry rather than annotating it — the table states what is true now, not the history of what was believed. A finding that came from one request during a propagation window is not a finding.
What to borrow back
Upstream ships evals/evals.json per skill: real prompts, expected outputs, and per-expectation checklists — a regression harness for a skill's judgment. moollm has no equivalent rung in its pyramid. That pattern is worth adopting repo-wide, and this skill is a reasonable place to try it first.
Related MOOLLM skills
- sister-script — the router script is its own documentation
- no-ai-humansplaining — the argument against vendoring the
twenty: restating what the agent can read is billed per call, forever
- robust-first — a missing checkout degrades to a URL, never a crash
- postel — route liberally on messy questions, emit exact skill names
- yaml-jazz —
GLANCE.ymlandCARD.ymlas semantic YAML
Part of MOOLLM
This skill is part of MOOLLM, a microworld OS where the filesystem is navigable space and skills are inheritable prototypes. See the repo README and skills README.
Credits
The twenty skills, the three MCP servers and the CLI are Mapbox's work, MIT licensed, at mapbox/mapbox-agent-skills. This skill routes to them and adds only what is local and what was measured.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/mapbox/SKILL.md
Popularity
- Repository stars
- 54
- Repository forks
- 5
- 7-day trend score
- 20
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/simhacker/moollm/mapbox)