Repository navigation
Tilequery: describe_tileset + tilequery tools, starting with elevation along a route #289
Description
Problem
Some questions need data that's in Mapbox tilesets but not behind any tool in this server:
- "How high is this point?" and "How hilly is this bike route?" (terrain)
- "How tall is this building?" (Streets v8
building.height) - "Is this spot in a park or an industrial area?" (Streets v8
landuse.class) - "Which of our sales territories is this address in?" (a customer's own tileset)
mcp-devkit-server has a generic tilequery_tool, but a model can only use it well if it already knows the tileset id, layer names and fields. Most models outside a developer setting don't.
Proposal
1. describe_tileset_tool
Takes a tileset id and returns its layers, with field names, geometry type and zoom range, read from the tileset's TileJSON. TileJSON already carries this. For example:
mapbox.mapbox-streets-v8: 16 layers.building:height,min_height,underground,extruderoad:class,lane_count,bike_lane,accesslanduse:class,typenatural_label:elevation_m
mapbox.mapbox-terrain-v2:contour(ele,index),landcover,hillshade
It's cheap and cacheable, and it works on the user's own tilesets too.
2. tilequery_tool
Tilequery API: tileset, point, radius, layers, limit, geometry type. It returns only the matched features' properties and distances, not full geometry, to keep results small. Its result includes a mapboxRender.ref so the hits can go on the map.
3. Built-in notes for Mapbox-owned tilesets
A few lines in the tool descriptions for Streets v8, Terrain v2 and Traffic v1: what each is good for, and the fields TileJSON leaves out. For example, Traffic v1's TileJSON lists no fields, but its tiles carry congestion, class and structure (checked against a live tile while working on #278). With these, common questions don't need a describe call first.
4. First use case: elevation along a route
A tool built on top of the two above. It takes a directions_tool ref or a line, samples points along it against the terrain tileset, and returns:
- total climb and descent
- the highest and lowest points
- a small profile the map could chart
It's a clear gap today (this server has no elevation at all), and it pairs well with routes on the map. A single point's elevation falls out of the same work.
Open questions
- Duplication with devkit. Do we copy devkit's
tilequery_toolhere, move it here and keep devkit for developer and admin work, or share the code? - On by default? Two more general tools add to tool-selection load. Off by default, at least for the hosted connector? Run the tool-selection eval (feat(evals): tool-selection eval for description routing regressions #274) either way.
- Listing tilesets. Listing a user's own tilesets needs the broader
tilesets:listtoken permission. Leave listing to devkit, and have users name the tileset? - Terrain precision. Vector contours come in fixed elevation steps. Check what tilequery gives on Terrain v2 versus the terrain DEM before promising elevation accuracy.
- Resource too? Claude Desktop and ChatGPT don't let the model read resources on its own, so describe has to be a tool. Should it also be a
mapbox://tilesets/{id}resource for hosts that do support reading them?
Activity
mattpodwysocki commentedon Oct 16, 2026
Reference: the Tilequery playground is a good model for
tilequery_tool's inputs and for how the results should look on the map.radius,limit,layers,geometry,dedupe.mapbox.mapbox-streets-v8,mapbox.mapbox-terrain-v2), so one call can answer "what's here and how high is it". The tool should accept an array.properties.tilequerycarriesdistance,geometryandlayer. Return one row per hit (layer, distance and the requested properties) rather than the raw FeatureCollection.mapboxRender.ref.mattpodwysocki commentedon Oct 20, 2026
Starting with part 4 (elevation) since it doesn't depend on the open questions. Quick finding that changes the plan a bit:
Tilequery isn't precise enough for elevation. Terrain v2 contours come back as nested bands in 10 m steps (or coarser), so the best you get is "somewhere above 240 m". Querying
mapbox.mapbox-terrain-dem-v1through Tilequery returns 422. Soelevation_toolreads the DEM raster tiles (.pngraw, terrain-RGB) and decodes the heights on the server instead:Points along a route share tiles, so a bike ride across SF is 1 tile request and SF to LA is under 48. No new dependency, the PNG decode is on Node's
zlib.That leaves the two questions for the general tools (parts 1 and 2), which I'd like the team's take on before building them:
tilequery_toolhere, move it here and keep devkit for developer/admin work, or share the code in a package?describe_tileset_toolandtilequery_toolare general and add tool-selection load. Off by default (at least on the hosted connector) and opt in with--enable-tools? Either way I'll run the feat(evals): tool-selection eval for description routing regressions #274 eval before and after.elevation_toolitself is narrow ("how hilly", "how high"), so I'm planning to ship it on by default unless anyone objects.