Skip to main content
Glama

🌍 bbox-mcp-server

FREE Geospatial tools for AI agents, with results you can inspect on a map.

Search OpenStreetMap, convert coordinates, generate H3 grids, calculate routes, and sample terrain elevation. 10 MCP tools, no API keys required to get started. Spatial results include shareable links to the interactive map.

Node.js License: MIT

Try asking

  • “Find cafes near Times Square.”

  • “Find me pizza near the Colosseum?”

  • “Eiffel Tower to the Louvre: walk or bike? Compare the routes.”

  • “Where are Manhattan’s coffee hotspots?”

  • “EV road trip: find chargers within 5km of Monterey.”

  • “How high up is Denver, really?”

Related MCP server: Mapbox MCP Server

Quick start

Requires Node.js 18+. Add this to your MCP client configuration:

{
  "mcpServers": {
    "bbox": {
      "command": "npx",
      "args": ["-y", "bbox-mcp-server"]
    }
  }
}

Client

Configuration file

Claude Desktop

claude_desktop_config.json

Cursor

.cursor/mcp.json

Windsurf

~/.codeium/windsurf/mcp_config.json

VS Code (GitHub Copilot)

.vscode/mcp.json - use servers instead of mcpServers

Tools

Tool

What it does

get_bounds

Find, buffer, convert, and project bounding boxes across formats and coordinate systems.

get_h3_indices

Generate H3 cells for a bounding box or exact polygon boundary, including holes.

generate_share_url

Create a shareable map link for a bounding box.

reverse_geocode

Resolve coordinates to an address and OpenStreetMap details.

search_overpass

Find or count OSM features within an area, bounding box, or radius.

list_osm_tags

Find OSM tags by category using curated suggestions and Taginfo fallback.

aggregate_overpass_h3

Group OSM query results into H3 hexagons for density analysis.

calculate_route

Get driving, walking, or cycling distance, duration, and route geometry.

get_elevation

Get elevation for points or sample a terrain grid using the 90m Copernicus DEM.

spatial_calc

Calculate geometry relations, point containment, distance/bearing, and grid subdivisions offline.

Your MCP client discovers each tool's full parameter and output schemas automatically. H3 tools use resolution (0–15).

Inputs and outputs

Tools with a location parameter accept place names. Tools with a bbox parameter auto-detect raw coordinates, single points, z/x/y tiles, WKT, GeoJSON, GeoJSON bboxes, and ogrinfo extents.

Coordinate order: raw bboxes default to lat1,lng1,lat2,lng2; points use lat,lng. Use GeoJSON or WKT to avoid ambiguity, for example {"bbox":[-74.006,40.712,-73.985,40.758]} in west/south/east/north order. coord_order on get_bounds controls formatted output only.

get_bounds supports 3,900+ bundled projections via epsg and nine output formats: csv, wkt, geojson-bbox, geojson-polygon, leaflet, overpass, ogc-bbox, kml, and stac-bbox.

For Overpass searches, supply a selector such as nwr["amenity"="cafe"]; the server adds spatial filters. Set radius_meters for an explicit distance or omit it to search the area. Use list_osm_tags to find selectors by category.

Configuration

Place search uses Nominatim with Photon fallback; a Mapbox token is optional. Defaults work without configuration.

Add an env object alongside command and args in your server configuration.

Variable

Purpose / default

OSM_USER_AGENT

Identify your application and contact; defaults to the server name, version, and repository URL.

NOMINATIM_EMAIL

Optional contact email for Nominatim requests.

NOMINATIM_API_URL

Geocoder endpoint; defaults to https://nominatim.openstreetmap.org.

PHOTON_API_URL

Fallback geocoder; defaults to https://photon.komoot.io.

MAPBOX_ACCESS_TOKEN

Optional additional geocoding fallback.

OVERPASS_API_URL

Custom Overpass endpoint(s); defaults rotate across public instances.

OSRM_API_URL

Preferred routing endpoint; defaults use public OSRM services.

ELEVATION_API_URL

Elevation endpoint; defaults to https://api.open-meteo.com/v1/elevation.

MAX_H3_CELLS

H3 generation cap; defaults to 50000.

For developers

Successful calls return readable content and structuredContent matching the tool's output schema, including provenance, complete, and warnings. Spatial tools also return share_url. Errors use isError: true; structured logs go to stderr, keeping stdout reserved for MCP.

To run from source:

npm install
npm test
npm start

npm test builds the server and runs the test suite.

Data and service use

Data © OpenStreetMap contributors. Public services have usage limits: avoid bulk scraping and frequent polling, and configure your own endpoints for shared or heavy workloads.

  • Nominatim and FOSSGIS routing limit requests to 1 per second. Nominatim also requires application identification, caching, and attribution. The server's per-process queue does not cover traffic across multiple instances.

  • Photon's public endpoint is a demo service without availability guarantees.

  • Open-Meteo's free API is for non-commercial use. Elevation grids return sample statistics, not guaranteed terrain-wide extrema or slopes.

MIT License

Available Tools

10 tools
aggregate_overpass_h3A
Read-onlyIdempotent

Executes an Overpass query and bins the results into H3 hexagons at a specified resolution to analyze spatial density. Plots the top density hotspots on the shareable verification map.

NameRequiredDescriptionDefault
bboxNoThe bounding box geometry to parse.
queryYesThe Overpass QL core query (e.g. `nwr["amenity"="cafe"]`).
locationNoA text location to search for (e.g. 'Seattle').
resolutionYesThe H3 resolution level (0-15) for binning. Default is 8.
radius_metersNoOptional search radius in metres around the location/bbox center.
timeout_secondsNoOverpass server query timeout in seconds. Default is 25.
use_area_boundaryNoIf true (default), uses exact OSM boundary polygon for named locations when available.

Output Schema

NameRequiredDescription
completeYes
warningsYes
share_urlYes
hex_countsYes
provenanceYes
resolutionYes
hex_geojsonYes
osm_area_idNo
alternativesNo
matched_placeNo
original_bboxYes
total_elementsYes
active_hex_countYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds that results are plotted onto a 'shareable verification map', which hints at a persistent side effect not captured by the annotations, but it says nothing about Overpass timeout behaviour, query failures, or how many hotspots are retained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action (query + H3 binning) before the secondary output behaviour (hotspot plotting). No filler or redundant restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the oneOf location/bbox exclusivity is handled structurally by the schema. What remains thin is operational context around failure modes and the nature of the plotted map output, but overall the description is adequate for a seven-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter including query, resolution, bbox/location, radius_meters, timeout_seconds, and use_area_boundary is already documented in the schema. The description only echoes that resolution drives the binning and adds no format or default guidance beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names two concrete operations: executing an Overpass query and binning results into H3 hexagons at a resolution, plus plotting density hotspots. This is a specific verb+resource statement an agent can act on. It does not explicitly contrast with the sibling search_overpass or get_h3_indices, so differentiation is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the tool is for spatial density analysis rather than raw feature retrieval. There is no explicit statement of when to pick this over search_overpass (raw results) or get_h3_indices (index retrieval), and no prerequisites or exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

calculate_routeA
Read-onlyIdempotent

Calculate real-world travel distance, duration, turn-by-turn summary, GeoJSON route geometry, and route bounding box between two locations or coordinate pairs using OpenStreetMap routing (FOSSGIS / OSRM, or configurable OSRM_API_URL). Draws the actual route path on the verification map and enforces rate limits (max 1 req/s).

NameRequiredDescriptionDefault
originYesStarting point as 'lat,lng' coordinates (e.g. '40.7128,-74.0060') or a natural-language place name (e.g. 'Times Square, NYC').
profileNoTravel mode profile: 'driving' (car), 'walking' (foot), or 'cycling' (bicycle). Defaults to 'driving'.
destinationYesEnding point as 'lat,lng' coordinates (e.g. '40.6413,-73.7781') or a natural-language place name (e.g. 'JFK Airport').
return_stepsNoIf true, includes step-by-step road names and maneuver instructions. Defaults to false.

Output Schema

NameRequiredDescription
stepsNo
originYes
profileYes
completeYes
warningsYes
share_urlYes
provenanceYes
route_bboxYes
destinationYes
distance_kmYes
detour_factorYes
route_geometryYes
distance_metersYes
initial_bearingYes
duration_minutesYes
duration_secondsYes
straight_line_metersYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true and destructiveHint=false, so the safety profile is covered. The description goes beyond them with real operational detail: an external provider dependency (FOSSGIS/OSRM, overridable via OSRM_API_URL), a hard rate limit of max 1 req/s, and the side effect of drawing the path on the verification map. It stops short of describing failure behavior when a provider is unreachable or a place name fails to resolve.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the capability and outputs before the provider/rate-limit detail. Dense with little waste, though the trailing parenthetical about OSRM_API_URL and the map-drawing clause are secondary information that could be split or subordinated more cleanly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return values, and it correctly focuses on capability, data source, rate limits, and side effects. The main remaining gap for a 4-parameter open-world tool is failure and resolution behavior (what happens when a place name is ambiguous or the routing service errors), which the description leaves silent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including per-parameter docs for origin/destination formats, the profile enum, and return_steps, so the schema does the heavy lifting. The description adds only the notion that endpoints can be coordinates or place names and that turn-by-turn output exists, without adding format or edge-case detail beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource — 'Calculate real-world travel distance, duration, turn-by-turn summary, GeoJSON route geometry, and route bounding box' — and scopes it to 'between two locations or coordinate pairs'. It enumerates the outputs so an agent knows exactly what it gets, and no sibling tool (get_bounds, spatial_calc, search_overpass) covers routing, so the resource is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the phrase 'between two locations or coordinate pairs' hints at routing use cases, and the rate-limit note constrains call frequency, but there is no explicit when-to-use, when-not-to-use, or pointer to an alternative sibling (e.g. spatial_calc for straight-line distance, reverse_geocode for resolving place names). An agent must infer the routing niche itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_share_urlA
Read-onlyIdempotent

Generates a URL that links to the visual Bounding Box tool to display these coordinates on a map. Supports WKT, GeoJSON, ogrinfo extent, tile 'z/x/y', and raw coordinate strings as input.

NameRequiredDescriptionDefault
bboxYesThe geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT, GeoJSON, tile 'z/x/y', or ogrinfo extent.

Output Schema

NameRequiredDescription
bboxYes
completeYes
warningsYes
share_urlYes
provenanceYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuine context by identifying the output as a link into an external visual Bounding Box tool, which the annotations do not convey. It stops short of saying whether the URL is persistent, shareable across users, or has any length/expiry limits, which is the main behavioral question for a link-generating tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the purpose before the input-format details, with no filler. Minor waste: the format enumeration duplicates the bbox schema description almost verbatim, so the second sentence earns less than its length suggests.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only tool with a full output schema and complete annotation coverage, the description supplies what structured fields cannot: the destination and visual purpose of the generated URL. It leaves only secondary details (URL lifetime, sharing scope) unstated, which is a small gap rather than a blocking one.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the bbox parameter already enumerates the same accepted formats (raw lat/lng string, WKT, GeoJSON, tile z/x/y, ogrinfo extent). The description's second sentence largely restates that list without adding parsing rules, precedence between formats, or how ambiguous strings are disambiguated, so baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and artifact ('Generates a URL') plus the target ('visual Bounding Box tool to display these coordinates on a map'), which makes the outcome concrete. No sibling tool (get_bounds, spatial_calc, reverse_geocode, etc.) produces a shareable visualization link, so the agent can separate this tool from the rest of the family without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: 'display these coordinates on a map' hints the tool is for visual verification of a geometry, and the formats list hints at acceptable inputs. There is no explicit when-to-use/when-not, no statement of prerequisites, and no named alternative for cases where a machine-readable geometry is needed instead (e.g. get_bounds).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_boundsA
Read-onlyIdempotent

Get converted coordinates for a bounding box or natural-language location search (powered by Nominatim with configurable Photon & optional Mapbox fallbacks). Supports parsing WKT, GeoJSON, ogrinfo extent, Web Mercator tiles ('z/x/y'), single points ('lat,lng'), and raw coordinate strings, plus optional metric buffering.

NameRequiredDescriptionDefault
bboxNoThe geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), a single point ('lat,lng'), a Web Mercator tile ('z/x/y'), a WKT polygon/linestring/point, a GeoJSON payload, or an `ogrinfo` extent block. Either 'location' or 'bbox' MUST be provided.
epsgNoThe projected EPSG code (e.g. '3857'). Defaults to '4326' (WGS84). Over 3,900 bundled projections; unknown codes are auto-fetched from epsg.io.
zoomNoThe map zoom level (0-22) used to calculate the map tile coordinates for the centroid. Defaults to 15.
formatNoFormat of the output. Options: wkt, geojson-bbox, leaflet, overpass, ogc-bbox, kml, geojson-polygon, csv, stac-bbox. Default: csv.
locationNoA text location to search for (e.g. 'New York City', 'Central Park'). Uses OpenStreetMap Nominatim (or configurable NOMINATIM_API_URL / PHOTON_API_URL / optional MAPBOX_ACCESS_TOKEN). Either 'location' or 'bbox' MUST be provided.
precisionNoThe number of decimal places to output coordinate strings as (defaults to 6).
coord_orderNoToggle between 'lng,lat' (default) and 'lat,lng' coordinate ordering in the formatted output. Useful for APIs that expect swapped coordinate orders.
buffer_metersNoOptional distance in meters to expand (positive) or shrink (negative) the bounding box in all directions. Ideal for creating a bounding box around a single point.

Output Schema

NameRequiredDescription
epsgYes
centerYes
formatYes
area_km2Yes
completeYes
warningsYes
precisionYes
projectedYes
share_urlYes
dimensionsYes
provenanceYes
coord_orderYes
alternativesNo
tile_indicesYes
matched_placeNo
original_wgs84Yes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive) and openness, so the description's job is narrower and it delivers: it discloses the external dependency on Nominatim with configurable Photon/Mapbox fallbacks, and that unknown EPSG codes are auto-fetched from epsg.io — both network-facing behaviors an agent should know about. It does not mention latency, rate limits, or failure behavior when the geocoder misses.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single front-loaded sentence that leads with the primary capability and the two input modes, then the format list. It is dense and slightly run-on, and the format enumeration duplicates the bbox schema, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. Given the input schema, annotations, and output schema, the description supplies the remaining essentials: the external geocoding providers, the projection-source fallback, and the accepted geometry formats.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description restates the bbox input variants and 'optional metric buffering' (buffer_meters), but adds no syntax, defaults, or edge-case guidance beyond what the property descriptions already say; epsg, zoom, format, precision, and coord_order are untouched.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get converted coordinates') and names the two input modes it handles: a bounding box or a natural-language location search. An agent can tell this is a coordinate-conversion helper rather than a geocoder or route tool, though it never names a sibling (e.g. reverse_geocode) to draw the boundary explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the enumerated input formats (WKT, GeoJSON, ogrinfo extent, z/x/y tiles, 'lat,lng', raw strings) suggest when the tool fits, but there is no explicit 'use this when…' or 'use reverse_geocode instead when…' routing. With nine siblings including reverse_geocode and spatial_calc, the overlap remains for the agent to infer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_elevationA
Read-onlyIdempotent

Query terrain elevation in meters above sea level using the Open-Meteo 90m Copernicus DEM API (free for non-commercial use; commercial use requires a paid key or self-hosted ELEVATION_API_URL). Supports querying specific point coordinates OR sampling an N×N point grid across a bounding box to compute sample statistics (note: finite grid sampling over a 90m DEM reports sample statistics, not guaranteed area-wide true minimum, maximum, or slope).

NameRequiredDescriptionDefault
bboxNoA bounding box or point string to sample terrain elevation across.
pointsNoList of {lat, lng, label?} points to query elevation for (up to 100 points).
locationNoA text location to sample elevation across (e.g. 'Mount Rainier', 'Denver').
grid_sizeNoGrid dimension N (N x N samples, from 2 to 10) when sampling a bounding box. Defaults to 5 (25 sample points).

Output Schema

NameRequiredDescription
bboxYes
modeYes
samplesYes
completeYes
warningsYes
share_urlYes
provenanceYes
sample_countYes
sample_statsYes
matched_placeNo
dem_resolution_metersYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world), so the description is free to spend its words elsewhere — and it does: it discloses the licensing/auth constraint (free for non-commercial, paid key or self-hosted ELEVATION_API_URL otherwise) and, more importantly, that grid results are point-sample statistics, not guaranteed true extrema or slope. That caveat materially affects how an agent reports results. It doesn't mention rate limits or failure behavior for out-of-coverage coordinates.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, front-loaded with the core action and units before the licensing and sampling caveats. The nested parentheses are slightly heavy but every clause carries information the agent needs; nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and annotations carry the safety profile. The remaining gap is precedence: all four parameters are optional with three mutually alternative entry modes (points, bbox, location), and the description never states what happens if more than one is provided or what the fallback is — a real ambiguity for a zero-required-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents every parameter, which sets the baseline at 3. The description adds only the mode relationship (grid_size applies to bbox sampling) and the statistical meaning of those samples; it says nothing extra about how 'location' is resolved or what happens when multiple mode parameters are supplied together.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource with units and data provenance: 'Query terrain elevation in meters above sea level using the Open-Meteo 90m Copernicus DEM API', and names both operating modes (point coordinates vs N×N bbox grid). It doesn't explicitly contrast itself with any sibling, but none of the listed siblings (get_bounds, reverse_geocode, spatial_calc) overlap with elevation lookup, so misrouting risk is low.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'OR' framing tells the agent that point queries and grid sampling are alternative modes, and the parenthetical warns when grid sampling is the wrong basis for area-wide min/max/slope claims — genuine when-not guidance. It stops short of saying how to choose among the three entry parameters (points vs bbox vs location) or which takes precedence.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_h3_indicesA
Read-onlyIdempotent

Get Uber H3 cell indices for a polygon (including interior holes), location boundary, or bounding box at a target resolution. When a WKT/GeoJSON polygon or named location boundary is provided, fills the exact polygon geometry (subtracting interior holes) rather than just its bounding rectangle.

NameRequiredDescriptionDefault
bboxNoThe geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT polygon (with optional holes), GeoJSON polygon/multipolygon, tile 'z/x/y', or ogrinfo extent. Either 'location' or 'bbox' MUST be provided.
compactNoWhether to return a compacted list of cells (mixing resolutions) to minimize response size. Defaults to false.
locationNoA text location to search for (e.g. 'San Francisco'). Either 'location' or 'bbox' MUST be provided.
resolutionYesThe H3 resolution level, from 0 to 15. (e.g. 7)
summary_onlyNoIf true, returns only cell count, sample cells, and map share URL without dumping thousands of cell IDs into context. Ideal for high resolutions. Defaults to false.
return_geometryNoIf true, return GeoJSON FeatureCollection with hex boundary polygons in addition to cell IDs. Defaults to false.
use_polygon_boundaryNoIf true (default), fills the exact WKT/GeoJSON/OSM polygon boundary (including interior holes) instead of its rectangular bounding box when available.

Output Schema

NameRequiredDescription
cellsNo
compactYes
geojsonNo
completeYes
warningsYes
share_urlYes
cell_countYes
provenanceYes
resolutionYes
sample_cellsNo
summary_onlyYes
original_bboxYes
used_polygon_boundaryYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, and open-world behavior. Beyond that, the description usefully discloses that polygon and named-location inputs fill exact geometry including interior holes rather than only the bounding rectangle, which is relevant behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two front-loaded sentences with no filler. The core operation comes first, followed by the important geometry detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has seven parameters but full schema coverage, an output schema, and rich annotations. The description covers the core operation and the key polygon-hole behavior; only sibling differentiation is notably absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains bbox, location, resolution, compact, summary_only, return_geometry, and use_polygon_boundary. The description reinforces the polygon-versus-bbox behavior but adds little parameter meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: get Uber H3 cell indices for a polygon, location boundary, or bounding box at a target resolution. It clearly identifies the operation but does not differentiate this tool from siblings such as aggregate_overpass_h3 or get_bounds.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by naming accepted geometry inputs and the target resolution, so an agent can infer when the tool applies. However, it gives no explicit when-to-use versus alternatives guidance or exclusions for sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_osm_tagsA
Read-onlyIdempotent

Discovery tool to look up the correct OpenStreetMap tags for any category. Uses built-in category index and live Taginfo API fallback to prevent tag hallucination.

NameRequiredDescriptionDefault
categoryYesCategory or keyword to look up (e.g. 'food', 'ev charging', 'gym', 'coworking', 'banks', 'dog park').

Output Schema

NameRequiredDescription
tagsYes
sourceYes
categoryYes
completeYes
warningsYes
provenanceYes
recommendations_textYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, open-world and non-destructive, so the safety profile is covered. The description adds real context beyond that: results come from a built-in category index with a live Taginfo API fallback, telling the agent to expect external network-dependent lookups and that this is the sanctioned source of tag truth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the tool's role and its data sources front-loaded. Nothing is repeated from the annotations or schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and annotations carry the safety profile, leaving a simple one-parameter lookup. Minor omissions remain: behavior when a category is unknown, and whether the live API fallback affects latency or result variance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage and a single required parameter already exemplified in the schema ('food', 'ev charging', etc.), the schema does the work. The description only reinforces breadth ('any category') without adding format, matching, or normalization guidance beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: look up OpenStreetMap tags for a category, framed as a 'discovery tool'. That role contrasts implicitly with siblings like search_overpass (which runs queries) and reverse_geocode, though no sibling is named outright.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'For any category' implies the call context, and the anti-hallucination framing hints it should precede tag-dependent queries. There is no explicit when-not-to-use clause and no named alternative tool to route to instead, so the agent must infer the workflow position.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reverse_geocodeA
Read-onlyIdempotent

Reverse geocode latitude and longitude coordinates to discover context, place name, address components, and OSM details ('what is here?').

NameRequiredDescriptionDefault
latYesLatitude coordinate (-90 to 90).
lngYesLongitude coordinate (-180 to 180).
zoomNoDetail zoom level from 0 (country) to 18 (building/address). Defaults to 18.

Output Schema

NameRequiredDescription
bboxYes
typeNo
classNo
centerYes
osm_idNo
addressYes
completeYes
osm_typeNo
warningsYes
share_urlYes
provenanceYes
matched_placeYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld, and non-destructive, so the safety profile is covered. The description adds only the shape of the returned data, which is largely redundant with the existing output schema, and says nothing about rate limits, coverage gaps, or fallback behavior when no feature is found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the verb and resource first, then the output summary. The enumeration of return fields is slightly padded given an output schema already exists, but nothing is confusing or wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Parameters are fully documented, annotations cover the safety profile, and an output schema exists, so the description need not explain return values. The main remaining gap is sibling differentiation, which matters here because search_overpass and get_bounds operate near this query space.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including coordinate ranges and the zoom scale (0=country to 18=building/address). The description mentions only lat/lng and adds no meaning beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Reverse geocode latitude and longitude coordinates') and enumerates what it yields (place name, address components, OSM details). It is clear on its own, but it never distinguishes itself from siblings like search_overpass, which could also answer a 'what is here' question.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'what is here?' implies the query type this tool answers, giving implicit usage context. There is no explicit when-to-use statement, no prerequisites, and no routing to alternatives such as search_overpass for tag-based lookups.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_overpassA
Read-onlyIdempotent

Execute an Overpass QL query to find POIs, roads, or other OSM features within an admin boundary area, bounding box, or radius. The server wraps your query in spatial filters, detects Overpass runtime errors, and returns structured JSON with provenance, completeness metadata, distance calculations, and a map link.

SEARCH MODES:

  • Location / Admin Area: when 'location' resolves to an OSM boundary polygon (e.g. 'Manhattan', 'Seattle'), searches inside exact boundary polygon.

  • Bounding box (default): searches a rectangular area.

  • Circle: searches within an exact radius when 'radius_meters' is provided.

  • Fast Count: set 'count_only: true' to get instant element counts without downloading full element payloads.

