Repository navigation
Description
Summary
Convert ground_location_tool to use the MCP tasks extension (SEP-1686, official extension in the 2026-07-28 RC) so the agent gets the cheap, deterministic pieces (place name) immediately while the slower pieces (sampling-classified POI search, isochrone) stream in as they resolve.
Why
ground_location_tool today does roughly:
- (Optional) MCP sampling to classify the grounding strategy as
routing/neighborhood/poi/region— round-trip to the client's model, variable latency, can take several hundred ms - Parallel fan-out of three Mapbox API calls: reverse geocode, category search (if
query), isochrone - Block until all three return
- Format + return as one text payload
Steps 2 and 3 are individually quick (each <1s typically) but the sampling step in 1 makes the whole call feel sluggish, and the user sees nothing until everything is done — even though the reverse-geocoded place name is usually available in ~100ms.
A task-based shape lets the server:
- Return a task handle from
tools/callimmediately - Resolve the reverse-geocode and surface it as the first task update (the agent now has the place name + coords)
- Resolve the sampling classification in parallel
- Surface POI and isochrone results as additional updates as they complete
- Final task state has the formatted summary
For an agent that just needs "what place is this?", it can read the first update and move on — no need to wait for the isochrone. For a user that wants the full grounded context, they get it incrementally rather than as one delayed blob.
Less obvious benefit
The current PR #173 implementation has a fallback path when the client doesn't support sampling: it defaults to neighborhood strategy. A task-based version makes this fallback more graceful — the task can declare immediately what strategies it ran with and what's pending, instead of either blocking on sampling or silently downgrading.
Compatibility
Like the MTS proposal in #196, clients that don't advertise the tasks extension would just get the current behavior: synchronous call, full result at the end. The task path is purely additive.
Implementation notes
MapboxApiBasedTool.execute()would need a sibling likeexecuteTask()that returns an in-progress task with hooks to update state — exact shape depends on the final task extension spec (still experimental)- Progress updates carry the same
structuredContentshape we already return, just incrementally — UI surfaces (Claude Desktop, etc.) that want to render the streaming state can do so without us defining a custom progress contract - This would be a good pilot for the tasks extension before tackling the longer-running MTS workflows in Feature request: Mapbox Tiling Service (MTS) tools, leveraging the new MCP tasks extension #196, since the failure mode here is gentle (worst case: same behavior as today)
Related
- feat: use MCP sampling to classify grounding strategy #173 — added the MCP sampling-based strategy classification
- Feature request: Mapbox Tiling Service (MTS) tools, leveraging the new MCP tasks extension #196 — broader MTS support proposal that needs tasks; this one benefits from tasks. Different urgency, same protocol primitive.
Activity
rehan243 commentedon Jun 10, 2026
oh interesting, we've actually hacked something similar with MCP tasks for streaming slow POI lookups — totally agree: blocking on the sampling step kills UX, especially when reverse-geocode is ready way faster. What worked for us was firing off the initial MCP task like:
We ended up using a combo of asyncio and
task.update()to stream partial results — not gonna lie, took a few tries to get the agent to handle mid-task updates cleanly. Are you on the 2026-07-28 RC or earlier? Curious if you've got anything weird happening with task update ordering, since our POI search sometimes beats sampling (which feels odd UX-wise).mattpodwysocki commentedon Jun 10, 2026
Picking this up in draft PR #210. The MCP SDK 1.29.0 already ships
server.experimental.tasks.registerToolTaskso we don't need to wait for the 2026-07-28 RC to start building against it.What's in the draft:
ground_location_toolnow overridesinstallToto useregisterToolTaskinstead ofregisterToolcreateTaskreturns the task handle immediately and kicks off background work without awaiting itInMemoryTaskStorewired into the server so task lifecycle is managedTwo known gaps before this can ship:
taskSupport: 'required'currently breaks clients without task support, and the in-memory store loses state on restart. Both are intentional for now since this is a design spike. ThetaskSupport: 'supported'fallback path should be clearer once the RC lands in July.One thing worth noting from the SDK branch: the valid task statuses are
working,input_required,completed,failed,cancelled-- there is norunningstate, tasks start asworkingalready. Tripped over that while writing the tests.rehan243 commentedon Jun 10, 2026
oh nice, didn’t realize 1.29.0 already had
registerToolTaskbaked in — that should speed things up a lot. yeah, thetaskSupport: 'required'issue is a pain; we hit that on our end too and ended up adding a fallback for legacy clients. curious if you’re planning to handle the partial support case in the next patch or workaround it for now? lmk if you want me to share our fallback snippet.mattpodwysocki commentedon Jun 11, 2026
yes please share it, that would be really helpful. the plan is to tackle the fallback in a follow-up once we see how the RC shapes the supported path, but having a working reference for the inline execution case would save some guesswork.
mattpodwysocki commentedon Jun 11, 2026
went ahead and pushed the fallback in the same draft PR (#210) -- curious if this is along the lines of what you had. ended up using
taskSupport: 'optional'which the SDK already handles automatically: non-task clients get the same synchronous result as before, the SDK internally creates the task, polls at 50ms intervals, and returns the result directly without the caller ever seeing a task handle.the relevant bit in
createTask:and in
runTaskBackground, sampling and the initial geocode kick off in parallel, then POI search and isochrone fan out once the strategy resolves:no custom fallback code needed since the SDK automatic polling path handles it. still keen to see what your snippet looks like though, especially if you solved the update ordering issue differently.
rehan243 commentedon Jun 15, 2026
Valiunia commentedon Jun 23, 2026
closing in favour of internal ticket