Skip to content

Maps in agent-built pages: options after reverting export_map_html_tool #281

Open

Description

@mattpodwysocki

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:

  1. map code (GL JS)
  2. a public token
  3. 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_tool needs tokens: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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions