Repository navigation
Maps in agent-built pages: options after reverting export_map_html_tool #281
Description
Problem
An agent building a site or file with a map (ChatGPT/Codex, Claude Code, Claude artifacts) has to write its own Mapbox GL JS code and ask the user for a public token. That's what happened in ChatGPT/Codex when someone asked for a site with a map. render_map_tool only renders inside the chat as an MCP App, so it doesn't help here.
#275 (export_map_html_tool) tried to solve this and was reverted in #279. The work is kept on feat/export-map-html-tool. This issue is for picking the approach before building again.
A page needs three things:
- map code (GL JS)
- a public token
- the data (routes, places, isochrones)
The data mostly works today: tools already return GeoJSON, and refs can be refetched (directionsRequestFromRef, #276). The real gap is the token, and how much code we hand the agent.
Options
1. Public token tool in this server (get_public_token_tool or similar)
Returns the account's default public token, using the same resolveMapboxPublicToken() the in-chat map already uses (pk passthrough, /tokens/v2/{user}?default=true with tokens:read, or MAPBOX_PUBLIC_TOKEN). The agent writes its own GL JS.
- Pros:
- Small, and needs no new OAuth scope.
- Fits any framework (plain HTML, React, Next).
- It's what a developer does by hand.
- pk tokens are meant to be public, and this one already ships to every in-chat map page.
- Cons:
- The default public token has no URL restrictions. Once it's in a published site or a public repo, anyone can reuse it and the usage bills to the user's account.
- A tool that returns a credential may get extra attention in the Claude connector directory and ChatGPT app reviews.
- The agent still writes GL JS from scratch, so quality varies.
- Mitigations:
- The result says plainly that this is for local or prototype use, and that a published site should use a URL-restricted token, with a link to create one.
- Never return secret or temporary tokens; pk only.
2. Point site building at the devkit server
mcp-devkit-server already has list_tokens_tool and create_token_tool, which can create a URL-restricted token. The server instructions here would say that site building is a devkit task.
- Pros:
- Proper scoped tokens, and no credential tool in the consumer server.
- Cons:
- It needs a second server installed.
create_token_toolneedstokens:write, a much bigger grant.- Most ChatGPT and Claude users won't have devkit.
3. Re-land export_map_html_tool
A whole page, with data and token baked in and the script pinned on jsDelivr.
- Pros:
- The best one-shot result for "make me a page with this map".
- Cons:
- It's what was reverted.
- It ties us to a public hosted script contract and the npm/jsDelivr release cycle.
- It hands over a whole document, which fits poorly into an existing app or framework.
- It has a 200 KB data cap.
- The token concern from option 1 still applies, because the token is inside the page.
4. An embed snippet tool (middle ground)
Returns a small GL JS snippet or config (style, layers, markers) plus the token, for the agent to drop into its own page, instead of a full document.
- Pros:
- Reuses our layer and marker logic.
- Fits existing pages.
- Cons:
- It's still a code-generation contract to maintain.
- The token concern is the same as option 1.
5. Static map URLs
For pages that don't need interaction, return a Static Images API URL (with the public token) that the page can use as an <img>.
- Pros:
- Trivial to embed, and no JS.
- Cons:
- Not interactive.
- The URL still carries the token.
6. Do nothing; document it
Server instructions tell the agent to ask the user for a public token and link to account.mapbox.com.
- Pros:
- No new surface.
- Cons:
- The friction that started this.
Questions to settle
- Is returning the default public token to the model acceptable, given it's already embedded in every in-chat map? Or do we require a URL-restricted token for anything that leaves the chat?
- Should the consumer server have any credential-returning tool, given connector directory review?
- Do we want to own any page or snippet code (options 3 and 4), or leave GL JS to the agent plus docs (
mcp-docs-server)?
Leaning
Option 1, scoped tightly:
- pk only, from the existing resolver.
- Read-only, no new scopes.
- The result says to use a URL-restricted token for published sites.
- Paired with docs for the GL JS side.
Option 2 stays the path for people who want proper scoped tokens. Options 3 and 4 can come back later if agents' hand-written maps turn out to be poor.
Activity