COMMON TAG EXAMPLES:

  • Restaurants: nwr["amenity"="restaurant"]

  • Pizza: nwr["amenity"="fast_food"]["cuisine"="pizza"]

  • Supermarkets: nwr["shop"="supermarket"]

  • Parks: nwr["leisure"="park"]

  • Hospitals: nwr["amenity"="hospital"]

  • EV Charging: nwr["amenity"="charging_station"]

  • Gyms: nwr["leisure"="fitness_centre"]

  • Banks: nwr["amenity"="bank"]

NameRequiredDescriptionDefault
bboxNoThe geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT, GeoJSON, or ogrinfo extent. Either 'location' or 'bbox' MUST be provided.
limitNoMaximum number of elements to return per page. Default is 100.
queryYesThe Overpass QL core query. Example: `node["amenity"="cafe"]` or `nwr["leisure"="park"]`. Multi-statement queries supported (e.g. `nwr["office"="coworking"]; nwr["amenity"="coworking_space"]`). DO NOT include spatial filters or output directives.
offsetNoPagination offset for retrieving subsequent pages of results. Default is 0.
locationNoA text location to search for (e.g. 'Manhattan', 'San Francisco'). Either 'location' or 'bbox' MUST be provided.
count_onlyNoIf true, executes an ultra-fast Overpass 'out count;' query and returns total counts (nodes, ways, relations, total) without downloading individual features. Defaults to false.
radius_metersNoSearch radius in metres. Enables circle mode — use ONLY when explicit distance is specified ('2km' → 2000).
return_geometryNoIf true, returns full geometry (polygon/polyline) for ways and relations instead of center point. Defaults to false.
timeout_secondsNoOverpass server query timeout in seconds. Default is 25.
sort_by_distanceNoIf true, sorts returned elements by distance from origin/center. Enabled by default for circle mode and point locations.
use_area_boundaryNoIf true (default), uses exact OSM administrative boundary polygon for named locations when available, avoiding bounding box collapse.

Output Schema

NameRequiredDescription
limitNo
osm3sNo
countsNo
offsetNo
completeYes
elementsNo
has_moreNo
warningsYes
generatorNo
share_urlYes
truncatedNo
count_onlyYes
provenanceYes
next_offsetNo
osm_area_idNo
search_modeYes
total_countNo
alternativesNo
distance_fromNo
matched_placeNo
returned_countNo
pagination_hintNo

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/openWorld/non-destructive, yet the description still adds substantive behavior: the server wraps the query in spatial filters, detects Overpass runtime errors, and returns provenance, completeness metadata, distance calculations, and a map link. The note that the query is auto-wrapped with spatial filters materially changes how an agent should construct input.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and scope, then organized under two clear headers, with no filler sentences. The eight common tag examples are useful for syntax learning but become repetitive after the first three, which all follow the same nwr["key"="value"] pattern.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter, open-world query tool with a full output schema and complete annotation coverage, this is close to complete: modes, query construction rules, count fast-path, and return content are all covered. Minor gaps remain around pagination behavior across pages and what a partial/failed query looks like to the caller.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: the 'DO NOT include spatial filters or output directives' constraint on query, the '2km → 2000' unit interpretation for radius_meters, and the note that sort_by_distance is on by default for circle mode and point locations. The tag examples also teach valid Overpass QL syntax that the schema only gestures at.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource ('Execute an Overpass QL query to find POIs, roads, or other OSM features') plus the three supported spatial scopes. It is unambiguous what the tool does, but it never explicitly distinguishes itself from the closest sibling, aggregate_overpass_h3, which presumably wraps the same data source for H3 aggregation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The SEARCH MODES block gives clear conditional routing among location, bbox, circle, and count_only, and radius_meters carries an explicit 'use ONLY when explicit distance is specified' exclusion. What is missing is any guidance on when to prefer a sibling tool (e.g. aggregate_overpass_h3 for aggregation, list_osm_tags for tag discovery) over this raw search.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spatial_calcA
Read-onlyIdempotent

Perform deterministic offline geometric calculations on bounding boxes, points, and polygons (with holes, zero network calls): 'relation' (intersects, contains, overlap area %, union & intersection bbox between two geometries), 'point_in_geometry' (check if a point is inside a bbox or WKT/GeoJSON polygon respecting interior holes), 'distance_bearing' (exact Haversine distance, initial compass bearing, and midpoint between two points), or 'split_grid' (subdivide a bbox into an N x M grid of sub-bboxes for chunked queries).

NameRequiredDescriptionDefault
colsNoNumber of longitude columns for 'split_grid' (1-20, default 2).
rowsNoNumber of latitude rows for 'split_grid' (1-20, default 2).
pointNoPoint coordinates 'lat,lng' to test in 'point_in_geometry'.
bbox_aYesFirst geometry / bounding box (for 'relation', 'point_in_geometry', 'split_grid') or origin point 'lat,lng' (for 'distance_bearing').
bbox_bNoSecond geometry / bounding box (for 'relation') or destination point 'lat,lng' (for 'distance_bearing').
operationYesThe geometric operation to perform.

Output Schema

