Skip to content

Tilequery: describe_tileset + tilequery tools, starting with elevation along a route #289

Open

Description

@mattpodwysocki

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, extrude
    • road: class, lane_count, bike_lane, access
    • landuse: class, type
    • natural_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_tool here, 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:list token 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

  1. mattpodwysocki commented on Oct 16, 2026

    @mattpodwysocki
    ContributorAuthor

    Reference: the Tilequery playground is a good model for tilequery_tool's inputs and for how the results should look on the map.

    • Inputs: they match the playground: tileset(s), point, radius, limit, layers, geometry, dedupe.
    • Several tilesets in one call: the API takes a comma-separated tileset list (e.g. 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.
    • Compact rows: each hit's properties.tilequery carries distance, geometry and layer. Return one row per hit (layer, distance and the requested properties) rather than the raw FeatureCollection.
    • On the map: like the playground, draw the query point, the radius circle and the matched features through mapboxRender.ref.
    • Notes for Mapbox's own tilesets: the playground offers Streets v8 and Terrain v2, which are the same two the built-in notes should cover first, plus Traffic v1.
  2. mattpodwysocki commented on Oct 20, 2026

    @mattpodwysocki
    ContributorAuthor

    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-v1 through Tilequery returns 422. So elevation_tool reads the DEM raster tiles (.pngraw, terrain-RGB) and decodes the heights on the server instead:

    Point Terrain v2 contours (Tilequery) DEM tiles
    Near Twin Peaks, SF 240 m 249.5 m
    Civic Center, SF 10 m 20.9 m
    Longs Peak summit 4,346 m (surveyed 4,346 m)

    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:

    1. Duplication with devkit. Copy devkit's tilequery_tool here, move it here and keep devkit for developer/admin work, or share the code in a package?
    2. On by default? describe_tileset_tool and tilequery_tool are 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_tool itself is narrow ("how hilly", "how high"), so I'm planning to ship it on by default unless anyone objects.

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