Fix hosted stateless follow-up path for large directions/isochrone results - #257
Open
mattpodwysocki wants to merge 1 commit into
Open
Fix hosted stateless follow-up path for large directions/isochrone results#257mattpodwysocki wants to merge 1 commit into
mattpodwysocki wants to merge 1 commit into
Conversation
… refs
directions_tool and isochrone_tool stored large responses in
temporaryResourceManager (an in-process Map, 30-min TTL) and returned a
mapbox://temp/{id} URI for a follow-up resources/read. The hosted
deployment is fully stateless across several ECS tasks with no session
stickiness, so a follow-up landing on a different task than the one that
computed the route found nothing - surfacing as "Resource not found or
expired" and easily misread as "Directions still computing" on long
routes, when the API had already finished.
Both tools now encode the full response into a new self-describing
mapbox://inline-response/{tool}?data=... ref, following the same
zero-server-state pattern already used by mapbox://compute/,
mapbox://selffetch/, and mapbox://inline/payload. Resolving the ref is a
pure function of the URI, so it works from any task/process - proven with
a real two-process integration test that computes the route in one
spawned server, kills it, and resolves the ref from a second, independent
process.
static_map_image_tool's equivalent fallback still uses
temporaryResourceManager and is intentionally left as-is (base64 binary
payload needs its own encoding to avoid double-base64 overhead) -
tracked as a fast follow-up.
4 tasks
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.
Summary
directions_toolandisochrone_toolstored large responses intemporaryResourceManager(an in-processMap, 30-minute TTL) and returned amapbox://temp/{id}URI for a client toresources/readafterward. The hosted deployment is fully stateless — everyPOST /mcpcan land on a different one of several ECS tasks behind a load balancer with no session stickiness — so a follow-up read landing on a different task than the one that computed the route found nothing, surfacing as "Resource not found or expired."This was most visible on long routes (e.g. London→Scotland with
geometries="geojson"), where the cleaned response crosses the 50KB inline threshold. It read like "the Directions API is still computing" or "requested too soon," but Directions is synchronous and had already finished by the time the URI was returned — the actual cause was which ECS task happened to serve the second HTTP request.Fix
Both tools now encode the full response directly into a new self-describing
mapbox://inline-response/{tool}?data=...ref, following the same zero-server-state pattern already used bymapbox://compute/,mapbox://selffetch/, andmapbox://inline/payloadin this codebase. Resolving the ref is a pure function of the URI string — no store, no TTL, no owner check — so it works identically no matter which task or process handles the follow-upresources/read.static_map_image_tool's equivalent large-payload fallback still usestemporaryResourceManagerand is intentionally left as-is here: it stores base64-encoded binary image data, not JSON, so naively applying the same scheme would double-base64-encode it (~77% size overhead vs. ~33%). Tracked as a fast follow-up.hosted-mcp-serverimports@mapbox/mcp-serveras a plain npm dependency and creates a fresh MCP server per request viaMCPManager/getMCPServer()— this fix requires no code changes there, only a version bump once released.Acceptance criteria
directions_tool/isochrone_toolresult works when handled by a different process/ECS task — proven withtest/integration/hostedMultiTaskFollowup.test.ts, which computes the route in one spawned server process, kills it outright, and resolves the ref from a second, completely independent process via a realresources/readcall.mapbox://temp/code path, then restoring the fix and confirming it passes.render_map_toolpreview via the self-fetch ref) are untouched for long routes — only the large-geometry inline-vs-ref fallback path changed.Test plan
npm run buildnpx vitest run— 949 tests passing, including new unit tests forinlineResponseRef.ts/InlineResponseResource.tsand updated large-response tests for both toolsnpx eslint --fixon all changed/new files — clean🤖 Generated with Claude Code