- map_matching_tool: When the Map Matching API can't match a trace (e.g.
code: "NoMatch"for distant/unmatchable coordinates), the tool now returns a clearisErrortext result instead of crashing withMCP error -32602: Output validation error— the API omitstracepoints/matchingsin this case, which previously violated the tool's output schema and was returned asstructuredContentanyway, triggering the MCP SDK's output validation. The same schema-violatingstructuredContentcould also be returned for acode: "Ok"response that otherwise failed schema validation (e.g. aconfidenceout of range); that fallback now also returns a gracefulisErrorresult instead of the raw invalid payload.tracepointsandmatchingsare also now.optional()in the output schema as a defensive measure. (AGI-1021)
- directions_tool: The map preview UI (both the MCP Apps resource and the legacy MCP-UI inline UI) now fetches its own route directly from the Directions API using the tool call's input parameters, instead of depending on the tool response carrying
geometries="geojson". Previously, the map showed an error whenever the defaultgeometries="none"was used because no route data was returned to draw. The map now works regardless of thegeometriesvalue, so text/data responses can stay compact by default without ever breaking the preview. - directions_tool map preview: Replaced the one-shot render latch with per-call render cycles, so a host that reuses the same iframe across sequential
directions_toolcalls gets the new route instead of the first one forever, and hardened the iframe's postMessage handling — messages are only accepted from the embedding host (sender pinning), and untrusted input that gets interpolated into the Directions request URL (coordinates,routing_profile,exclude) is validated before the self-fetch runs, mirroring the server-side zod guarantees.
- CONTRIBUTING: Clarify that unsolicited PRs adding third-party directory/discovery listings (e.g. README badges,
beacon.json-style manifests) are out of scope and will be closed without review (#225).
- Public token resolution:
resolveMapboxPublicTokennow also resolves a public token fortk.*(OAuth-issued temporary) bearers, not justsk.*bearers. Previously, granting thetokens:readscope to an OAuth client had no effect because the Tokens API lookup was skipped fortk.*tokens, causing GL JS preview tools (e.g. Directions) to fail with "No Mapbox public token available" even whentokens:readwas granted. - Public token cache is now per-user: the resolved public token cache was previously a single global slot shared by every request. It's now keyed by the token's account, so concurrent requests from different accounts can no longer receive each other's cached public token.
- Docker: Remove
libgnutls30from the runtime image viadpkg --remove --force-depends. The package is only depended on byapt, which is not needed at runtime.libgnutls30is not called by Node.js (which uses OpenSSL for TLS) and was present solely as a transitive system dependency of the Debian slim base.
- Temporary resources (
mapbox://temp/...) are now scoped to the account that created them: a read by a different account returns the standard not-found response. Token resolution mirrors the tools (request auth, then the env token for stdio/single-user), so local reads are unaffected. Adds regression tests.
- Normalize line endings to LF: Added
.gitattributes(* text=auto eol=lf) and"endOfLine": "lf"to the Prettier config so Windows contributors no longer hit CRLF/Prettier failures when runningnpm run lint.
- static_map_image_tool: Stop embedding the Mapbox access token in tool results. Previously the tool returned a
createUIResource({ iframeUrl })whose URL carried the caller's?access_token=query param, leaking the secret token via the MCP-UI resource item. The credentialed URL is now only used server-side to fetch the image, which is returned inline as base64. The tool'smeta.ui.resourceUrideclaration is removed (the iframe path required the credentialed URL to function and cannot be reinstated without leaking). A regression test asserts the access token does not appear in any content item. - chore: upgrade @opentelemetry/* packages to latest (fixes protobufjs GHSA-xq3m-2v4x-88gg critical CVE) (#183)
- CVE-2026-33750: Added
overridesforbrace-expansionto^2.0.3— eliminates vulnerable1.1.14installs nested under@eslint/config-array,@eslint/eslintrc, andeslintviaminimatch@3.1.5 - CVE-2026-33750 (Docker): Upgrade npm to
11.16.0in Dockerfile —node:22-slimships with npm 10.9.8 which bundlesbrace-expansion2.0.2 internally; upgrading npm replaces it with 5.0.6 (patched)
- Remove
point_in_polygon_tool—points_within_polygon_toolfully covers the single-point case; pass a one-elementpointsarray instead. Updatedpoints_within_polygon_tooldescription to make clear it handles single points as well as batches.
- Upgrade
tshyto^4.1.1,vitest/@vitest/coverage-istanbulto^4.1.4,typescriptto^6.0.2— removed deprecatedbaseUrlfromtsconfig.base.json(TS6), updatedpathsentry to use relative./prefix - Upgrade OpenTelemetry to 2.x — upgraded
@opentelemetry/resourcesand@opentelemetry/sdk-trace-basefrom^1.30.1to^2.6.1; upgraded experimental packages (sdk-node,instrumentation,exporter-trace-otlp-http) from^0.56.0to^0.214.0; upgradedauto-instrumentations-nodeto^0.72.0andsemantic-conventionsto^1.40.0; migratednew Resource()toresourceFromAttributes()following the 2.x API change - Upgrade
zodfrom^3.25.42to^4.3.6— migratedz.record()calls to require explicit key schema (z.string()), updated.shapeaccess (no longer a function in v4), and fixeddenoisedefault handling inIsochroneToolinput schema
directions_toolnow renders as a live Mapbox GL JS map for both the MCP Apps spec and legacy MCP-UI clients:- MCP Apps: the tool declares
_meta.ui.resourceUripointing to a newDirectionsAppUIResource(ui://mapbox/directions-app/index.html). MCP App–capable hosts (Claude Desktop, VS Code, Cursor) render the route via postMessage handoff. - MCP-UI: when
geometries=geojsonis requested and the response carries a renderable LineString, an inlinerawHtmlUIResource is added to the tool'scontent[](gated by the existingENABLE_MCP_UI/--disable-mcp-uiflag, likestatic_map_image_tool). - One source of truth: both pathways render the same HTML produced by
renderDirectionsAppHtml— for MCP Apps the resource serves a generic version and the iframe receives the tool result via postMessage; for MCP-UI the tool bakes the route geometry into the HTML before returning. No more "GL JS map for one client, static image for the other." - Public token: resolved server-side via
GET /tokens/v2/{user}?default=true(requirestokens:readon thesk.*token) withMAPBOX_PUBLIC_TOKENenv var fallback. Non-MCP-App hosts that also have MCP-UI disabled ignore both UI hints and consume the existing text/structuredContent payload unchanged. - Graceful degradation: responses without renderable geometry (>50KB temporary-resource path,
geometries=none,geometries=polyline*) skip the inline rawHtml block and show a "no geometry to render" message in the MCP App iframe. - CSP:
_meta.ui.csp.workerDomains: ['blob:']so MCP App hosts grant Mapbox GL JS the iframe sandbox permissions it needs.
- MCP Apps: the tool declares
- MCP Completions capability: Add auto-completion support for prompt arguments per MCP spec (2025-11-25). Clients can now suggest values when users fill in prompt parameters (#176)
categoryargument onfind-places-nearby— 482 Mapbox Search API categoriesmodeargument onget-directions,search-along-route,show-reachable-areas— driving, driving-traffic, walking, cycling
- ground_location_tool MCP sampling: Use MCP sampling to classify the grounding strategy (
routing/neighborhood/poi/region) and shape downstream Geocoding, Search, and Isochrone calls accordingly. Falls back toneighborhoodwhen the client doesn't support sampling.
- static_map_image_tool: Validate custom-marker URLs to reject loopback, private, link-local, and cloud-metadata IP addresses, preventing SSRF via the Mapbox Static Images API (CWE-918)
- CLI metadata flags: Handle
--helpand--versionbefore server startup so users can inspect usage and version information without requiring Mapbox environment configuration. - Prompt descriptions: Add missing
driving-traffictransport mode toget-directions,search-along-route, andshow-reachable-areasprompt descriptions - ground_location_tool: Use
mapbox/prefix for isochrone profiles and adddriving-trafficsupport - ground_location_tool: Reverse geocode now returns neighborhood/locality/place name instead of street address by default
- ground_location_tool: Strengthened tool description to prefer it over
reverse_geocode_toolfor location context queries
- CVE-2026-4926: Upgraded
@modelcontextprotocol/sdkto^1.29.0, resolvingpath-to-regexpto8.4.1and fixing the ReDoS vulnerability GHSA-j3q9-mxjg-w52f; regenerated output-validation patch for the new version - static_map_image_tool: Validate
styleparameter againstusername/style-idformat to prevent path traversal attacks where a crafted style value (e.g.,../../tokens/v2) could escape the/styles/v1/URL path and access arbitrary Mapbox API endpoints using the server operator's token - static_map_image_tool: Remove access token from URL returned in text content — the token is only used internally for the HTTP fetch and the MCP Apps iframe URL, not exposed to the model context
- 9 new offline Turf.js geometry tools (no API key required, instant results):
points_within_polygon_tool: Batch-test multiple points against a polygon in one call — replaces Npoint_in_polygon_toolcalls for delivery zone validation, fleet geofencing, etc.union_tool: Merge two or more polygons into a single unified geometry; useful for combining service areas, isochrones, or delivery zonesnearest_point_tool: Find the nearest point in a collection to a target — replaces callingdistance_toolfor each candidateintersect_tool: Find the intersection geometry of two polygons (area they share in common)difference_tool: Subtract one polygon from another ("what is in zone A but not zone B?")destination_tool: Calculate a destination point given origin, bearing, and distancelength_tool: Measure the total length of a line/route without a routing API callnearest_point_on_line_tool: Snap a point to the nearest position on a line or routeconvex_tool: Compute the convex hull of a set of points
- Added
getAllToolsto@mapbox/mcp-server/toolssubpath export for batch access to all registered tools - Added
getVersionInfoandVersionInfotype to@mapbox/mcp-server/utilssubpath export
- version_tool: Removed from the tool list — version info is now available as a resource at
mapbox://versionwith zero token overhead
- mapbox://version resource: Server version, git SHA, tag, and branch accessible via
readResource('mapbox://version')
- static_map_image_tool: Large images (>700KB raw) are now stored as temporary resources instead of being inlined as base64, preventing the 1MB tool result limit from being exceeded in Claude Desktop
- Image stored at
mapbox://temp/static-map-{id}, retrievable viaresources/readwith a 30-minute TTL TemporaryResourceManagernow enforces a 50MB byte cap with oldest-first eviction to prevent unbounded memory growthTemporaryDataResourcenow serves image mime types as blob content
- Image stored at
- IsochroneTool large-response handling: Isochrone responses exceeding 50KB are now stored as temporary resources, consistent with DirectionsTool (#131)
- Returns a compact summary with contour count and resource URI instead of the full GeoJSON
- Full GeoJSON retrievable via
readResource('mapbox://temp/isochrone-{id}')with 30-minute TTL - Normal-sized responses are unaffected
- static_map_image_tool: Return a proper error when the Mapbox Static Images API returns a non-2xx response instead of silently encoding the error JSON as a fake base64 image (#130)
- BaseResource URI template registration: Fixed
TemporaryDataResource(and any resource with{in its URI) never matchingreadResourcecalls (#133)server.registerResource()with a plain string registers an exact-match static resource; template URIs likemapbox://temp/{id}require aResourceTemplateobjectBaseResource.installTo()now detects{in the URI and wraps it withResourceTemplateautomatically
- Upgrade
@mcp-ui/serverfrom^5.13.1to^6.1.0(security advisory on older versions) - Upgrade
@modelcontextprotocol/sdkfrom^1.26.0to^1.27.1(security advisory on older versions); regenerated output-validation patch for new version
- Updated README: Goose added to MCP Apps supported clients; MCP-UI noted as legacy protocol
-
place_details_tool: New tool to retrieve detailed information about a specific place by Mapbox ID
- Accepts a
mapbox_idfrom search results (search_and_geocode_tool,category_search_tool,reverse_geocode_tool) - Optional
attribute_setsparameter:basic,photos,visit(hours, rating, price),venue(phone, website, social media) - Optional
languageandworldviewparameters - Returns formatted text summary plus structured GeoJSON Feature content
- Opening hours formatted as readable per-day text (e.g. "Monday: 9 AM – 9 PM") rather than raw JSON
- Accepts a
-
Large Response Handling: DirectionsTool now creates temporary resources for responses >50KB
- Prevents context window overflow on long-distance routes
- Returns summary with distance, duration, and resource URI
- Full route geometry available via MCP resource API
- Temporary resources expire after 30 minutes
- Resource URI format:
mapbox://temp/directions-{id} - Updated tool description to guide LLMs: use geometries="none" for planning, geometries="geojson" only for visualization
- Returns lightweight structured content for large responses (summary data without geometry) to satisfy output schema validation
- Updated
search-along-routeprompt to usegeometries="none"and linear interpolation for route sampling instead of extracting coordinates from geometry
- search_and_geocode_tool, category_search_tool: Include
mapbox_idin formatted text output so models can chain directly toplace_details_toolwithout re-fetching results as JSON - category_search_tool: Fix schema validation failures on Japanese and other international place data
- Added
.passthrough()to all context sub-schemas to allow extra fields returned by the API - Made
country_code,country_code_alpha_3,region_code, andregion_code_fulloptional to match real API responses - Fixed
BaseToolto pass the full Zod schema (not just.shape) to the MCP SDK so.passthrough()settings are preserved during structured-content validation
- Added
- Added hosted MCP endpoint (
https://mcp.mapbox.com/mcp) toserver.jsonremotesfor registry discoverability
- Upgrade
@modelcontextprotocol/ext-appsfrom^1.1.0to^1.1.1 - Upgrade
@modelcontextprotocol/sdkfrom 1.25.3 to 1.26.0 - Regenerated SDK patch for version 1.26.0
- PR Guidelines: Added CHANGELOG requirement to CLAUDE.md (#112)
- All pull requests must now update CHANGELOG.md
- Document what changed, why, and any breaking changes
- Add entry under "Unreleased" section with PR number
- Release Process: Added automated CHANGELOG preparation script (#112)
- New
npm run changelog:prepare-release <version>command - Automatically replaces "Unreleased" with version and date
- Adds new empty "Unreleased" section for next changes
- Includes validation for version format and CHANGELOG structure
- New
- MCP Apps Support for StaticMapImageTool (#109)
- Added interactive map preview in compatible MCP clients (VS Code, Claude Code, Goose)
- Implemented
StaticMapUIResourceserving interactive HTML with inline MCP Apps SDK - Added
@modelcontextprotocol/ext-apps@^1.0.1dependency - Enhanced
BaseToolwithmetaproperty for MCP Apps metadata - Configured CSP for
api.mapbox.comdomains - Sends
ui/notifications/size-changedto fit panel to rendered image height - Fullscreen toggle using
ui/request-display-mode - Uses proper
RESOURCE_MIME_TYPE("text/html;profile=mcp-app") per MCP Apps specification - Tool response now includes: URL text (first, for MCP Apps), base64 image (for non-MCP-Apps clients), and optional UIResource (when MCP-UI enabled)
- CVE-2026-0621: Updated
@modelcontextprotocol/sdkto 1.25.3 to fix ReDoS vulnerability in UriTemplate regex patterns - Regenerated SDK patch for version 1.25.3
- Added
@modelcontextprotocol/ext-apps@^1.0.1 - Updated
@modelcontextprotocol/sdkfrom 1.17.5 to 1.25.3
- StaticMapImageTool: Added text content to response for better MCP client compatibility (#103)
- Tool now returns structured content array with text description, image, and optional MCP-UI resource
- Text content includes map metadata (center, zoom, size, style, overlay count)
- Follows MCP specification for tool results with multiple content items
- Removed an invalid option in input schema of
search_and_geocode_tool. Thenavigation_profileused to have invaliddriving-trafficoption.
-
MCP Resources Support: Added native MCP resource API support
- Introduced
CategoryListResourceexposing category lists asmapbox://categoriesresource - Supports localized category lists via URI pattern
mapbox://categories/{language}(e.g.,mapbox://categories/jafor Japanese) - Created base resource infrastructure (
BaseResource,MapboxApiBasedResource) for future resource implementations - Added
ResourceReaderToolas fallback for clients without native resource support - Enables more efficient access to static reference data without tool calls
- Introduced
-
MCP-UI Support: Added rich UI embedding for compatible MCP clients
StaticMapImageToolnow returns both image data and an embeddable iframe URL- Enables inline map visualization in compatible clients (e.g., Goose)
- Fully backwards compatible - clients without MCP-UI support continue working unchanged
- Enabled by default, can be disabled via
ENABLE_MCP_UI=falseenv var or--disable-mcp-uiflag - Added
@mcp-ui/server@^5.13.1dependency - Configuration helper functions in
toolConfig.ts
- CategoryListTool: Marked as deprecated in favor of the new
mapbox://categoriesresource- Tool remains functional for backward compatibility
- Users are encouraged to migrate to either the native resource API or
resource_reader_tool
- Update to MCP registry schema version 2025-10-17
- Support for
structuredContentfor all applicable tools - Registers output schemas with the MCP server and validates schemas
- Adds OpenTelemetry Instrumentation for all HTTP calls
- Fixed the version tool to properly emit the git version and branch
- Refactored
fetchClientto be generichttpRequest.
- Add server.json for MCP registry
- Introduce new tool: SearchAndGeocodeTool
- Remove former tools: ForwardGeocodeTool, PoiSearchTool; their capabilities are combined in the new tool
- Minor changes to tool descriptions for clarity
- New fetch pipeline with automatic retry behavior
- Dual emits ESM and CommonJS bundles with types per target
- Migrated from Jest to vitest
- Format Options: Add
formatparameter to all geocoding and search tools- CategorySearchTool, ForwardGeocodeTool, PoiSearchTool, and ReverseGeocodeTool now support both
json_stringandformatted_textoutput formats json_stringreturns raw GeoJSON data as parseable JSON stringformatted_textreturns human-readable text with place names, addresses, and coordinates- Default to
formatted_textfor backward compatibility - Comprehensive test coverage for both output formats
- CategorySearchTool, ForwardGeocodeTool, PoiSearchTool, and ReverseGeocodeTool now support both
- Support-NPM-Package: Introduce the NPM package of this mcp-server
- First tag release