NameRequiredDescription
toNo
bboxNo
colsNo
fromNo
rowsNo
cellsNo
pointNo
insideNo
completeYes
midpointNo
warningsYes
operationYes
share_urlYes
area_a_km2No
area_b_km2No
intersectsNo
provenanceYes
union_bboxNo
distance_kmNo
inside_bboxNo
target_bboxNo
total_cellsNo
a_contains_bNo
b_contains_aNo
original_bboxNo
inside_polygonNo
union_area_km2No
bearing_degreesNo
distance_metersNo
intersection_bboxNo
cardinal_directionNo
overlap_percent_of_aNo
overlap_percent_of_bNo
intersection_area_km2No
centroid_distance_metersNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description adds genuine behavioral context beyond them: deterministic results, no network access, interior holes respected in containment tests, and grid bounds of 1-20 with default 2. It does not describe failure modes for malformed WKT or out-of-range rows/cols, but the added disclosure is substantive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then a single structured enumeration of the four operations. Dense with parenthetical detail but nearly every clause carries operational information; the one-sentence mega-structure is slightly harder to scan than a short bulleted layout would be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and all four operation modes plus their parameter roles are covered. What remains thin is edge-case behavior (invalid geometry input, behavior when bbox_a is a polygon for split_grid), which keeps it just short of fully complete for a six-parameter multi-mode tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description earns above it by clarifying geometry formats the schema leaves generic ('bbox or WKT/GeoJSON polygon', 'lat,lng' origin/destination) and by tying cols/rows to the split_grid subdivision semantics. The mapping of which parameter is consumed by which operation is spelled out in prose as well as schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('deterministic offline geometric calculations on bounding boxes, points, and polygons') and then enumerates the four operations with their outputs (overlap area %, union & intersection bbox, Haversine distance, N x M grid). The 'zero network calls' clause separates it from network-dependent siblings like reverse_geocode and search_overpass.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each operation name is paired with the condition that selects it (use 'relation' for two-geometry comparison, 'point_in_geometry' for point-in-polygon with holes, 'distance_bearing' for point pairs, 'split_grid' for chunked queries), which is effectively mode-selection guidance. It stops short of naming an explicit sibling alternative or stating when not to use it, so it is clear context rather than full when/when-not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv1.5.0
    • Changedaggregate_overpass_h34 fields changed
      • addedInput schema / properties / radius_meters
        Added value: +{
        +  "description": "Optional search radius in metres around the location/bbox center.",
        +  "type": "number"
        +}
      • addedInput schema / properties / timeout_seconds
        Added value: +{
        +  "description": "Overpass server query timeout in seconds. Default is 25.",
        +  "type": "number"
        +}
      • addedInput schema / properties / use_area_boundary
        Added value: +{
        +  "description": "If true (default), uses exact OSM boundary polygon for named locations when available.",
        +  "type": "boolean"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "active_hex_count": {
        +      "type": "number"
        +    },
        +    "alternatives": {
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "hex_counts": {
        +      "type": "object"
        +    },
        +    "hex_geojson": {
        +      "type": "object"
        +    },
        +    "matched_place": {
        +      "type": "string"
        +    },
        +    "original_bbox": {
        +      "properties": {
        +        "lat1": {
        +          "type": "number"
        +        },
        +        "lat2": {
        +          "type": "number"
        +        },
        +        "lng1": {
        +          "type": "number"
        +        },
        +        "lng2": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "lat1",
        +        "lng1",
        +        "lat2",
        +        "lng2"
        +      ],
        +      "type": "object"
        +    },
        +    "osm_area_id": {
        +      "type": "number"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "resolution": {
        +      "type": "number"
        +    },
        +    "share_url": {
        +      "type": "string"
        +    },
        +    "total_elements": {
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "resolution",
        +    "total_elements",
        +    "active_hex_count",
        +    "hex_counts",
        +    "hex_geojson",
        +    "original_bbox",
        +    "share_url",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Addedcalculate_route
    • Changedgenerate_share_url2 fields changed
      • changedInput schema / properties / bbox / description
        Previous value: -"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT, GeoJSON, or ogrinfo extent."New value: +"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT, GeoJSON, tile 'z/x/y', or ogrinfo extent."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "bbox": {
        +      "properties": {
        +        "lat1": {
        +          "type": "number"
        +        },
        +        "lat2": {
        +          "type": "number"
        +        },
        +        "lng1": {
        +          "type": "number"
        +        },
        +        "lng2": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "lat1",
        +        "lng1",
        +        "lat2",
        +        "lng2"
        +      ],
        +      "type": "object"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "share_url": {
        +      "type": "string"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "bbox",
        +    "share_url",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Changedget_bounds4 fields changed
      • changedInput schema / properties / bbox / description
        Previous value: -"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), a WKT polygon/linestring/point, a GeoJSON payload, or an `ogrinfo` extent block. The Minimum Bounding Rectangle (MBR) encapsulating the geometry will be extracted. Either 'location' or 'bbox' MUST be provided."New value: +"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), a single point ('lat,lng'), a Web Mercator tile ('z/x/y'), a WKT polygon/linestring/point, a GeoJSON payload, or an `ogrinfo` extent block. Either 'location' or 'bbox' MUST be provided."
      • addedInput schema / properties / buffer_meters
        Added value: +{
        +  "description": "Optional distance in meters to expand (positive) or shrink (negative) the bounding box in all directions. Ideal for creating a bounding box around a single point.",
        +  "type": "number"
        +}
      • changedInput schema / properties / location / description
        Previous value: -"A text location to search for (e.g. 'New York City'). Requires MAPBOX_ACCESS_TOKEN env var. Either 'location' or 'bbox' MUST be provided."New value: +"A text location to search for (e.g. 'New York City', 'Central Park'). Uses OpenStreetMap Nominatim (or configurable NOMINATIM_API_URL / PHOTON_API_URL / optional MAPBOX_ACCESS_TOKEN). Either 'location' or 'bbox' MUST be provided."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "alternatives": {
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "area_km2": {
        +      "type": "number"
        +    },
        +    "center": {
        +      "properties": {
        +        "lat": {
        +          "type": "number"
        +        },
        +        "lng": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "lat",
        +        "lng"
        +      ],
        +      "type": "object"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "coord_order": {
        +      "type": "string"
        +    },
        +    "dimensions": {
        +      "properties": {
        +        "height_km": {
        +          "type": "number"
        +        },
        +        "width_km": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "width_km",
        +        "height_km"
        +      ],
        +      "type": "object"
        +    },
        +    "epsg": {
        +      "type": "string"
        +    },
        +    "format": {
        +      "type": "string"
        +    },
        +    "matched_place": {
        +      "type": "string"
        +    },
        +    "original_wgs84": {
        +      "properties": {
        +        "lat1": {
        +          "type": "number"
        +        },
        +        "lat2": {
        +          "type": "number"
        +        },
        +        "lng1": {
        +          "type": "number"
        +        },
        +        "lng2": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "lat1",
        +        "lng1",
        +        "lat2",
        +        "lng2"
        +      ],
        +      "type": "object"
        +    },
        +    "precision": {
        +      "type": "number"
        +    },
        +    "projected": {
        +      "properties": {
        +        "xmax": {
        +          "type": "number"
        +        },
        +        "xmin": {
        +          "type": "number"
        +        },
        +        "ymax": {
        +          "type": "number"
        +        },
        +        "ymin": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "xmin",
        +        "ymin",
        +        "xmax",
        +        "ymax"
        +      ],
        +      "type": "object"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "share_url": {
        +      "type": "string"
        +    },
        +    "tile_indices": {
        +      "properties": {
        +        "x": {
        +          "type": "number"
        +        },
        +        "y": {
        +          "type": "number"
        +        },
        +        "z": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "x",
        +        "y",
        +        "z"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "original_wgs84",
        +    "projected",
        +    "center",
        +    "tile_indices",
        +    "epsg",
        +    "format",
        +    "coord_order",
        +    "precision",
        +    "area_km2",
        +    "dimensions",
        +    "share_url",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Addedget_elevation
    • Changedget_h3_indices5 fields changed
      • changedInput schema / properties / bbox / description
        Previous value: -"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT, GeoJSON, or ogrinfo extent. Either 'location' or 'bbox' MUST be provided."New value: +"The geometry to parse. Can be a raw bounding box string ('lat1,lng1,lat2,lng2'), WKT polygon (with optional holes), GeoJSON polygon/multipolygon, tile 'z/x/y', or ogrinfo extent. Either 'location' or 'bbox' MUST be provided."
      • changedInput schema / properties / location / description
        Previous value: -"A text location to search for (e.g. 'San Francisco'). Requires MAPBOX_ACCESS_TOKEN env var. Either 'location' or 'bbox' MUST be provided."New value: +"A text location to search for (e.g. 'San Francisco'). Either 'location' or 'bbox' MUST be provided."
      • addedInput schema / properties / summary_only
        Added value: +{
        +  "description": "If true, returns only cell count, sample cells, and map share URL without dumping thousands of cell IDs into context. Ideal for high resolutions. Defaults to false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / use_polygon_boundary
        Added value: +{
        +  "description": "If true (default), fills the exact WKT/GeoJSON/OSM polygon boundary (including interior holes) instead of its rectangular bounding box when available.",
        +  "type": "boolean"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "cell_count": {
        +      "type": "number"
        +    },
        +    "cells": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "compact": {
        +      "type": "boolean"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "geojson": {
        +      "type": "object"
        +    },
        +    "original_bbox": {
        +      "properties": {
        +        "lat1": {
        +          "type": "number"
        +        },
        +        "lat2": {
        +          "type": "number"
        +        },
        +        "lng1": {
        +          "type": "number"
        +        },
        +        "lng2": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "lat1",
        +        "lng1",
        +        "lat2",
        +        "lng2"
        +      ],
        +      "type": "object"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "resolution": {
        +      "type": "number"
        +    },
        +    "sample_cells": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "share_url": {
        +      "type": "string"
        +    },
        +    "summary_only": {
        +      "type": "boolean"
        +    },
        +    "used_polygon_boundary": {
        +      "type": "boolean"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "resolution",
        +    "compact",
        +    "summary_only",
        +    "used_polygon_boundary",
        +    "cell_count",
        +    "original_bbox",
        +    "share_url",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Changedlist_osm_tags2 fields changed
      • changedInput schema / properties / category / description
        Previous value: -"Broad category to look up (e.g. 'food', 'health', 'transport', 'leisure', 'retail')."New value: +"Category or keyword to look up (e.g. 'food', 'ev charging', 'gym', 'coworking', 'banks', 'dog park')."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "category": {
        +      "type": "string"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "recommendations_text": {
        +      "type": "string"
        +    },
        +    "source": {
        +      "type": "string"
        +    },
        +    "tags": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "category",
        +    "source",
        +    "tags",
        +    "recommendations_text",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Addedreverse_geocode
    • Changedsearch_overpass11 fields changed
      • addedInput schema / properties / count_only
        Added value: +{
        +  "description": "If true, executes an ultra-fast Overpass 'out count;' query and returns total counts (nodes, ways, relations, total) without downloading individual features. Defaults to false.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of elements to return. Default is 100. Increase if you need more results."New value: +"Maximum number of elements to return per page. Default is 100."
      • changedInput schema / properties / location / description
        Previous value: -"A text location to search for (e.g. 'San Francisco', 'JFK Airport'). Requires MAPBOX_ACCESS_TOKEN env var. Either 'location' or 'bbox' MUST be provided."New value: +"A text location to search for (e.g. 'Manhattan', 'San Francisco'). Either 'location' or 'bbox' MUST be provided."
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Pagination offset for retrieving subsequent pages of results. Default is 0.",
        +  "type": "number"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"The Overpass QL core query. Example: `node[\"amenity\"=\"cafe\"]` or `nwr[\"leisure\"=\"park\"]`. DO NOT include spatial filters, bounding box, or output directives — the server handles those automatically."New value: +"The Overpass QL core query. Example: `node[\"amenity\"=\"cafe\"]` or `nwr[\"leisure\"=\"park\"]`. Multi-statement queries supported (e.g. `nwr[\"office\"=\"coworking\"]; nwr[\"amenity\"=\"coworking_space\"]`). DO NOT include spatial filters or output directives."
      • changedInput schema / properties / radius_meters / description
        Previous value: -"Search radius in metres. Enables circle mode — use ONLY when the user specifies an explicit distance (e.g. '2km' → 2000, '500 metres' → 500, '1 mile' → 1609). Omit entirely for area/region queries or vague terms like 'near'."New value: +"Search radius in metres. Enables circle mode — use ONLY when explicit distance is specified ('2km' → 2000)."
      • addedInput schema / properties / return_geometry
        Added value: +{
        +  "description": "If true, returns full geometry (polygon/polyline) for ways and relations instead of center point. Defaults to false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / sort_by_distance
        Added value: +{
        +  "description": "If true, sorts returned elements by distance from origin/center. Enabled by default for circle mode and point locations.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / timeout_seconds
        Added value: +{
        +  "description": "Overpass server query timeout in seconds. Default is 25.",
        +  "type": "number"
        +}
      • addedInput schema / properties / use_area_boundary
        Added value: +{
        +  "description": "If true (default), uses exact OSM administrative boundary polygon for named locations when available, avoiding bounding box collapse.",
        +  "type": "boolean"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "alternatives": {
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "complete": {
        +      "type": "boolean"
        +    },
        +    "count_only": {
        +      "type": "boolean"
        +    },
        +    "counts": {
        +      "properties": {
        +        "nodes": {
        +          "type": "number"
        +        },
        +        "relations": {
        +          "type": "number"
        +        },
        +        "total": {
        +          "type": "number"
        +        },
        +        "ways": {
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "distance_from": {
        +      "type": "object"
        +    },
        +    "elements": {
        +      "items": {
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "generator": {
        +      "type": "string"
        +    },
        +    "has_more": {
        +      "type": "boolean"
        +    },
        +    "limit": {
        +      "type": "number"
        +    },
        +    "matched_place": {
        +      "type": "string"
        +    },
        +    "next_offset": {
        +      "type": "number"
        +    },
        +    "offset": {
        +      "type": "number"
        +    },
        +    "osm3s": {
        +      "type": "object"
        +    },
        +    "osm_area_id": {
        +      "type": "number"
        +    },
        +    "pagination_hint": {
        +      "type": "string"
        +    },
        +    "provenance": {
        +      "properties": {
        +        "attribution": {
        +          "type": "string"
        +        },
        +        "cache_age_ms": {
        +          "type": "number"
        +        },
        +        "cached": {
        +          "type": "boolean"
        +        },
        +        "data_timestamp": {
        +          "type": "string"
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "usage_policy": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "provider",
        +        "data_timestamp",
        +        "cached",
        +        "cache_age_ms"
        +      ],
        +      "type": "object"
        +    },
        +    "returned_count": {
        +      "type": "number"
        +    },
        +    "search_mode": {
        +      "type": "string"
        +    },
        +    "share_url": {
        +      "type": "string"
        +    },
        +    "total_count": {
        +      "type": "number"
        +    },
        +    "truncated": {
        +      "type": "boolean"
        +    },
        +    "warnings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "search_mode",
        +    "count_only",
        +    "share_url",
        +    "provenance",
        +    "complete",
        +    "warnings"
        +  ],
        +  "type": "object"
        +}
    • Addedspatial_calc
  2. 1 tool updatev1.2.5
    • Changedsearch_overpass4 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of elements to return. Helps prevent enormous JSON responses. Default is 100. Set to a higher number if you need more results."New value: +"Maximum number of elements to return. Default is 100. Increase if you need more results."
      • changedInput schema / properties / location / description
        Previous value: -"A text location to search for (e.g. 'San Francisco'). Requires MAPBOX_ACCESS_TOKEN env var. Either 'location' or 'bbox' MUST be provided."New value: +"A text location to search for (e.g. 'San Francisco', 'JFK Airport'). Requires MAPBOX_ACCESS_TOKEN env var. Either 'location' or 'bbox' MUST be provided."
      • changedInput schema / properties / query / description
        Previous value: -"The Overpass QL core query. Example: `node[\"amenity\"=\"cafe\"]` or `nwr[\"leisure\"=\"park\"]`. DO NOT include the bounding box `(S,W,N,E)` or output format (`out json`), the server handles that automatically."New value: +"The Overpass QL core query. Example: `node[\"amenity\"=\"cafe\"]` or `nwr[\"leisure\"=\"park\"]`. DO NOT include spatial filters, bounding box, or output directives — the server handles those automatically."
      • addedInput schema / properties / radius_meters
        Added value: +{
        +  "description": "Search radius in metres. Enables circle mode — use ONLY when the user specifies an explicit distance (e.g. '2km' → 2000, '500 metres' → 500, '1 mile' → 1609). Omit entirely for area/region queries or vague terms like 'near'.",
        +  "type": "number"
        +}
  3. 6 tool updatesv1.2.4
    • First observedaggregate_overpass_h3
    • First observedgenerate_share_url
    • First observedget_bounds
    • First observedget_h3_indices
    • First observedlist_osm_tags
    • First observedsearch_overpass

TDQS

A3.9/5.0

Scored across 10 tools

Disambiguation4/5

Most tools target clearly distinct operations (geocoding, reverse geocoding, H3 indexing, routing, elevation, share URLs). The main overlap is between search_overpass and aggregate_overpass_h3, which share the same Overpass query surface and differ only by H3 binning, and spatial_calc bundles four disparate modes into one tool. Descriptions do enough to steer selection, but these boundaries are the weak spots.

Naming Consistency4/5

Nine of ten names follow a predictable verb_noun pattern (get_h3_indices, get_bounds, search_overpass, list_osm_tags, calculate_route, get_elevation, generate_share_url). The exceptions are reverse_geocode (verb-first but noun-shaped) and spatial_calc (noun-only), both readable but minor deviations from the dominant convention.

Tool Count5/5

Ten tools is well within the sweet spot and each one maps to a distinct geospatial capability. No tool feels redundant enough to remove, and the surface is not padded with trivial variants.

Completeness4/5

The surface covers the full stateless geospatial workflow: coordinate parsing/forward geocoding, reverse geocoding, tag discovery, POI search, density aggregation, H3 indexing, routing, elevation, offline geometry, and map sharing. Gaps are minor — no batch/bulk geocoding, isochrone/route-matrix operations, or explicit GeoJSON export are present, but agents can work around these via existing tools.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    AI agents hallucinate math. Euclid fixes that. Connect once and give your agent 10 deterministic tools: arithmetic, unit conversion, statistics, datetime, finance, regex, color, encoding, validation, and geospatial. Same input, same output, every time.
    2
    -
  • A
    license
    A
    quality
    D
    maintenance
    Geospatial API tools for AI agents — geocoding, reverse geocoding, routing, isochrone, distance matrix, static maps, H3 hexagons, elevation, GPS map-matching, point-in-polygon, address normalisation, timezone lookup, and batch geocoding. Built on OpenStreetMap infrastructure. Cost-effective alternative to Google Maps API.
    18
    39 npm
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    Enables AI agents to become geospatially intelligent assistants with tools for location search, smart routing, round trip planning, reverse geocoding, isochrone analysis, route visualization, geofence management, and interactive map display.
    8
    17 npm
    7
    Apache 2.0