PlaceRoot
PlaceRoot is an MCP server that answers real-world spatial questions from open map data β no API key β with compact, ranked results for agents.
π Search & identify: find places by category/brand/name near a point, inside an administrative boundary, or within a reachability shed; geocode/reverse-geocode, resolve stable GERS ids, batch lookups, and category search.
π Area analysis: summarize and compare neighborhoods, land use, buildings, infrastructure/water, changes over time, and get life-decision neighborhood verdicts.
π΄ Routing & reachability: real street-graph routes, travel-time matrices, isochrones, multi-stop route optimization, places along a route, fair meeting points, and reachability-filtered search.
πΊοΈ Geometry & maps: render interactive HTML maps, simplify GeoJSON, and run geometry operations like buffers, intersections, and point-in-polygon tests.
βοΈ Utilities: warm up a city cache, set persistent travel preferences, check the active data version, verify listing claims, and get a one-call orientation snapshot of any location.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PlaceRootWhat's around downtown Palo Alto?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PlaceRoot grounds AI agents in open map data. It's an MCP server that answers spatial questions β what's nearby, what's in this neighborhood, how do I get there β from Overture Maps open data. No API key, no signup, no vendor platform.
An independent project by vibemapper.
π― Answers, not data dumps. Every tool returns compact, ranked results sized for an agent's context window β never a raw GeoJSON dump.
πΊοΈ Real routing, zero keys.
routeandisochronewalk an actual street graph built from Overture's transportation segments β not a straight-line guess β anywhere on Earth.πΆ Reachability-filtered search.
find_places(..., within={"minutes": 15, "mode": "walk"})keeps only results truly inside the street-graph walk/cycle/driveshed β not a radius that guesses at it, and not a second call to intersect a polygon yourself.ποΈ Rich, filterable place data. Category, brand, confidence, operating status, contactability β sourced from Overture's open dataset (contributed by Meta, Uber, TomTom, and others).
π Boundary-accurate. Search inside a named place's real administrative polygon, not a guessed radius circle.
β‘ Zero setup. Reads Overture's public data directly β no key, no database, nothing to install beyond the server itself.
Quick start
Run it straight from PyPI or npm β no install step:
uvx placeroot # stdio MCP server
uvx placeroot --http # HTTP endpoint at http://127.0.0.1:8321/mcpclaude mcp add placeroot -- uvx placerootAdd to your claude_desktop_config.json:
{
"mcpServers": {
"placeroot": {
"command": "uvx",
"args": ["placeroot"]
}
}
}Same config as above wherever your client keeps its MCP server list. Prefer npm? Use "command": "npx", "args": ["placeroot"].
{
"mcpServers": {
"placeroot": {
"command": "npx",
"args": ["placeroot"]
}
}
}Then ask your agent something spatial:
"What's around downtown Palo Alto?" Β· "Compare these two neighborhoods for a bike shop." Β· "Plan my errands: pharmacy, hardware store, post office."
Related MCP server: chuk-mcp-geocoder
What it can do
44 tools, grouped into four families β every answer fits in a couple of thousand tokens:
Family | Tools | Answers questions like |
π Search & identify |
| What cafΓ©s are near this point? Coffee near the Eiffel Tower? |
π Area analysis |
| What's in this neighborhood, should I live here, and how does it differ from that one? |
π΄ Routing |
| How far to walk from A to B? What's reachable in 15 minutes? Best order for 6 stops? Which streets did this GPS trace actually take? |
πΊοΈ Geometry & maps |
| Show me this result as an interactive map |
It also ships seven workflow prompts (site selection, neighborhood comparison, errand planning, should I live here, get to know my city, verify listing claims, plan area visit) and three attachable resources β and a PLACEROOT_TOOLS setting to load only the tool profiles you need, cutting schema overhead by up to 95%.
π Full tool catalog, prompts, resources & configuration β docs/REFERENCE.md
Open data has honest limits: no live traffic, no opening hours, no ratings or photos βwhat PlaceRoot deliberately doesn't do. For everything else about where things are and what's reachable from them, it answers without a key.
Why PlaceRoot
It's the only keyless MCP server doing real graph routing over global open map data β with every tool declaring proper MCP annotations so clients know which calls are read-only before prompting you. Stable GERS ids let agents hold onto places across turns; local caching makes repeat queries answer in milliseconds and keeps working offline; and the whole thing is self-hostable end to end.
How it stacks up against Mapbox MCP and Google Maps MCP: head-to-head benchmarks Β· token-efficiency numbers.
Recreation places
Overture's places theme is derived from business listings, which makes it strong on businesses and thin on the places a family goes on a Saturday β playgrounds, neighbourhood parks, dog parks, beaches. Those features aren't missing from Overture, though; they're in a different theme. Overture's base theme is a direct conflation of OpenStreetMap, and PlaceRoot already queries it for land_use_at and infrastructure_at. The places tools read it too, by default.
Nothing is downloaded, built, or hosted β it's one more live scan of the same public Overture release, and it roughly 2.5xes playground coverage (1,552 vs 674 across New York City in release 2026-07-22.0, with 1,013 of them more than 150 m from any places-theme playground). Every places tool answers from both at once, with no other change: same tools, same response shape, same category filters.
The cost is a second dataset scan per places query (cached like everything else), and these rows carry no confidence or operating_status and are often unnamed β an unnamed playground comes back with name: null rather than being dropped. If you'd rather have the latency than the coverage:
export PLACEROOT_RECREATION_LAYER=0data_version reports the layer whenever it's active. Full details, including why live Overpass queries and raw OSM Parquet were measured and rejected: docs/RECREATION.md.
Development
uv sync # install dev dependencies
uv run pytest # offline test suite
uv run ruff check .See CONTRIBUTING.md for dev setup, design rules, and how to propose a tool. Other docs: CHANGELOG Β· SECURITY Β· publishing Β· website Β· running a data mirror Β· the recreation layer
Contact
hello@placeroot.dev
Developed by vibemapper.
Privacy Policy
PlaceRoot runs on your machine β no account, no API key, no sign-up. It has no telemetry and sends nothing to us; the only network traffic is your own queries going straight to Overture Maps' public data on AWS S3 (or a mirror you configure). Full details: placeroot.dev/privacy.html.
License and attribution
The code is MIT. The data it queries is the Overture Maps public release, licensed per theme β places under CDLA-Permissive-2.0; the OSM-derived themes (divisions, transportation, base) under ODbL, which asks for attribution on anything user-facing you build from them:
Β© Overture Maps Foundation Β· Β© OpenStreetMap contributors (ODbL)
Per-theme obligations: docs/DATA-LICENSE.md.
mcp-name: io.github.chuofringer/placeroot
Available Tools
42 toolsaddress_atNearest street addresses to a pointARead-onlyIdempotent
Nearest street addresses to a point, nearest first: number, street, unit, postcode.
The address-level counterpart to reverse_geocode (issue #188): where
that returns one collapsed hop plus the admin chain, this returns the
few doorways around the point with the attributes an address lookup
wants. Returns {"results": [{number, street, unit, postcode,
postal_city, address_levels, country, distance_m}, ...]}, capped at 5.
Optional attributes are omitted when the source has no value for them.
No id is returned: Overture documents address ids as not GERS-stable, so
unlike a place/division/building id there is no durable handle to hand
out. For a stable reference to what is at a coordinate, use
reverse_geocode and hold onto the division it names.
Coverage is the thing to read carefully. The addresses theme is
Overture's only alpha theme and covers 39 countries β no UK, Ireland,
India, China, Korea or Russia, no Africa or Middle East, and little of
Latin America outside Brazil, Mexico, Chile, Colombia and Uruguay. An
empty results list is a valid answer, never an error, and always carries
a "note" saying whether the country is outside the theme's coverage
entirely or is covered but had nothing within the search radius. That
country is the one whose division polygon contains the point, so the note
stays correct next to a border; if the lookup behind it cannot run, the
note says so rather than asserting anything about the data.
Returns a structured {"error": ...} if upstream is unavailable, if the
dataset is missing the bbox/street columns this depends on, or for an
out-of-range coordinate.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only/idempotent annotations, the description discloses important behavior: optional attributes are omitted when absent, empty results are valid and carry an explanatory note, structured errors are returned for upstream/data/coordinate issues, and no id is returned because ids are not GERS-stable. This is substantial extra context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but each paragraph earns its place: output format, relation to siblings, id stability, coverage caveats, and error behavior. The most important 'nearest first' detail is front-loaded, and the return shape is given concretely.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the return shape, ordering, optional-field omission, result cap, coverage limitations, empty-result semantics, error cases, and the no-id policy. Given the tool's complexity and the annotations provided, nothing critical is missing for correct invocation and interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the tool description must explain lat, lon, and limit. While it mentions 'a point' and says results are capped at 5, it never explicitly names or explains the limit parameter, its default, or coordinate constraints. This leaves meaningful ambiguity for a 3-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: returns nearest street addresses to a point, ordered nearest first, with the exact fields returned. It also explicitly distinguishes itself as the address-level counterpart to reverse_geocode, so an agent can tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: use this when you want doorway-level address attributes near a point, and use reverse_geocode when you need a stable reference via the division. It also warns about coverage gaps, making it clear when results should not be expected.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
admin_lookupAdmin hierarchy lookupARead-onlyIdempotent
Containing admin hierarchy for a point: neighborhood up to country.
Point-in-polygon against Overture's divisions theme. Returns {"chain":
[{"name": ..., "type": "locality", "id": ...}, ...]} smallest division
first (e.g. neighborhood, then locality, county, region, country) β an
empty chain means no division in the active dataset contains the
point, which is a valid answer for remote areas, not an error. Returns
a structured {"error": ...} if upstream is unavailable or the divisions
dataset is missing the geometry column this tool depends on.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, the description discloses result ordering, the meaningful empty-chain case, and structured error behavior for upstream or dataset schema failures. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: purpose, method, output shape, ordering, empty-result meaning, and errors are each covered in a useful sentence. There is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover safety and idempotence, the description still supplies the important contextual details: hierarchy order, empty chain as a valid answer, and failure modes. An agent has enough to call and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema coverage, the description's 'point' and 'point-in-polygon' wording clarifies that lat/lon are a geographic coordinate pair. However, it does not specify coordinate system, decimal-degree format, or valid ranges, so parameter meaning is only partially compensated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the tool returns the admin hierarchy for a point from neighborhood up to country, and names the point-in-polygon method against Overture's divisions theme. This is specific enough to distinguish it from reverse_geocode, address_at, and other sibling lookup tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use case is explicit: given a lat/lon point, get the chain of containing administrative divisions. It does not explicitly name alternatives or exclusion cases, but the scope is clear and edge-case semantics are explained.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
buildings_atBuildings near a pointARead-onlyIdempotent
Nearest building footprints to a point, nearest first.
From Overture's buildings theme (issue #23). Returns {"results": [{id
(GERS), subtype, class, footprint_area_m2, height_m, num_floors,
distance_m}, ...]}. No raw geometry by default (design rule: answers,
not data) β pass include_geometry=true to also get each row's
footprint as GeoJSON, simplified to a small per-row token cap (each row
then also carries geometry_max_deviation_m, reporting what was lost).
Returns a structured {"error": ...} if upstream is unavailable or the
dataset is missing geometry/bbox.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| limit | No | ||
| radius_m | No | ||
| include_geometry | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is fully covered. The description adds valuable behavioral context beyond annotations: it discloses the no-raw-geometry-by-default design rule, the include_geometry=true caveat with token cap and geometry_max_deviation_m reporting, and the structured error behavior when upstream is unavailable or dataset is missing geometry/bbox. That is more than annotations provide. Not a 5 because it doesn't mention pagination or ordering ties, but the disclosed behaviors are meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately sized but every sentence earns its place: the return shape, the no-geometry design rule, the include_geometry consequences, and the error case are all covered. It front-loads the core purpose and leads with the most important semantic ('nearest first'). Slightly dense parenthesis nesting costs a little readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given annotations cover safety and idempotence, the output schema is explicitly illustrated in the description, and the tool is a simple point-query with 5 params, the description is complete. It even discloses edge cases (upstream unavailable, missing geometry/bbox) and the design rule behind default behavior. An agent can call this correctly without additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden. It explains include_geometry in detail and implies radius_m and limit via 'nearest ... nearest first', but doesn't specify units for radius_m (meters are inferable from the name), default/range semantics, or limit semantics beyond a list length. With 5 params at 0% coverage, a 3 is the minimum viable; the description compensates for the most important parameter but leaves lat/lon/radius_m/limit to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Nearest building footprints to a point, nearest first') and differentiates from siblings: it's clearly a point-query tool (like infrastructure_at, land_use_at, water_near) targeting building footprints. The scope is unambiguous: buildings near a point, not places, infrastructure, or areas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the design rule ('answers, not data') and the optional include_geometry behavior, giving context for when to use the default versus when to pass the flag. It doesn't explicitly name alternatives or exclusions like infrastructure_at for non-building features, but the phrasing 'building footprints' and the sibling list imply the boundary. Slight gap: no explicit 'use X for other features' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
changes_in_areaChanges in areaARead-onlyIdempotent
What's opened or closed around here since a past Overture release.
Use this for "what's new around here", "what's closed since spring",
or any question with a time dimension β every other tool here answers
against a single, current snapshot of the data; this is the only tool
that compares two.
Area, exactly one of:
- place: a free-text area name ("Palo Alto"), resolved with this
server's usual free-text area matching (prominence-ranked, "City,
ST" suffix aware). The resolved division is echoed back as "area"
on the response. A name
matching several equally-ranked divisions returns {"error":
"ambiguous_area", "candidates": [...]} rather than silently picking
one; an unresolvable name returns {"error": "not_found"}. If the
resolved division is too large to diff (bigger than this tool's
per-side degree cap β countries, large regions), returns a
{"error": "bad_request"} naming the area and suggesting a smaller
one (a neighborhood or district instead of a whole city/region) or
an explicit bbox.
- min_lon/min_lat/max_lon/max_lat: an explicit bbox (all four
together, or none) β for when the caller already has coordinates
rather than a name. Same size cap as the named-area path.
category, when given, filters both releases' scans identically before
diffing β see diff_places; a place that changed OUT of the category
between releases reads as "disappeared" from this filtered view, which
is the correct reading of "restaurants that changed", not a bug.
from_release/to_release: Overture release strings (YYYY-MM-DD.N). Omit
both to diff the previous release against the ACTIVE one β to_release
defaults to release.resolve_release(), the same release every other
tool in this conversation queries (env pins included), and
from_release defaults to the newest listed release older than it: an
adjacent, recent window. Not the oldest release Overture still serves
β years-old releases are schema-drifted enough that most compared
columns NULL out and everything reads as "changed"; pass explicit
releases for a wider window, and check "degraded_fields" on the
response when you do. Pass both to pick a
specific window; passing only one is a {"error": "bad_request"}. When
the release listing is reachable, an explicit release not in it is
also a {"error": "bad_request"} rather than a silent typo'd diff; when
the listing itself is unreachable (network trouble), explicit releases
are tried directly instead β they may still resolve even though the
list couldn't be built.
If neither release is given and no listed release is older than the
active one (a listing failure, or a world with only one live release),
this returns a structured {"error": "upstream_unavailable"} naming
whatever releases WERE found β never an empty diff that would read as
"nothing changed here" when the real answer is "the window couldn't be
built".
limit caps how many ranked rows each of appeared/disappeared/changed
carries (default 8, hard cap 25 β the same per-answer row bound every
other tool here uses); "counts" and the "*_by_category" breakdowns are
never reduced by it.
Returns a compact digest, not the full diff: headline "counts"
(appeared/disappeared/changed/unchanged, always exact within the
scanned bound), a `limit`-capped ranked slice of each of
appeared/disappeared/changed (id, name, category, confidence, lat,
lon β changed rows carry old_name/new_name and
old_category/new_category instead of name/category), a small
per-bucket "*_by_category" breakdown computed over everything the
scans saw (same denominator as "counts", not the limit-capped slice),
the "releases" window actually used, "degraded_fields" when either
release's schema is missing a compared column (that field was NULL on
that side, so treat "changed" with suspicion), and
"truncated"/"omitted_count" when more exists than fits
(omitted_count sums omissions across the three lists).
Honest framing (issue #309): a "notes" list is attached whenever it
applies β a disappearance may be delisting or data cleanup, not a
closure; an appearance may be newly-mapped, not newly-opened. Neither
claim is inferable from this data alone, so the digest says so rather
than implying otherwise.
Returns a structured {"error": ...} if upstream is unavailable or the
active places dataset is missing the id/bbox columns this tool depends
on, for either release.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| place | No | ||
| max_lat | No | ||
| max_lon | No | ||
| min_lat | No | ||
| min_lon | No | ||
| category | No | ||
| to_release | No | ||
| from_release | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description's job is to add behavioral context β and it does so richly. It discloses structured error modes (ambiguous_area with candidates, not_found, bad_request for oversized areas and partial release pairs, upstream_unavailable), the default release window resolution, degraded_fields schema-drift behavior where 'everything reads as changed', truncation/omitted_count semantics, and the honest-framing 'notes' caveat that a disappearance may be data cleanup rather than a closure. This goes far beyond what annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and usage before parameter detail, and organized into clear paragraphs per parameter group. It is lengthy, but every section carries substantive content. Minor redundancy exists β degraded_fields is mentioned both in the release-window guidance and in the return-format section, and the final error paragraph restates upstream_unavailable behavior already described β but for a 9-parameter tool with 0% schema coverage, this depth is largely earned rather than padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool of this complexity (9 params, release-window semantics, size caps, multiple error modes, nuanced return digest), the description covers every dimension an agent needs: parameter semantics, defaults, edge cases, error contracts, truncation behavior, and interpretive caveats about what appeared/disappeared actually mean. Even though an output schema exists, the description adds semantic nuance (exact counts, by_category denominators, degraded_fields warnings) that structured schemas cannot express. Nothing needed for correct invocation or result interpretation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for all 9 parameters β and it does so exhaustively. place gets free-text resolution semantics plus ambiguous/not_found error behavior; the four bbox params get their all-or-none constraint and size cap; category gets its both-sides-identically filter semantics and the 'disappeared' interpretation; from_release/to_release get defaults, validation rules, and the partial-passing bad_request; limit gets its default (8), hard cap (25), and the fact that counts/by_category are never reduced by it. No parameter is left to schema inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific, verb-driven statement of what the tool does: 'What's opened or closed around here since a past Overture release.' It then explicitly distinguishes itself from every sibling: 'every other tool here answers against a single, current snapshot of the data; this is the only tool that compares two.' An agent can immediately tell this apart from compare_areas (two areas, one snapshot) and find_places (one snapshot, no time dimension).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete example queries ('what's new around here', 'what's closed since spring') and an explicit selection rule: any question with a time dimension belongs here because no other tool compares two releases. It also implicitly gives the when-not-to-use condition (single-snapshot questions should go elsewhere) and later warns against too-large areas, routing the caller to a neighborhood/district or bbox instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_areasCompare areasARead-onlyIdempotent
Compare 2-5 areas side by side: category mix, density, and what differs.
areas is a list of centers sharing one radius_m, each a {"lat": ...,
"lon": ...} dict, a GERS id, or a free-text place/area name, mixed
freely β a named area compares the same radius_m circle around its
resolved point as a coordinate would (not its actual boundary; that's a
later feature). An id/name that failed to resolve returns an indexed
error (areas[i]: ...) with candidates on ambiguity. Any area given by
id/name adds "resolved": [{"index": i, "name", "id", "lat", "lon",
"matched_by"}, ...] for just those areas; absent when every area was
already coordinates. Returns per-area total_places, place density per
km^2, and category_counts aligned across areas for the top ~10
categories by combined count, plus "differentiators" β those categories
ranked by how much they differ, relatively, between areas (the fastest
way to answer "how is area A different from area B"). Returns a
structured {"error": ...} if areas isn't 2-5 centers, or if upstream is
unavailable or the dataset is missing columns this tool depends on for
any area (a partial comparison is not returned).
priorities (optional, up to 6) turns the comparison into a scored
verdict: each entry is {"label": your own term for the criterion,
e.g. "competition"; "category": an Overture taxonomy slug, or
"__density__" for overall place density as a foot-traffic proxy;
"prefer": "more" | "fewer"; "weight": 0.1-5, default 1}. Each area's raw
measure per priority is that category's count (or density) within
radius_m β matched exactly against the category taxonomy (slug plus its
descendants, so "park" never counts parking garages) and counted
explicitly even for categories outside the top-10 alignment above; the
per-priority winner is whichever area is better on that raw measure (a
tie has no winner for that priority); each area's verdict score is the
weight-summed share of each priority normalized against the best area
(measure/max for "more", min/measure for "fewer" β the best area always
gets 1.0, and every area measuring 0 makes all shares 1.0), and the
highest score wins overall (a tie leaves winner_idx null). Adds (never
replaces) "verdict": {"winner_idx", "scores", "reasons" (one sentence
per priority), "margin", and a fixed "measured_note"} β the note,
always present when priorities are given, states plainly that these are
open-data place counts/density, never revenue, rent, actual foot
traffic, or demographics, and that "__density__" is only a proxy. If
the dataset's category columns are all degraded, count-based priorities
can't be measured and the verdict comes back with null winner_idx and
scores plus "degraded": true rather than a fabricated score. Returns
bad_request for more than 6 priorities or a malformed one (missing
label/category, an unrecognized prefer, or a non-numeric weight).
When priorities produced a verdict, the response also carries "map"
(#369) β a render-ready payload, keyword-splattable straight into this
server's map-rendering tool (its keys are exactly that tool's keyword
arguments): a pin per area (the winner picked out by class), a cheap
circle outline per area (radius_m, not a real boundary) labeled with
its score, and a one-line summary restating the winner. Absent when
priorities weren't given, or a verdict couldn't be scored.
| Name | Required | Description | Default |
|---|---|---|---|
| areas | Yes | ||
| radius_m | No | ||
| priorities | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only and idempotent; the description adds substantial extra behavior: resolution errors, GERS/name fallback, structured errors, degraded verdict behavior, caveats about boundary vs radius, and a map payload that splats into render_map. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long, but it is organized into coherent paragraphs (core result, priority scoring, map payload) and front-loads the purpose in the first sentence. Every major behavior is concretely specified; the length is mostly earned, though it could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is exhaustive for this tool's complexity: it documents input formats, edge cases, error behavior, scoring formulas, degraded-data behavior, and integration with render_map. Given the rich nested behavior and sparse schema, nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden. It fully explains areas (dict, GERS id, or name), the shared radius_m, and every field of priorities, including constraints like up to 6, weights 0.1-5, and valid prefer values. This is exemplary compensation for the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the verb and resource: compare 2-5 areas side-by-side, with specific dimensions (category mix, density, differences). It is unambiguous and distinct in behavior, but it does not explicitly contrast this tool with sibling tools such as summarize_area or changes_in_area.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context is very clear: use this when comparing 2-5 centers, and it details optional priority-based scoring. It does not explicitly state when not to use it or name alternative tools, so it misses full alternative routing, but the intended scenario is obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
data_versionData versionARead-onlyIdempotent
Which Overture Maps release backs the answers from every other tool.
Reports the active release string, its date, and whether it came from
live S3 discovery, an operator env override, or the pinned fallback
baked into this build. Resolved once at process start and cached for
the process lifetime β this tool just reports that cached value, it
doesn't re-check upstream, so it's small and has no upstream DB
dependency.
The body is resources.data_version_payload(), shared verbatim with the
placeroot://data-version MCP resource so the two surfaces cannot drift
(issue #195); tests/test_resources.py asserts they stay equal.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavior beyond the annotations: values are resolved once at process start, cached for the process lifetime, and not re-checked upstream. It also explains the three possible provenance sources and its shared implementation with the placeroot resource, giving an agent accurate expectations about freshness and reliability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded, with the purpose stated in the first sentence and each following sentence adding meaningful detail: output fields, caching behavior, and alignment with the resource surface. No sentence is filler or redundant with the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only, idempotent tool with an output schema, the description is complete. It explains what the value reports, how it was resolved, its stability, and its relationship to the data-version MCP resource, leaving no practical gap for an agent deciding whether or how to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema is empty, so there is nothing for the description to clarify about arguments. The description instead explains what the report contains, which is all that is needed for a parameterless informational tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise, non-generic statement: 'Which Overture Maps release backs the answers from every other tool.' It then names the exact outputs (release string, date, provenance), making the tool's function unmistakable and clearly distinct from the geographic sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly frames when to use the tool: whenever an agent needs to know the underlying Overture release behind all other tools. It does not explicitly name alternatives, but no sibling offers this function, and it adds exclusions by noting the tool does not re-check upstream, clarifying it is not a live-source lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
distance_matrixDistance matrixARead-onlyIdempotent
Straight-line (great-circle) distance in meters between every origin and destination.
origins and destinations are each a list of LocationRefs β a {"lat":
..., "lon": ...} dict, a GERS id, or a free-text place name, mixed
freely β capped at 10 each (100 pairs max). This is a plain haversine
calculation, not a routed distance or travel time, so it's cheap but it
is NOT what Google/Mapbox distance-matrix APIs return: no roads, no
turns, no travel time. For "how far can I get in N minutes" use
isochrone() instead; for actual routed times/distances between several
points use travel_time_matrix().
An id/name that failed to resolve returns an indexed error
(origins[i]: ... or destinations[i]: ...) with candidates on ambiguity
β checked after the 10-point cap, so an over-cap list always fails on
the cap first. Any origin/destination given by id/name adds "resolved":
{"origins": [{"index", "name", "id", "lat", "lon", "matched_by"}, ...],
"destinations": [...]} covering just those entries; each side is
present only if it had a string entry, and the whole key is absent when
every point was already coordinates.
Returns {"elements": [{"origin_idx": 0, "dest_idx": 0, "distance_m":
812}, ...]}, flat and origin-major (all destinations for origin 0,
then origin 1, ...), budgeted like every other tool. Empty origins or
destinations returns {"elements": []}. Returns a structured {"error":
"bad_request", ...} instead of raising if either list exceeds 10
points or a point is missing/non-numeric lat or lon.
| Name | Required | Description | Default |
|---|---|---|---|
| origins | Yes | ||
| destinations | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the description adds substantial behavioral context beyond that: the 10-point cap with 100-pair limit, error handling for unresolved names with indexed errors and ambiguity candidates, check ordering (cap fails first), the 'resolved' field behavior, flat origin-major return order, empty-input handling, and structured bad_request errors. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place. The first sentence front-loads the core function, then paragraphs cover scope limits, alternatives, error semantics, resolved-field behavior, output format, and edge cases. There is no fluff or repetition; dense paragraphs are organized by topic.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the output schema being present, the description also details the return shape and ordering, covers empty input, error behavior, id/name resolution, and budget hints. With sibling differentiation and clear parameter semantics, nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the full burden. It fully compensates by explaining that origins and destinations are lists of LocationRefs with three acceptable forms (lat/lon dict, GERS id, free-text name), that they can be mixed freely, that each is capped at 10, and how unresolved strings are reported. This goes far beyond the plain array/string schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource statement: 'Straight-line (great-circle) distance in meters between every origin and destination.' It immediately distinguishes itself from routed-distance or travel-time tools by calling the calculation a plain haversine and explicitly saying what it is NOT, which differentiates it from travel_time_matrix and Google/Mapbox APIs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use and when-not-to-use guidance, naming alternatives: use isochrone() for 'how far can I get in N minutes' and travel_time_matrix() for routed times/distances. It also characterizes the tradeoff (cheap but not routed), making the selection rationale clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
elevation_atElevation at a pointARead-onlyIdempotent
Ground elevation in meters at a point, from Copernicus GLO-30 (~30 m resolution).
Reads the Copernicus DEM directly from AWS Open Data (no API key, no
third-party elevation service) β the same open-data pattern every other
tool here uses, just a different bucket than Overture's. Nearest-cell
sampling, not interpolated: at ~30 m ground resolution the answer is
"the elevation of the DEM cell containing this point", which can be off
by a few meters from the exact spot on a steep slope.
Returns {"elevation_m": <float>}. No coverage at this point β open
ocean, or a tile the Copernicus release excludes from public
distribution β is a real, non-error answer: {"elevation_m": null,
"note": "..."} explaining why. Returns a structured {"error": ...} for
an out-of-range coordinate, or if the DEM tile can't be fetched
(network/upstream failure).
Attribution: Copernicus DEM Β© DLR/ESA, accessed via AWS Open Data.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description goes well beyond this: it discloses nearest-cell (non-interpolated) sampling and the accuracy caveat on steep slopes, the exact success return shape, the non-error null+note behavior for no coverage, and the structured error case for out-of-range coordinates or fetch failures. This fully specifies the behavioral contract.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then builds out the data source, sampling semantics, return contract, error contract, and attribution in clearly separated paragraphs. Every paragraph earns its place; the middle sentence about "the same open-data pattern every other tool here uses" is mildly redundant context and could be trimmed, but the overall structure is efficient for the amount of behavioral detail conveyed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool, the description is complete: purpose, data provenance, resolution, accuracy caveats, success return shape, the non-error null path, the error path, and attribution are all covered. The output schema's existence plus the explicit return-shape documentation means an agent knows exactly what to expect before and after invoking the tool. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does partially: "at a point" maps the two required numeric params to a coordinate pair, and "out-of-range coordinate" signals that lat/lon have validity bounds. However, it never states the coordinate format or the actual valid ranges (lat -90..90, lon -180..180), leaving the agent to rely on geographic convention.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: "Ground elevation in meters at a point, from Copernicus GLO-30 (~30 m resolution)." It names the exact data source and measurement, making it easy to distinguish from sibling point-lookup tools like buildings_at, land_use_at, and address_at. The purpose is unambiguous and non-tautological.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The tool's purpose is specific enough that an agent can infer when to use it (any time elevation at a coordinate is needed), and the coverage/error notes clarify when results will be null or failed. However, it never explicitly names an alternative or states when not to use this tool versus a sibling. The open-data pattern remark references other tools generally but provides no routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_nearFind places near a nameARead-onlyIdempotent
Places of a category near a named place or city.
Prefer find_places(where=..., category=...): it is the canonical form of
this search β the same one hop, plus every find_places filter, detail
tier, and mode. find_near stays as a thin alias.
Pass the user's place name as near. Do not call geocode(),
resolve_place(), or geocode_batch() first. One hop for a category
near a named landmark. Resolves near, then searches like a point
find. Returns compact rows (name, category, distance, trust_note)
plus the resolved near (name and coordinates).
A comma qualifies: "Le Marais, Paris" searches inside Paris only.
If near matches several equally-ranked places, returns
{"error": "ambiguous_place", "candidates": [...]} instead of picking
a city. An unresolvable name returns {"error": "not_found"}; empty
category or near returns {"error": "bad_request"}. radius_m and
limit follow the same clamps as a point search.
A truncated answer carries "cursor" (delegated straight through from
find_places); pass it back with the same category/near/radius_m/limit
to continue. See find_places' docstring for the bad_cursor/release-
mismatch details β they apply here unchanged.
| Name | Required | Description | Default |
|---|---|---|---|
| near | Yes | ||
| limit | No | ||
| cursor | No | Continuation cursor from a previous truncated answer; valid for the same query on the same data release. | |
| category | Yes | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the bar is lower, but the description adds substantial behavioral context. It documents error responses for ambiguous, unresolved, and bad input, the compact row shape, comma-qualified place scoping, and cursor delegation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and every sentence contributes useful information about behavior, errors, or alternatives. It is fairly long and repeats the 'one hop' idea, but the density is justified by the tool's error-handling and pagination complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's 5 parameters, sibling-alias relationship, and cursor behavior, the description is complete: it covers invocation, result shape, error responses, pagination continuation, and the relationship to find_places. The output schema and the referenced find_places docstring cover the remaining details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, so the description must compensate, and it does: near is explained as a user-supplied place name with comma-scoping behavior, and radius_m/limit clamping plus cursor continuation are defined. It does not enumerate valid category values, but enough is provided for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action and resource: finding places of a category near a named place or city. It also distinguishes itself from the canonical sibling find_places by explicitly calling itself a thin alias with one-hop behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly directs agents to prefer find_places(where=..., category=...) and explains that find_near is only a thin alias. It also instructs the agent to pass the user's place name as near and not to call geocode(), resolve_place(), or geocode_batch() first, giving concrete when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_placesFind placesARead-onlyIdempotent
Find named places, either near a point or inside an area's boundary.
Three mutually exclusive modes:
- Point + radius: pass lat and lon (radius_m defaults to 1000m), or the
same center as `where` β a {"lat", "lon"} dict, a GERS id, or a
free-text place name ("Alamo Square, SF"), resolved here, so a named
search is one hop: no geocode()/resolve_place() call first. lat/lon
or where, not both, and neither with division_id/area. An id/name
`where` adds a compact "resolved": {"name", "id", "lat", "lon",
"matched_by"} (absent for lat/lon or a {lat,lon} where); an ambiguous
name returns {"error": "ambiguous_place", "candidates": [...]} rather
than picking one. Results are nearest-first around that center.
- Division polygon: pass division_id (a GERS division id, e.g. one from
an admin-hierarchy chain) instead of lat/lon. Results are every matching place whose
point falls inside that division's true boundary polygon β no radius
to guess, and no circle clipping a coastline or straddling a border.
Results are ordered by name (there's no reference point to rank
distance from).
- Area by name: pass area ("Palo Alto") to get the division-polygon mode
without first resolving the id yourself. The name is resolved with the
same ranking geocode/resolve_place use; the resolved division is
echoed back as "area" on the response so it's clear which one was
searched. A name matching several equally-ranked divisions returns
{"error": "ambiguous_area", "candidates": [...]} listing their
division_ids rather than silently picking one, and an unresolvable
name returns {"error": "not_found"} rather than an empty result that
would read as "this place has no coffee shops".
category matches Overture's taxonomy (e.g. 'coffee_shop', 'restaurant',
'grocery'); name is a substring match on the place name β both compose
with either mode. Results include operating_status ("in business" /
"permanently closed" / null when unknown) β a business-lifecycle
signal, NOT opening hours; this data has no open-now information β
and a compact trust_note calibrated from confidence and that status.
min_confidence (0.0-1.0) keeps only rows whose confidence score is at
least that value; out-of-range values return a bad_request error.
operating_status filters to a single status (see the schema's enum for
accepted relabeled/raw values); "permanently closed"/"closed" also
match Overture's separate "closed_permanently" raw value, since both
relabel the same way. Unrecognized values return a bad_request error.
brand is a substring match on the place's brand name (e.g. 'Starbucks').
Brand data is sparse β most independent businesses have no brand at all,
so brand=X narrows results down to that chain only; the absence of a
result does NOT mean "not a Starbucks", it may just mean brand isn't
populated for that place. has_website/has_phone filter on whether a
place has any website/phone entries at all (presence, not content) β
each result row carries brand (string or null) and has_website/has_phone
(booleans) so an agent can see why a place matched, but the full
websites/phones arrays are only returned by place_details.
Every filter above composes with either mode, and each is a silent
no-op (not an error) if the column it needs (confidence /
operating_status / brand / websites / phones) is absent from the active
dataset β see degraded_fields() on the response.
name has two fallback tiers (point + radius mode only, #373) for when
the literal substring search finds nothing: an alternate-spelling match
("Munich" -> a place named "MΓΌnchen") then a typo-tolerant fuzzy match
("Startbucks" -> "Starbucks"). A row found either way carries
"matched_by": "alt_name" | "fuzzy" (absent on an ordinary match), and a
top-level "note" names the spelling actually matched.
Returns {"results": [...]}, plus truncated/omitted_count if the answer
didn't fit the token budget. Returns a structured {"error": "bad_request",
...} if no mode's inputs are given (or more than one is), {"error":
"not_found", ...} if division_id/area doesn't match any known division, or
a structured {"error": ...} if the upstream dataset is unavailable or
missing columns this tool depends on. If a category filter was given and
it matched nothing (in either mode), a non-fatal "note" field hints that
the category slug may be wrong and points at search_categories.
A truncated answer β either token-budget-trimmed or because more
matching rows exist beyond limit β also carries "cursor"; pass it back
unchanged, with every other argument identical, to fetch the next page.
cursor is only ever issued for a literal or ambiguity-free match: an
answer built from #373's alt-name/fuzzy name fallback never carries one
(those pools are small; ROADMAP Β§4.4). A cursor for a different query,
or one that's malformed, returns {"error": "bad_cursor", ...} naming
the mismatch; a cursor issued against an older Overture release is
honored anyway, against the current release, with a one-line "note"
that rows may have shifted.
detail picks how much of each row comes back (ROADMAP Β§4.5, roadmap
feature 5): "compact" (the DEFAULT) is {id, name, category, lat, lon,
distance_m, trust} β trust is a tier string ("strong"/"ok"/"weak"/
"unknown") derived from the same confidence/operating-status signals
as "full"'s trust_note, so the two can never disagree; the payload
also carries one "trust_legend" line explaining the tiers. compact
keeps lat/lon (unlike "ids") so a composed call feeding these rows
into a map-rendering tool still has coordinates under the default
tier. "ids" is just {id,
distance_m} β deliberately coordinate-free, the cheapest shape, for
chaining straight into a batch id lookup or place_details. "full" is
every field, unchanged from before this param existed, including
trust_note's prose. division-polygon rows have no distance_m at any
tier (no reference point to measure from) β the key is omitted, never
null; they still carry lat/lon at every tier but "ids". detail is
presentation only: it does not affect which rows match or their
order, is NOT part of a cursor's query identity, and a cursor issued
under one detail continues correctly under a different one.
Projection happens before the token budget is applied, so a smaller
detail tier fits more rows per answer β that's the point of a tier
smaller than "full". Unrecognized values return a bad_request error
naming the accepted ones.
categories (mutually exclusive with category β passing both is a
bad_request) runs a checklist of up to 5 slugs in ONE scan instead of
category's one slug, each matched with identical substring/prefix
semantics. group_by_category=False (the default) merges every
category's matches into one nearest-first list, same shape and cursor
pagination as a single category (categories, sorted, is part of the
cursor's query identity). group_by_category=True instead buckets the
answer as {"results": {category: [rows...]}}, up to `limit` rows PER
category β a category with zero matches is simply absent from the
dict. Grouped answers carry no cursor at all (each category is already
limit-bounded from a single scan; page a specific one further by
re-running with category=<that slug> instead). More than 5 slugs, or
categories together with category, both return a bad_request error;
group_by_category=True together with a non-null cursor is also a
bad_request (there is nothing to continue). The category-miss "note"
(see above) also covers categories: it fires when the scan matched
none of the requested slugs at all.
within = {"minutes", "mode"?, "of"?} (roadmap Β§4.2) keeps only results
truly reachable from `of` within `minutes` by street-graph `mode` β
the real graph, not a radius guess; radius_m is ignored when set. `of`
(a LocationRef) defaults to the search center β lat/lon or whatever
`where` resolved to; required in division_id/area mode. An id/name `of`
adds a "resolved" echo, unless `where` already claimed that key, in
which case `of`'s match is named in the note. The answer gets a short
reachability note. A cold graph returns
{"error": "needs_confirm", ...} β retry with confirm=true once the
user agrees to wait (5-25s).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| area | No | ||
| name | No | ||
| brand | No | ||
| limit | No | ||
| where | No | ||
| cursor | No | Continuation cursor from a previous truncated answer; valid for the same query on the same data release. | |
| detail | No | Row detail tier for find_places rows: 'ids' (id + distance_m only), 'compact' (id/name/category/lat/lon/distance_m/trust), or 'full' (every field, incl. trust_note prose). Default: compact. | |
| within | No | ||
| confirm | No | ||
| category | No | ||
| radius_m | No | ||
| has_phone | No | ||
| categories | No | ||
| division_id | No | ||
| has_website | No | ||
| min_confidence | No | ||
| operating_status | No | Business-lifecycle status filter (relabeled or raw Overture value, case-insensitive). Default: no filter. | |
| group_by_category | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark the tool read-only and idempotent, the description adds substantial behavior: ambiguity errors instead of silent selection, name-fallback tiers with matched_by, cursor identity rules, detail being presentation-only, brand sparsity caveats, and the needs_confirm cold-graph flow. Nothing contradicts the readOnlyHint, idempotentHint, or destructiveHint annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but justified by 20 parameters and three modes, and its labeled mode/filter/pagination/detail structure makes it navigable. It is not perfectly conciseβroadmap references such as '#373', 'ROADMAP Β§4.4', and 'roadmap feature 5' are incidental noise for an agentβso it falls just short of a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool this complex, the description covers input modes, output shapes, error contracts, per-mode ordering, pagination, projection tiers, degraded columns, and data-caveat behavior. The output schema exists, but the description adds the error responses, cursor semantics, and per-mode behavioral rules an agent needs to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 15%, and the description compensates thoroughly. It explains defaults like radius_m=1000, the where forms (lat/lon dict, GERS id, free text), operating_status relabeling, categories/group_by_category semantics, within/confirm, cursor, and detail tiers. Even limit receives indirect explanation through pagination and grouped-row behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence identifies a specific operationβfinding named placesβand the two spatial contexts (near a point or inside an area boundary). It also distinguishes itself from siblings by noting that named search is one hop and needs no prior geocode()/resolve_place() call, and later points to search_categories and place_details where relevant.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The three mutually exclusive modes are clearly specified with their exact parameter combinations and the errors for mixing them. It gives routing guidance: skip geocode/resolve_place for named searches, use search_categories when a category slug matches nothing, and use place_details when full website/phone arrays are needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
from_toNamed-place routeARead-onlyIdempotent
Shortest-path walk, cycle, or drive between two places.
from_to is route() with LocationRef ends and a walk default; route is
the canonical routing tool and is growing the same from/to ends, so
prefer route(from=..., to=...) once it takes them.
Pass each of from/to as a free-text place name, a {"lat", "lon"} dict,
or a GERS id β mixed freely. Do not call geocode(), resolve_place(), or
geocode_batch() first. Plain names resolve in parallel exactly as
before; coordinates pass through untouched. Builds one street graph and
returns distance, duration, export maps/gpx/text, and a "from"/"to"
block carrying whatever the input resolved to (name/id when it was a
name or GERS id, lat/lon always).
A comma qualifies: "Alamo Square, SF" searches inside SF only.
If a name matches several equally-ranked places, returns
{"error": "ambiguous_place", "candidates": [...]} instead of picking
a city. If the two ends resolve a city apart, returns
{"error": "too_far"} with the resolved ends and the mode cap rather
than extracting a continent graph. Same per-mode straight-line caps
as a coordinate route (walk ~7.5 km, cycle ~23.5 km, drive ~95.5 km).
An unresolvable name or GERS id returns {"error": "not_found"}; a
malformed from/to (empty string, dict missing lat/lon, wrong type)
returns {"error": "bad_request"} β either way the offending side is
named in "field": "from" | "to". Omit mode to use the stored
preferences mode, else walk.
include_path, include_elevation, prefer, and avoid pass straight through
to route() β see that tool's docstring for what each returns/means
("elevation" climb profile, prefer="flat" grade-avoiding preference and
its honest step-free/accessibility caveats, avoid=["motorway"|"trunk"]
class avoidance and why no toll or ferry option exists). avoid needs
mode="drive": the walk default already excludes those classes.
confirm=true after the user agreed to wait for a first-time street-graph
build (about 5β25 seconds). Pass it only after a needs_confirm reply
and they said yes. A warm or cached graph never needs it.
Omit confirm unless you just asked and they said yes.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| from | Yes | ||
| mode | No | Travel mode. Default: stored preference, else walk. | |
| avoid | No | Road classes to keep the route off. No toll or ferry option exists: Overture carries no toll attribute, and the graph is road-only. Default: none (no class avoided). | |
| prefer | No | Grade preference. Default: none (plain-distance routing). | |
| confirm | No | ||
| include_path | No | ||
| include_elevation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark this read-only and idempotent, and the description agrees without contradicting them. It goes far beyond annotations by detailing exact error shapes ('ambiguous_place', 'too_far', 'not_found', 'bad_request'), per-mode distance caps (7.5/23.5/95.5 km), the maybe-needed 'confirm' delay for first-time graph builds, and pass-through parameter behavior with caveats like 'avoid needs mode="drive"'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every paragraph earns its place: input format, error handling, caps, pass-through params, and confirm behavior are each given a compact block. It is front-loaded with the one-sentence summary, and the alternative tool is identified in the second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a routing tool with 8 parameters and 38% schema coverage, the description covers all invocation-critical details: input resolution, errors, mode defaults, graph-build confirmation, and what outputs are returned. The existing output schema and read-only/idempotent annotations cover the remaining structural expectations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 38%, yet the description thoroughly compensates. It defines the accepted 'from/to' forms (free-text name, {"lat", "lon"} dict, GERS id, mixed), clarifies the default mode ('stored preferences mode, else walk'), and details 'confirm' semantics ('warm or cached graph never needs it'). It even explains the meaning of 'prefer' and 'avoid' via route() semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Shortest-path walk, cycle, or drive between two places,' a specific verb/resource combination that exactly matches the tool name and title. It then explicitly contrasts itself with the sibling 'route' tool: 'from_to is route() with LocationRef ends and a walk default; route is the canonical routing tool.' This makes the tool's unique role unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives direct routing guidance: 'prefer route(from=..., to=...) once it takes them,' telling the agent when to use the sibling instead. It also forbids unnecessary upstream calls ('Do not call geocode(), resolve_place(), or geocode_batch() first') and precisely conditions the confirm flag on user consent ('Pass it only after a needs_confirm reply and they said yes').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocodeGeocode a place nameARead-onlyIdempotent
Free-text place name -> ranked candidate locations, from Overture divisions and places.
No Nominatim, no third-party geocoding API. Matches localities,
neighborhoods, regions, and countries by name (exact > prefix >
substring), falling back to named places if that doesn't fill `limit`.
Returns {"results": [{name, type, lat, lon, id (GERS), admin_context,
rank_score}, ...]}, budgeted like every other tool. Returns a structured
{"error": ...} instead of raising if the remote scan fails.
A query with no location context in it at all (a bare place name that
matches no division, e.g. "Blue Bottle Roastery") can't be bounded to a
region, so the places half of the search is skipped rather than
scanning the global places dataset β minutes, not seconds (#105). That
case comes back empty with a "note" saying so and what to do instead.
A misspelled name that matches no division literally ("Berekley", or
"Berekley, CA" β the region suffix is set aside first) gets one
close-spelling retry over the local divisions table (#215); those
results rank below any literal match, carry "matched_by": "fuzzy", and
come with a "note" naming the spelling they were corrected to.
A query that is entirely a postcode ("94110", "1011AB") is answered as
one (#223): one result per country whose address points carry that code,
with "type": "postcode", "country", "address_count" and a null "id" (a
postcode is not a GERS entity). Codes are shared across countries far
more often than not, so the alternates below the top row are real
ambiguity. The accompanying "note" carries the granularity caveat (a
Dutch code is a street block, a US ZIP a district) and the coverage
limits -- including the countries the addresses theme covers but that
carry no postcode values at all, which is why a valid postcode can still
come back empty.
Exonyms work too (#214): names are matched against Overture's ~100
localized alternates as well as its canonical one, so "Munich" answers
MΓΌnchen and "Tokyo" answers ζ±δΊ¬ι½. `name` is always the canonical
spelling; such rows carry an extra "matched_name" naming the alternate
that matched.
lang (#410) requests Overture's language-tagged name variant instead
of a division row's primary name, when the data has one for that row
and language: `name` becomes the variant and `name_primary` is added
only when it differs. Default: the stored `preferences()` lang, else
the primary name unchanged. Never invented or transliterated β only a
variant actually present in Overture's data is ever returned.
`PLACEROOT_HOME=<city/area>` (#406) sets a home region once at startup;
a bounded score bonus then nudges same-tier ambiguous namesakes (the
"which Springfield" case) toward it β a bias, never a filter, so a
distant result stays in the answer, just not first. Only when the bias
actually changed the top result does a "note" say so, e.g. "ranked
toward your configured home region (Seattle); pass a city/near hint to
override". No home configured -> no bias, no note, behavior unchanged.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Result-language code (2-3 lowercase letters, e.g. "de"). Overture-tagged name variants only β never transliterated or invented. Default: stored preference, else the primary name. | |
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only, idempotent, and non-destructive, and the description goes far beyond them. It discloses ranking order (exact > prefix > substring), fallback to places, budgeted execution, structured error return instead of raising, empty-result notes, fuzzy retry, postcode handling, exonym matching, lang variants, and home-region bias. This is a thorough disclosure of the tool's hidden behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded in one clear sentence, and the subsequent paragraphs are organized by scenario. However, the description is very long, with embedded issue numbers (#105, #215, #223, #214, #410, #406) and repeated caveats that add clutter. It is structured and relevant, but not concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the return schema, error behavior, empty-result notes, fuzzy matching, postcode edge cases, exonym behavior, language preferences, and home-region bias. It tells the agent exactly what to expect in every described scenario and when a 'note' will appear. No critical usage aspect is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only describes 'lang'; 'query' and 'limit' are bare. The description compensates by explaining 'lang' in detail (language-tagged variants, never transliterated) and characterizing 'query' as a free-text place name. It provides minimal direct explanation of 'limit' beyond the budgeted context, but the intended meaning is still inferable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line 'Free-text place name -> ranked candidate locations, from Overture divisions and places' states a clear verb, resource, and input scope. It also explicitly disclaims Nominatim and third-party APIs, distinguishing the tool from external geocoders. The description's scope clearly separates it from siblings like reverse_geocode (coordinatesβplace) and geocode_address (structured addresses).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description defines what kind of input qualifies ('free-text place name') and what entity types it covers (localities, neighborhoods, regions, countries). It does not explicitly name sibling alternatives or state when to avoid this tool, such as using geocode_address for structured addresses. The usage context is clear, but explicit exclusions are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocode_addressFind a street addressARead-onlyIdempotent
Street address -> coordinates: "1600 Amphitheatre Parkway, Mountain View".
The forward counterpart to address_at, and finer than geocode, which
answers at city/neighborhood granularity and never at a doorway. The
first comma splits the street from the city; a bare integer at either end
of the street part is the house number ("1600 Amphitheatre Parkway",
"HauptstraΓe 5"). Pass `number`/`street`/`city` instead if you already
have the parts. Unit/apartment numbers are not parsed.
The city is resolved first and its boundary bounds the search, so a city
that resolves to no boundary β or to something far larger than a city,
like a state β returns an empty list plus a note rather than a scan. If a
same-named runner-up in the same country supplies the boundary instead,
the note names it β the answer is never silently about a different city,
and never about one in another country. Check `anchor` (name, country,
admin_context) to see which one it was. Street names match in either
spelling (Parkway/Pkwy, West/W, NW/Northwest).
Returns {"results": [{number, street, unit, postcode, country,
distance_m, lat, lon}, ...], "anchor": {name, id, country,
admin_context}, "match": "exact"|"nearest_number"|"street"},
deduplicated to distinct number+street+postcode and nearest the city's
own point first. More matches than `limit` adds "truncated",
"distinct_in_range" and a note. `match` is absent only when no street
was scanned at all (no street name, no city, or an unresolved anchor).
A requested number with no address point is never interpolated: when the
street has other numbered points, `results` holds the real nearest known
numbers bracketing the miss instead (`match: "nearest_number"`, each row
its own genuine coordinates, plus a note naming the miss and neighbors)
β never a synthesized coordinate for the missing number. No usable
numbers on the street falls to `match: "street"`, today's empty-plus-note.
Coverage is alpha: 39 countries, no UK, Ireland, India or China. An empty
list is a valid answer and always carries a note saying whether the
country is uncovered or the street simply wasn't found.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | ||
| limit | No | ||
| query | No | ||
| number | No | ||
| street | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already declare readOnly, idempotent, and non-destructive behavior, the description adds substantial operation traits: city-first resolution, boundary bounding, empty-plus-note semantics, no interpolation of missing numbers, country-boundary safeguards, and alpha coverage limits. It also discloses exact match-mode behavior, which is valuable beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense and well-structured, with the core transformation front-loaded at the top. Each paragraph adds a distinct behavior β parsing, resolution, matching, edge cases, coverage β so every sentence earns its place; no repetitions or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with optional parameters, multiple input modes, subtle matching semantics, and edge cases, the description is exceptionally complete. It covers query grammar, structured input, city-boundary behavior, empty results, truncation, deduplication, matching fallbacks, and geographic coverage, leaving virtually no ambiguity about invocation or expected behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it delivers. It explains how to format the query string, including comma separation and house-number placement, and describes when to use the structured number/street/city alternatives. It also clarifies limit behavior through truncation semantics, making the parameters meaningful beyond their names and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a crisp transformation statement β "Street address -> coordinates" β and immediately gives a concrete example. It distinguishes itself from address_at and geocode by naming them and specifying the granularity difference, so an agent can tell exactly what this tool resolves and at what precision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly positions this as the forward counterpart to address_at and finer than geocode, telling the agent when geocode would be the wrong choice. It also gives a clear alternative invocation β "Pass number/street/city instead if you already have the parts" β so the agent knows when to use the structured parameters rather than the single query string.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocode_batchGeocode names in batchARead-onlyIdempotent
Geocode up to 20 free-text queries in one call, one best match each.
Cuts N round-trips of geocode() into one and, more importantly,
shares ONE local divisions name table across the batch (#329) so a
two-name walk is not N cold S3 scans. For each query, keeps only
the top candidate.
Returns {"results": [{"query", "name", "type", "lat", "lon", "id"
(GERS), "rank_score"}, ...]}, one row per query, in input order β a
query with no match gets the standard error envelope {"query",
"error": "not_found", "detail"} instead, and does not fail the rest of
the batch. queries is capped at 20; a longer list returns a structured
{"error": ...} rather than truncating silently. Budgeted like every
other tool. Returns a structured {"error": ...} instead of raising if
the remote scan itself fails.
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | ||
| limit_per_query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond the readOnly/idempotent annotations: per-query error envelopes, batch cap at 20, structured errors instead of raising, and non-failing of the rest of the batch. However, it states 'keeps only the top candidate' while the input schema includes limit_per_query with a default of 3, and that parameter's behavior is never explained, creating an incomplete and potentially misleading behavioral model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but organized and mostly information-dense: purpose, motivation, output format, then failure behavior. The implementation-specific notes like '#329' and 'cold S3 scans' add useful rationale, though 'Budgeted like every other tool' is vague and earns little weight. Overall it stays front-loaded and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is quite complete for a read-only batch operation: it covers input cap, output shape, per-query error isolation, and remote failure behavior. The major gap is the undocumented limit_per_query parameter, which affects actual behavior and is central to calling the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the full semantic burden for parameters. It does explain that queries are free-text and capped at 20, but it never mentions limit_per_query, its default, or the effect it has on the returned candidates. With a parameter silently left unexplained, agents cannot correctly tune or even predict the tool's output.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Geocode up to 20 free-text queries in one call, one best match each.' It explicitly contrasts with geocode() by framing itself as the batched replacement, so an agent can tell it apart from both geocode and the other sibling tools without inspecting the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly motivates when to use this tool: when you have N free-text names to geocode, it cuts N round-trips to one and avoids repeated cold S3 scans. It does not explicitly say 'use geocode for a single query' or list exclusion cases, but the batching rationale makes the intended usage clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geometry_opGeometry operationsARead-onlyIdempotent
Geometry math and predicates β one tool, many ops, no Overture scan.
`op` selects the operation; pass only the params it needs (points are
`{"lat": ..., "lon": ...}`; `geometry` is a GeoJSON object):
- `distance(point, point2)` -> `{"distance_m"}` (great-circle haversine distance)
- `bearing(point, point2)` -> `{"bearing_deg"}` (initial compass bearing)
- `destination(point, bearing_deg, distance_m)` -> `{"point"}`
- `midpoint(point, point2)` -> `{"point"}` (great-circle midpoint)
- `area(geometry)` -> `{"area_m2", "area_km2"}` (Polygon/MultiPolygon)
- `length(geometry)` -> `{"length_m"}` (LineString/MultiLineString)
- `bbox(geometry)` -> `{"bbox": [xmin, ymin, xmax, ymax]}` (any geometry)
- `centroid(geometry)` -> `{"point"}` (any geometry)
- `buffer(point, radius_m)` -> `{"geometry"}` (Polygon, ~32-vertex circle approximation)
- `convex_hull(points)` -> `{"geometry"}` (Polygon; points capped at 100)
- `point_in_polygon(points, geometry)` -> `{"results": [bool, ...]}` (Polygon/MultiPolygon,
holes honored; points capped at 100)
- `nearest_point(point, points)` -> `{"index", "distance_m"}` (points capped at 100)
- `nearest_point_on_line(point, geometry)` -> `{"point", "distance_m", "fraction"}` (LineString)
- `union(geometry, geometry2)` -> `{"geometry", "area_km2"}` (Polygon/MultiPolygon, either slot)
- `intersect(geometry, geometry2)` -> `{"geometry", "area_km2"}`, or `{"empty": true, "note"}`
when the two inputs don't overlap
- `difference(geometry, geometry2)` -> `{"geometry", "area_km2"}` (geometry minus geometry2),
or `{"empty": true, "note"}` when geometry2 fully covers geometry
`buffer`, `convex_hull`, and `union`/`intersect`/`difference` are the
ops that return geometry; that output is simplified to fit the same
token budget `simplify_geometry`'s own default targets, so there's no
need to chain a second call. `union`/`intersect`/`difference` run via
the DuckDB spatial extension already loaded for other tools (see
geometry_setops.py) rather than geometry_ops.py's pure-Python math.
An unknown op returns `{"error": "bad_request", ...}` listing valid ops.
Missing/wrong-shaped params for the given op return `{"error":
"bad_request", ...}` naming exactly what that op needs, e.g. "op=buffer
needs point and radius_m". Point-like inputs are range-checked (lat in
[-90, 90], lon in [-180, 180]); `geometry`/`geometry2` get structural
validation only (right type, non-empty numeric coordinates) β see
geometry_ops.py's module docstring for the accuracy notes behind
area/centroid (a local meters projection, not a geodesic computation)
and buffer/convex_hull (planar approximations, fine at city/regional
scale).
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | Geometry operation; each takes a different subset of the other arguments β see below. | |
| point | No | ||
| point2 | No | ||
| points | No | ||
| geometry | No | ||
| radius_m | No | ||
| geometry2 | No | ||
| distance_m | No | ||
| bearing_deg | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark read-only/idempotent/non-destructive, and the description builds on this with concrete error responses, coordinate range checks, structural-only validation of geometries, accuracy caveats, and the DuckDB execution note. This is more behavioral detail than most tool descriptions provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but tightly organized: one-line op signatures with outputs, grouped notes for shared behavior, and a final validation/accuracy section. Every sentence supplies operational information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter dispatcher with 16 operations, the description covers selection, input shaping, output shapes, error behavior, caps, and precision caveats. Nothing needed to call it correctly is missing, even without opening the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 11% and the geometric params are untyped anyOf blocks, so the description carries the full burden. It defines point shape, GeoJSON geometry, per-op signatures, caps (100 points), and edge-case empty results, fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with 'Geometry math and predicates β one tool, many ops,' immediately stating the verb, domain, and dispatch nature. The full enumerated operation list makes it impossible to mistake for any sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The op list plus 'pass only the params it needs' gives clear selection guidance for choosing an operation. It also says geometry outputs are already simplified to simplify_geometry's token targets, so no chained simplification call is needed. It does not explicitly contrast with distance-matrix or routing siblings, but the scope is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gers_lookupLook up a GERS idARead-onlyIdempotent
Any GERS id -> what it is, across themes, plus its cheap cross-theme joins.
The reverse of every other tool: hand back an id one of them returned
(a place, a division, or a building) and get the entity it names β
{"id", "theme", "type", "name", "lat", "lon", "summary", "related"} β
without needing to know which theme it came from. summary carries a few
theme-specific fields (place: category, confidence, brand; division:
subtype, country, region; building: class, height, floors); related
carries the containing division, plus the building at the point when
the id is a place. Never geometry.
Also pass near_lat/near_lon β the lat/lon of the row the id came from β
whenever you have them: the lookup is an id scan across up to three
themes, and the hint narrows each one to a ~50km box instead of a
full-theme scan. Omitting it still works, just much slower on a cold id.
The hint *bounds* the search rather than merely ordering it: an id
outside the box comes back not_found with a note saying so, and the
exhaustive lookup is the same call without near_lat/near_lon. Pass a
hint you are sure of, or none at all.
Transportation segment/connector ids are not resolvable yet and come
back as not_found. Returns {"error": "not_found"} if no theme claims
the id, {"error": "bad_request"} for a malformed id (a GERS id is an
opaque token β 32 lowercase hex characters) or an out-of-range hint,
or a structured {"error": ...} if upstream is unavailable.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| near_lat | No | ||
| near_lon | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation safe and idempotent, and the description adds substantial behavioral detail beyond that: the hint bounds the search rather than ordering it, out-of-box ids return not_found, transportation ids are not resolvable yet, and the exact error shapes for malformed ids and upstream failures. It also states 'never geometry', clarifying a common expectation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: core purpose first, then hint semantics, then error behavior. The structure is logical and front-loaded, with no filler or repetition of annotation metadata.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the description still enumerates the returned entity fields, the theme-specific summary fields, and the related object. It also covers the non-trivial edge cases of unresolvable ids, malformed ids, out-of-range hints, and upstream failures. An agent has everything needed to call this tool correctly and interpret its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it succeeds. It explains that id is an opaque 32-character lowercase hex token, defines near_lat/near_lon as optional hints derived from the source row, and describes the consequences of including or omitting them. This goes far beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states exactly what the tool does: given any GERS id, return the entity it names across themes. It explicitly positions itself as 'the reverse of every other tool' and names the entity fields, making it easy to distinguish from sibling lookups and search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains when to use this tool: whenever another tool returns a GERS id and you need the underlying entity. It also gives explicit guidance on the near_lat/near_lon hint, including when to pass it, when not to, and its effect on performance and results.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ground_locationGround a locationARead-onlyIdempotent
One-hop location grounding: where, surroundings, reach, notable.
Answers "orient me at this point" in a single call instead of chaining
a reverse lookup, an area summary, a reachable-area scan, and a
nearby-places search. Give the point as lat/lon, or as `where` β a
{"lat", "lon"} dict, a GERS id, or a free-text place name β but not
both (and not neither); either way returns {"error": "bad_request"}
naming the choice. A `where` given as an id/name adds a compact
"resolved": {"name", "id", "lat", "lon", "matched_by"} to the answer
(a separate key from the answer's own "where" section below); absent
for lat/lon or a {lat,lon} where. Returns:
- where: reverse_geocode's answer for the point (address/divisions
chain, or a "divisions_only" degrade).
- surroundings: total places and the top few categories within a fixed
500m radius, plus density_per_km2.
- reach: reachable-area stats only for (minutes, mode) β
{reachable_nodes, max_radius_m, area_km2}. Never includes the
reachable-area polygon; this tool returns no geometry, ever.
- notable: the nearest 2-3 named places, no category filter.
Each section is independent: if its underlying call fails or comes
back empty, that section is dropped and a short line explaining why is
added to "notes" instead β the call only fails outright if every
section failed, returning a structured {"error":
"upstream_unavailable", ...}.
minutes must be > 0 and <= 60; omit mode to use the stored
preferences mode, else walk.
Both, plus out-of-range coordinates, return {"error": "bad_request"}.
No confirm gate: the reach scan runs with the requested minutes/mode
as-is (it self-caps its graph extraction radius; no nearby street
graph just degrades the reach section to a note).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| mode | No | Travel mode. Default: stored preference, else walk. | |
| where | No | ||
| minutes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as readOnly/idempotent/non-destructive, and the description adds substantial behavior beyond that: per-section independent failure with notes, structured bad_request vs upstream_unavailable errors, no geometry ever returned, no confirm gate, self-capping of the graph extraction radius, and degradation of the reach section to a note. This far exceeds the baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with a one-line summary, clear return-section bullets, and a short list of edge cases. It front-loads the core purpose and keeps related facts grouped. It loses one point because a few details are slightly redundant, such as repeating the mode default that already appears in the schema and restating bad_request behavior in two places.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description is remarkably complete: it covers input cardinality, accepted formats, bounds, error modes, per-section degradation, and even the deliberate absence of geometry. An agent has everything needed to invoke this tool correctly and to interpret unexpected per-section outcomes, especially with an output schema also present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, but the description compensates thoroughly. It explains the mutually exclusive lat/lon vs where inputs and the bad_request result when both or neither are supplied, enumerates valid where forms (dict, GERS id, free-text name), explains the resolved key, constrains minutes to (0, 60], and clarifies mode default behavior. This is exactly the semantic guidance the sparse schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-plus-resource: 'Ground a location' with 'One-hop location grounding: where, surroundings, reach, notable.' It clearly distinguishes itself from sibling chainable tools by promising a single call that replaces a reverse lookup, area summary, reachable-area scan, and nearby-places search. The purpose is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly identifies when to use the tool: 'Answers "orient me at this point" in a single call instead of chaining' the four underlying operations. This gives an agent a concrete decision rule and names the alternatives it replaces, without requiring it to infer from sibling names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
infrastructure_atInfrastructure near a pointARead-onlyIdempotent
Infrastructure near a point, nearest first: bridges, towers, piers β and street furniture.
From Overture's base theme (issue #179), type=infrastructure β the
built things that are neither buildings nor POIs. Read the data
honestly before trusting an answer: this layer is dominated by street
furniture (street_lamp, bench, waste_basket, bollard, kerb, crossing),
which outnumbers landmark infrastructure roughly 50:1 in a city
centre. An unfiltered query in a dense area returns lamps and benches
and says nothing about whether a bridge is nearby. To ask about
landmarks, filter: subtype/infra_class match Overture's `subtype` and
`class` columns (case-insensitive substring; infra_class is `class`
under a non-reserved name) β e.g. subtype="bridge", subtype="tower",
subtype="power", infra_class="pier".
Returns {"center", "radius_m", "results": [{"id", "subtype", "class",
"name", "distance_m"}, ...]}, plus "truncated": true, "total_in_range"
and an explanatory "note" whenever more features matched than were
returned. id is the GERS id, usable with other GERS-keyed tools. No raw
geometry (design rule: answers, not data).
Radius search, not containment: most infrastructure is linear or a
bare point, so "what's within radius_m" is the answerable question.
distance_m is measured to the closest point on the feature, not its
centroid β a bridge you are standing on reads ~0 m, not "distance to
the middle of the bridge". radius_m echoes the effective radius, which
may be lower than requested (large values are clamped).
An empty results list is a valid answer, not an error: base-theme
coverage is OSM-derived and patchy, and "no infrastructure within
500 m" is a real finding. Returns a structured {"error": ...} if
upstream is unavailable or the dataset is missing geometry/bbox, and
{"error": "bad_request"} for a non-finite or out-of-range coordinate.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| limit | No | ||
| subtype | No | ||
| radius_m | No | ||
| infra_class | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the bar is about added context. The description adds substantial behavioral detail: radius clamping, distance measured to closest point rather than centroid, empty results as a valid answer, truncation/note behavior, GERS id semantics, no raw geometry, and structured error cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but organized into purposeful paragraphs: summary, data caveat, filtering guidance, output shape, radius behavior, and error handling. It is front-loaded with the primary purpose and uses examples compactly. Some phrasing could be trimmed, but nothing is merely filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a tool of this complexity: it explains what the tool returns, the truncated/total_in_range/note mechanics, how distance_m is computed, radius clamping, valid empty results, and error responses. The output schema and annotations cover the structured contract, while the description fills the practical gaps an agent would need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description carries the semantic burden. It thoroughly explains subtype and infra_class as case-insensitive substring matches against Overture columns, and meaningfully describes radius_m effective behavior. It does not explicitly explain lat/lon units or the limit parameter semantics beyond the default, though these are more self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific function: return infrastructure near a point, nearest first, with named categories (bridges, towers, piers, street furniture). It differentiates itself from siblings by specifying this is Overture type=infrastructure β built things that are neither buildings nor POIs, which separates it from tools like buildings_at.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong guidance on when to use it and how to frame queries, including the crucial warning that unfiltered results are dominated by street furniture and the recommendation to filter by subtype/infra_class for landmark questions. It does not explicitly name alternative tools for when this tool should not be used, so it stops short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
isochroneReachable area (isochrone)ARead-onlyIdempotent
Isochrone: the area reachable from a point within minutes, by mode.
Give the point as lat/lon, or as `where` β a {"lat", "lon"} dict, a
GERS id, or a free-text place name β but not both (and not neither);
either way returns {"error": "bad_request"} naming the choice. A
`where` given as an id/name adds a compact "resolved": {"name", "id",
"lat", "lon", "matched_by"} to the answer; absent for lat/lon or a
{lat,lon} where.
Builds a street graph from Overture's transportation theme and runs
Dijkstra out to the time budget. Each mode
excludes its own set of unusable road classes (e.g.
drive excludes footway/path/steps; cycle and drive exclude
motorway/trunk... drive itself allows motorways) and respects one-way
restrictions for cycle/drive (walk ignores them). speed_m_s overrides
the mode's default speed model (walk 1.4 m/s, cycle 4.2 m/s, drive
per-edge from Overture's speed_limits or a class-based default table)
with a single constant. Returns {"polygon": <GeoJSON Polygon>, "stats":
{reachable_nodes, max_radius_m, area_km2}, ...}. The polygon traces the
boundary of reached nodes' occupied grid cells (falling back to a
convex hull for very small reachable sets); reachable_nodes/
max_radius_m are always exact, only the drawn polygon shape
approximates, and is decimated/simplified to fit the token budget.
radius_m optionally overrides the auto-derived graph extraction radius
(capped per mode: 5km walk, 15km cycle, 60km drive); passing something
larger than the cap returns a structured error instead of silently
truncating. An unrecognized mode string returns a structured
{"error": "unsupported_mode"}. minutes must be > 0 and radius_m (if
given) must be >= 0, else returns {"error": "bad_request"}.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| mode | No | Travel mode. Default: stored preference, else walk. | |
| where | No | ||
| minutes | No | ||
| radius_m | No | ||
| speed_m_s | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the readOnly/idempotent annotations: discloses the Dijkstra-on-Overture graph algorithm, per-mode road-class exclusions, one-way handling, default speed models, the exact-stats vs approximate-polygon distinction with token-budget decimation, and radius caps that return errors instead of truncating. Error semantics for unsupported modes and bad requests are fully specified and consistent with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long (~400 words) but nearly every sentence carries functional content, and the flow from purpose to origin to algorithm to output to errors is logical. Minor bloat: the parenthetical road-class enumeration rambles somewhat and 'but not both (and not neither)' is a clunky double negative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers origin specification rules, all mode behaviors, the time budget, optional radius/speed overrides, cap violations, and every error path, while the existing output schema handles return-value details. An agent has everything needed to invoke the tool correctly in one place.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at only 14%, the description carries the full burden and succeeds: it explains the lat/lonβwhere mutual exclusion and 'resolved' side-effect, minutes > 0, per-mode radius_m caps (5/15/60 km) with structured errors, and speed_m_s overrides with mode defaults. Every one of the 7 parameters gains meaning that the schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise definition β 'the area reachable from a point within minutes, by mode' β and grounds it with a concrete return shape ('polygon' + 'stats'). Though no sibling is named, the area-reachability scope is unmistakable next to distance/matrix/route siblings like within_distance and travel_time_matrix.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The primary usage is implied by the definition ('reachable from a point within minutes') rather than stated as explicit when-to-use/when-not-to-use guidance, and no alternatives are named. It does give clear operational context for choosing origin form (lat/lon vs where, not both/neither), but tool-selection criteria against siblings are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
land_use_atLand use at a pointARead-onlyIdempotent
What kind of land is this: land use and land cover classification at a point.
From Overture's base theme (issue #167) β PlaceRoot's first tool over
base, distinct from the place-search and area-summary tools (those cover
discrete POIs, not the land itself). Returns {"lat", "lon", "land_use":
{"subtype", "class", "name"} or null, "land_cover": {"subtype",
"class"} or null}. No raw geometry (design rule: answers, not data).
null for either field means no polygon of that type covers the point β
coverage is OSM-derived and patchy outside well-mapped cities, so this
is a common, valid answer for a rural or remote point, not an error.
When multiple polygons overlap (Overture nests them, e.g. a park inside
a residential parcel), the smallest/most specific one is returned and
a "note" flags that the pick was made among several valid candidates.
Returns a structured {"error": ...} if upstream is unavailable or a
base-theme dataset is missing geometry/bbox, and {"error":
"bad_request"} for a non-finite or out-of-range coordinate.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description richly documents null semantics, patchy OSM coverage, overlapping-polygon resolution, the 'note' flag, and structured error cases for upstream failures and bad coordinates. This is exactly the behavioral context an agent needs that annotations cannot provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, every sentence earns its place: purpose, output shape, null meaning, overlap behavior, and error semantics are all covered without redundancy. The most important scoping information appears early.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description covers the response shape, valid null cases, overlap selection logic, and failure modes. An agent has enough information to invoke it correctly and interpret results, especially with the output schema also present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only exposes lat/lon as numbers with zero description coverage. The tool description adds minimal parameter-specific meaning beyond mentioning out-of-range coordinates as an error case; the parameter names are self-evident, but coordinate system and range details are not explicitly documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear question-answer framing ('What kind of land is this') and explicitly identifies the resource as land use and land cover classification at a point. It also distinguishes itself from place-search and area-summary tools, making its purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states the tool is for querying land itself, not discrete POIs, and names the broad tool categories it is distinct from. However, it does not explicitly contrast with point-query siblings like infrastructure_at or buildings_at, so an agent could use more direct exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
meeting_pointMeeting pointARead-onlyIdempotent
Where several people should meet, fairly: candidate venues ranked by equalized travel time, not geometric distance.
Fairness objective: minimize the MAXIMUM per-person travel time to the
venue ("no one gets screwed"), tie-broken by the smaller spread
(max - min across everyone), then by the smaller total. This is
deliberately not "minimize the average" β that objective can strand
one person with a long trip so two others get a short one.
origins is 2-5 points, each a {"lat": ..., "lon": ..., "mode": ...}
dict, a GERS id, or a free-text place name, mixed freely β mode is
"walk", "cycle", or "drive", defaulting to "walk" when omitted (a
string origin always gets the default mode; give a dict with "mode" to
pick otherwise), and can differ per person (e.g. one driving, one
walking). An id/name that failed to resolve returns an indexed error
(origins[i]: ...) with candidates on ambiguity. Any origin given by
id/name adds "resolved": [{"index", "name", "id", "lat", "lon",
"matched_by"}, ...] for just those origins; absent when every origin
was already coordinates. category optionally filters candidate venues
to an Overture taxonomy slug (e.g. 'coffee_shop'); a wrong or
unrecognized slug is a silent zero-match, not an error.
Method: a seed center is computed from each origin's implied
straight-line travel time (not raw distance, so a walking participant
pulls the center toward them more than a driving one at the same
distance), venues are searched for near that seed, and each
candidate's real per-person times come from routing.route() β the
exact routed number, not the seed's approximation. The total routed
(candidate, origin) fan-out is capped at 16 pairs, regardless of
`limit` β 8 candidates at 2 origins, down to 3 candidates at 5.
Returns {"center": {"lat", "lon"}, "candidates": [{"id", "name",
"category", "lat", "lon", "per_person": [{"origin_idx", "mode",
"travel_time_min", "distance_m"}, ...], "max_travel_time_min",
"spread_min"}, ...]}, ranked fairest-first, capped at `limit` (default
3, max 5). per_person entries carry origin_idx aligned to the input
origins list, one entry per origin β a candidate that can't be routed
from every origin (no street graph nearby, or genuinely disconnected)
is dropped from the ranking entirely rather than ranked on a partial,
unfair comparison. A per_person leg whose street graph hit its
internal size cap carries "truncated": true (as does its candidate,
and the answer carries a note) β that leg's time may be off. An empty
"candidates" list is a valid answer (nothing matched the category
nearby, or nothing routed from every origin) β it carries a "note"
explaining which, including when every pair was over the mode's
straight-line routing cap (try a faster mode).
confirm=true after the user agreed to wait for a first-time
street-graph build (about 5β25 seconds; see `route`). Without it, a
fan-out that would need a cold graph build returns {"error":
"needs_confirm"} instead of silently blocking. Omit confirm unless you
just asked and they said yes.
A non-empty result also carries "map" (#369) β a render-ready payload,
keyword-splattable straight into this server's map-rendering tool (its
keys are exactly that tool's keyword arguments): pins every origin, the
fairest candidate picked out by class, the rest, and the fairness seed
center, plus a one-line summary naming the fairest venue and its
numbers. Absent when "candidates" is empty.
Returns a structured {"error": "bad_request", ...} if origins has
fewer than 2 or more than 5 points, a point is missing/non-numeric
lat or lon, or a mode isn't walk/cycle/drive; {"error": "bad_request",
...} with the offending coordinate if lat/lon is out of range; or a
structured {"error": ...} if the upstream places or transportation
dataset is unavailable or missing columns this tool depends on.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| confirm | No | ||
| origins | Yes | ||
| category | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations, disclosing the seed-center method, routed-time computation, the 16-pair fan-out cap, cold-graph confirmation behavior, truncated leg handling, candidate dropping when routing fails, silent zero-match categories, and the optional map payload. These operational details are consistent with the readOnly/idempotent/non-destructive annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every paragraph earns its place: purpose and fairness first, then method, parameter details, return format, map payload, and error behavior. The structure is scannable, front-loaded with the core concept, and the density is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with four parameters, a nuanced fairness algorithm, multiple input types, and several edge cases, the description is complete. It covers input validation, ranking details, return shape, error structures, caps, truncated results, and the map payload, leaving no critical gap for an agent deciding whether and how to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the full load for parameters, and it does. It explains origins types and mixing rules, mode defaults and per-origin modes, limit default and maximum, category slug behavior, and confirm semantics with the cold-graph build wait. This is far more than the raw schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific purpose: compute fair meeting venues ranked by equalized travel time, not geometric distance. It also explains the fairness objective in detail, clearly distinguishing this tool from sibling geospatial tools that answer different questions such as distance matrices or area suggestions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly identifies the use case: several people need to meet somewhere fairly, and explicitly contrasts the max-travel-time objective with the 'minimize the average' approach. It does not name alternative sibling tools, but it gives thorough contextual guidance, including when to pass confirm=true and when to omit it, which is strong practical usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
neighborhood_verdictNeighborhood verdictARead-onlyIdempotent
Life-decision neighborhood verdict, not a data dump.
Accepts a point plus free-form life context (household, mobility,
priorities) and returns a ranked verdict: strengths, weak points, and
the one thing to verify in person. Empty context still answers a
generic walk-first daily-needs check and says what was assumed.
Optional radius_m / minutes / mode override what the context implies
(no car / walk-first -> walk, bike -> cycle, car -> drive; default
walk, 15 minutes). Does not call out to extra remote APIs.
Returns a structured {"error": ...} for bad coordinates, an unknown
mode, a radius past the mode cap, upstream failure, or a degraded
schema. Missing street graph degrades to straight-line times with a
note rather than failing the verdict.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| mode | No | Travel mode override. Default: inferred from context, else walk. | |
| context | No | ||
| minutes | No | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the read-only and idempotent annotations by disclosing that it does not call external APIs, returns structured errors for multiple failure cases, and degrades gracefully to straight-line times when street graphs are missing. This gives the agent a clear picture of side-effect-free behavior and fallbacks without needing to probe the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than a typical one-liner, but every sentence adds meaningful detail about behavior, defaults, or failure modes. It is front-loaded with the core purpose and then efficiently covers edge cases. The density is appropriate for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers invocation parameters, defaults, error conditions, degradation behavior, and the nature of the returned verdict. An output schema is present, so the exact return shape does not need to be enumerated here. For a tool with this many optional behaviors, the description is complete and self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 17%, so the description carries the burden of explaining parameters. It explains the mode override mapping from context, default walk with 15 minutes, the meaning of radius_m/minutes as overrides, and how empty context behaves. The only remaining parameters are lat/lon, which are self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: accepting a point plus life context and returning a ranked verdict with strengths, weak points, and a verification item. It distinguishes itself from siblings by explicitly saying it is 'not a data dump' and by focusing on life-decision output. The action and resource are specific enough for an agent to recognize its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool through phrases like 'life-decision neighborhood verdict' and explains what happens with empty context, but it never explicitly names alternative tools or states when not to use it. The guidance on mode and radius overrides is useful for invocation but does not fully replace explicit sibling routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
optimize_routeBest visiting order for stopsARead-onlyIdempotent
Best order to visit several stops: multi-stop route ordering (a small TSP).
Answers "I have these five errands, what order costs least" β stops is a
list of 2-10 points, each a {"lat": ..., "lon": ..., "name": ...
(optional)} dict, a GERS id, or a free-text name, mixed freely. The
answer is the cheapest visiting order over the real street graph, not a
straight-line guess. Solved exactly (Held-Karp over the routed cost
matrix), so it is the optimum, not a nearest-neighbour approximation.
Any stop given by id/name that failed to resolve returns an indexed
error (stops[i]: ...) with candidates on ambiguity β the whole call
fails, not silently drops that stop.
Returns {"order": [stop indices, in visiting order], "legs":
[{"from_idx", "to_idx", "distance_m", "duration_s"}, ...],
"total_distance_m", "total_duration_s", "mode", "roundtrip", "export"}
β indices refer to the input `stops` list, and there is no
polyline/geometry β for a single pair's numbers on their own, call
`route`. export is the pocket handoff: a multi-stop Google/Apple Maps
directions URL (coordinates only β no Maps API), a GPX 1.1 document
with every stop as a waypoint, and a printable list that keeps any
names the caller passed. If a stop already carries confidence or
operating_status (from a prior place lookup), the response adds
verify_before_going naming the 1β2 weakest. Any stop given as an id or
name adds "resolved": [{"stop": i, "name", "id", "lat", "lon",
"matched_by"}, ...] for just those stops β plain {lat,lon} stops need
no echo and the key is absent when every stop was already coordinates.
keep_order=true visits the stops in the order you gave and never
reorders them: the itinerary is the caller's, and this tool supplies
routed (not straight-line) per-leg numbers, the totals, and the export
for it β one street-graph build for the whole run instead of chaining
`route` per leg. Use it whenever the order came from the user ("first
the bank, then the school, then home"); leave it off to be told the
cheapest order. The response echoes "keep_order": true, and "order" is
then just 0..n-1. start_index must stay 0 with it (there is nothing to
fix β the given order already starts where it starts), and roundtrip
still chooses whether the last leg closes back to the first stop, so a
one-way itinerary wants roundtrip=false.
start_index (default 0) is fixed as the first stop. roundtrip=true (the
default) returns to it; the closing leg is in "legs" but the start is not
repeated in "order". roundtrip=false is an open path that ends wherever
is cheapest. Omit mode to use the stored preferences mode, else drive. Same
cost model every routing tool uses; one-ways make the drive/cycle cost
matrix asymmetric and that is solved for exactly. The objective minimized
is total duration.
If some pair of stops has no route between them (disconnected road data),
the call still succeeds: that leg's numbers are a straight-line estimate,
the leg carries "estimated": true, and the response carries
"estimated": true plus a note naming the estimated legs β so a flagged
approximation, never a crash.
confirm=true after the user agreed to wait for a first-time street-graph
build (about 5β25 seconds). Pass it only after a needs_confirm reply
and they said yes. One gate for the whole call β every stop rides the
same graph, so it asks once, never once per leg. A warm or cached graph
never needs it. Omit confirm unless you just asked and they said yes.
Errors are structured, not raised: fewer than 2 or more than 10 stops, a
stop that is not a valid location reference, an out-of-range
start_index, or keep_order=true with a non-zero start_index return
{"error": "bad_request"} naming the offending stop
index; an unresolvable name/id returns {"error": "not_found"} or
{"error": "ambiguous_place", "candidates": [...]}, indexed the same way;
an unknown mode returns {"error": "unsupported_mode"}; a stop set whose
two furthest-apart stops are further apart than the mode's straight-line
cap (see `route`) returns {"error": "route_too_long"}; a stop with no
usable street node near it returns {"error": "no_graph_nearby"} naming
that stop's index.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Travel mode. Default: stored preference, else drive. | |
| stops | Yes | ||
| confirm | No | ||
| roundtrip | No | ||
| keep_order | No | ||
| start_index | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare read-only, idempotent, and non-destructive behavior, and the description adds substantial behavioral context beyond that: exact Held-Karp optimization, structured errors, estimated straight-line legs on disconnected graphs, and the confirmation/one-time-build behavior. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but each paragraph covers a distinct, necessary concern: optimization semantics, `keep_order`, start/roundtrip behavior, estimation, confirmation, and errors. The key distinction from `route` is front-loaded, and the length is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the sparse schema, the description is complete: it covers input constraints, parameter interactions, return structure, error categories, ambiguous stops, disconnected road data, and the confirmation flow. An agent has everything needed to invoke and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 17%, so the description carries the full burden for parameters. It explains each stop format (`{lat, lon, name}`, GERS id, free-text name, mixed), mode defaults, `roundtrip`, `keep_order`, `start_index`, and `confirm` in enough detail to use the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement of what the tool does: 'Best order to visit several stops: multi-stop route ordering (a small TSP).' It also differentiates from the sibling `route` tool by explicitly saying a single pair's numbers should use `route` instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: use `keep_order=true` when the order came from the user, omit it to get the cheapest order, and call `route` for a single pair. It also clearly states the `confirm` gate: pass it only after a `needs_confirm` reply and user agreement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
place_detailsPlace detailsARead-onlyIdempotent
One place, in full: addresses, websites, phones, socials, brand, source attribution, GERS id, confidence, operating status, and a compact trust_note.
Resolve either by GERS id (the `id` field find_places and other tools
return) or by name + lat/lon (nearest name match within radius_m of
that point). Pass id, or pass name together with lat and lon β not
both. Long array fields (addresses, websites, phones, socials, sources)
are capped and never silently dropped: a truncated field carries a
matching "<field>_omitted_count". Returns {"error": "not_found", ...}
if nothing matches, or a structured {"error": ...} if the upstream
dataset is unavailable or missing columns this tool depends on.
When looking up by id, also pass near_lat/near_lon β the lat/lon from
the find_places (or other tool) row the id came from β so the lookup
can be narrowed to a ~50km box instead of scanning the whole dataset.
Ignored when resolving by name. Omitting it still works, just slower on
a cold, uncached id.
lang (#410) requests Overture's language-tagged name variant for this
place, when the data has one: `name` becomes the variant and
`name_primary` is added only when it differs. Default: the stored
`preferences()` lang, else the primary name unchanged. Never invented
or transliterated.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | ||
| lat | No | ||
| lon | No | ||
| lang | No | Result-language code (2-3 lowercase letters, e.g. "de"). Overture-tagged name variants only β never transliterated or invented. Default: stored preference, else the primary name. | |
| name | No | ||
| near_lat | No | ||
| near_lon | No | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, and the description adds substantial behavioral detail beyond that: truncation carries _omitted_count, errors have structured shapes, missing upstream data is surfaced, and lang variants are never invented or transliterated. This is rich, honest behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with a compact summary and each paragraph earns its place. The '#410' reference is minor noise, and the amount of detail is justified given the tool's optional-parameter complexity and resolution modes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 don't need elaboration, and the description covers the remaining operational context: both resolution branches, required parameter pairing, truncation semantics, error responses, performance implications, and language handling. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 13%, so the description carries the full burden, and it succeeds. It explains id, name, lat/lon pairing, radius_m scope, near_lat/near_lon purpose and perf impact, and lang behavior far beyond the schema's bare definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'One place, in full' and enumerates the exact payload fields, making the resource and scope unmistakable. It also specifies two distinct resolution modes, which separates it from other place-related sibling tools without needing to open their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage rules: pass id, or pass name together with lat/lon, 'not both'; near_lat/near_lon are for id lookups and ignored for name lookups. It does not explicitly compare against sibling tools like resolve_place, but the resolution instructions are concrete and actionable enough to prevent incorrect calls.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
places_along_routePlaces along a routeARead-onlyIdempotent
Places on the way from A to B: corridor search along the route.
Answers "find a coffee shop on my drive to the airport" β the route tool
plus find_places in one call. Builds the same street-graph shortest path
`route` returns, then finds places whose nearest point on that path is
within max_detour_m (default 1000m, capped at 5000m; larger values
return a bad_request error rather than being silently clamped).
Each result row is a find_places row plus two numbers: detour_m, the
straight-line distance to the route doubled β an approximation of the
round trip off and back on, not a re-routed detour β and along_m, how
far along the route from the origin that place sits, so "roughly
halfway" is answerable. Results are ordered by along_m (route order,
reading as an itinerary) rather than by detour cost. When more than
limit places are on the way, the response is an even sample spanning the
whole route β never just the first limit, which would drop the far end
of the journey β and carries "truncated": true saying so. It also
carries {"route": {"distance_m", "duration_s", "mode"}} for the
underlying route. A composed itinerary also carries
verify_before_going when any stop is low-confidence or listed closed,
naming the 1β2 places most worth checking.
category and name narrow the search exactly as they do in find_places
(category matches Overture's taxonomy, e.g. 'coffee_shop'; name is a
substring match) β worth passing on a long route, since an unfiltered
corridor through a dense area can hold more places than the search
considers, in which case the response carries "truncated": true and a
note saying so.
Omit mode to use the stored preferences mode, else drive. Same cost model
and the same straight-line-distance caps as `route`, and the same
structured errors: route_too_long, no_graph_nearby, no_route,
unsupported_mode, and bad_request for non-finite/out-of-range
coordinates or an invalid max_detour_m.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Travel mode. Default: stored preference, else drive. | |
| name | No | ||
| limit | No | ||
| to_lat | Yes | ||
| to_lon | Yes | ||
| category | No | ||
| from_lat | Yes | ||
| from_lon | Yes | ||
| max_detour_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already declaring read-only, idempotent, and non-destructive hints, the description adds substantial behavioral context: results are ordered by along_m rather than detour cost, the detour_m metric is an approximation rather than a re-routed detour, results are evenly sampled when truncated, and a composed itinerary carries verify_before_going. This is far beyond the annotation baseline and meaningfully informs invocation and result interpretation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place, covering purpose, filtering, output fields, ordering, truncation, route metadata, and error behavior. It is front-loaded with the core concept, then branches into increasingly specific details, making it dense yet scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, parameter count, and the availability of an output schema, the description covers all the non-obvious aspects an agent needs: result row structure, ordering semantics, sampling behavior, route metadata, composed-itinerary verification, mode resolution, and error cases. Nothing material is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 11%, but the description thoroughly compensates by explaining max_detour_m's default, cap, and error behavior; category and name semantics matching find_places; mode's default-to-stored-preferences behavior; and limit's effect on sampling/truncation. Even the coordinate parameters are implicitly clear from the 'from A to B' framing and the route context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb phrase 'corridor search along the route' and explicitly answers an example query, making the tool's function immediately clear. It also distinguishes itself from sibling tools by describing itself as 'the route tool plus find_places in one call,' so an agent can tell it apart from both without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: when the need is 'places on the way from A to B,' and it names the constituent siblings (route and find_places) without being either one alone. It also provides practical guidance on when to pass filters ('worth passing on a long route') and how mode selection behaves, giving an agent actionable selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preferencesPersistent preferencesADestructiveIdempotent
Travel defaults.
State "I bike everywhere, I have a dog" once. Routing tools use the
stored mode when you omit theirs; an explicit argument always wins.
pace and household are stored for later features and do not change
answers yet. lang (#410) is the stored result-language preference: the
name-lookup tools that accept their own `lang` use this one when
theirs is omitted, returning an Overture-tagged name variant (e.g.
"Munich" for "MΓΌnchen" with lang="en") β a per-call `lang` always
wins. The same document is the placeroot://preferences resource.
Call with no arguments to read. Pass mode, pace, household tags, a
free-text note, or lang to merge those fields.
clear=true deletes the file and cannot be combined with other fields.
Nothing is sent off this machine.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Result-language code (2-3 lowercase letters, e.g. "de"). Overture-tagged name variants only β never transliterated or invented. Default: stored preference, else the primary name. | |
| mode | No | Travel mode to store. Omit to leave it unchanged. | |
| note | No | ||
| pace | No | ||
| clear | No | ||
| household | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already include idempotentHint=true and destructiveHint=true, but the description adds essential behavioral detail: clear=true deletes the file and cannot be combined with other fields, 'Nothing is sent off this machine,' and 'The same document is the placeroot://preferences resource.' It also explains that pace and household do not yet affect answers, and exactly how lang selection works with name-lookup tools. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it opens with 'Travel defaults,' immediately states the core use case with an example, then covers edge behaviors (explicit args win, pace/household inert, lang semantics, clear, privacy). Each sentence earns its place and the structure flows from the most common use to edge cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, parameter count of 6, and only 33% schema coverage, the description still covers the essential call patterns: read, merge, clear, and how stored values affect other tools. It explains the persistence resource identity and privacy, which is rare and valuable context. There is no missing information an agent needs to correctly call this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers individual parameters with descriptions for lang and mode, and an enum for mode. The description itself explains the merge semantics: 'Pass mode, pace, household tags, a free-text note, or lang to merge those fields.' It also gives a concrete example of lang usage ('Munich' for 'MΓΌnchen'). Since schema description coverage is only 33%, the description significantly compensates by explaining how parameters behave as a group, though it does not individually document note, pace, and household beyond listing them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool reads and merges persistent preferences, including travel mode, pace, household, note, and language. It distinguishes itself from routing and name-lookup tools by explaining how stored preferences interact with those tools. The phrase 'Travel defaults' and the explicit 'Call with no arguments to read. Pass mode, pace, household tags, a free-text note, or lang to merge those fields.' provide a specific verb and resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use this tool: to set travel defaults, household info, and stored language preferences. It distinguishes from routing tools by noting 'Routing tools use the stored mode when you omit theirs; an explicit argument always wins.' It also clarifies that pace and household are stored for later features and do not change answers yet, preventing misuse. The clear=true behavior and its exclusivity are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
render_mapRender mapA
Render any result as a shareable one-pager: map, verdict, and stop list.
Writes ONE self-contained HTML file β interactive SVG map (inline CSS/JS,
vector markers with labels and click popups, polygon/line shapes
including reachability output shaped {"polygon": ..., "stats": {...}}),
a composed verdict, per-stop details, a scale bar, and required
attribution. A shape feature's properties may carry "role": "shed"
(soft translucent fill, dashed edge β for travel-time sheds) or
"role": "outline" (no fill, strong edge β for a compared-area boundary);
any other/absent role keeps the default style. Properties may also carry
a short "label" and one-line "callout", rendered as a text chip over the
shape (capped ~40/~80 chars); for the reachability payload, set
role/label/callout at the payload's top level. No CDN, no tile server,
no API key, zero
network requests when opened β a local file the user can send as-is.
Pass `summary` for
the verdict you want on the page (the sentence you'd tell a spouse,
co-founder, or landlord); when omitted a short fallback is composed
from the payload. Written to PLACEROOT_ARTIFACT_DIR (default: alongside
the tile cache directory). The file itself is the artifact; this tool's
response stays small on purpose. Returns {"path", "bytes",
"features_rendered", "skipped_features"} (plus "truncated": True when
applicable) β skipped_features counts rows/features that couldn't be
rendered (missing coordinates, malformed geometry, or dropped past
mapview.MAX_RENDER_VERTICES) rather than failing the call outright. Pass
inline=true to also get the HTML back in the response when it's small
enough to be worth it.
A point in `result` carrying a "class" property gets a contrasting
marker dot when `legend` maps that class to {"label": str, "color":
str?} β pass e.g. {"open": {"label": "Open now"}, "closed": {"label":
"Closed", "color": "#d55e00"}}. A missing color is assigned from a
fixed color-blind-safe palette; an invalid one (not #rgb/#rrggbb hex)
is dropped rather than used. Classes actually present get a legend box
on the page; a class not in `legend` keeps the default dot and is
reported in the response's "note". Omitting `legend` (or a result with
no "class" properties) renders exactly as before.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | ||
| inline | No | ||
| legend | No | ||
| result | Yes | ||
| summary | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide no read-only, idempotence, or destructiveness hints, so the description carries the full burden β and it delivers. It discloses file writing to PLACEROOT_ARTIFACT_DIR, fallback summary composition, skipped-feature behavior rather than hard failure, inline response behavior, color validation/drop rules, and zero network requests. These are substantial behavioral details beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence carries necessary operational detail: artifact location, styling rules, edge cases, response fields, and optional parameters. It is front-loaded with the core purpose and then layers detail appropriately. No repetitive or filler content is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, zero schema coverage, absent annotation hints, and an output schema, the description covers everything an agent needs: input structures, transformation rules, output fields, environment behavior, failure handling, and size caps. It is complete for safe and correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must compensate for all parameters, and it does. The `result` structure, `summary` purpose, `inline` behavior, and the full `legend` mapping format with examples are all explained. Only `title` is not explicitly covered, but its meaning is self-evident from the parameter name and default. The description adds significant semantic value beyond the bare input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Render any result as a shareable one-pager: map, verdict, and stop list.' It then details the exact artifact produced (a self-contained HTML file with interactive SVG map), distinguishing this tool from the data-retrieval and geometry siblings. The purpose is unambiguous and complete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes clear context for when to use the tool: any time a shareable map/verdict one-pager is needed, including reachability payloads, shape roles, and point classes. It does not explicitly name alternatives or exclusions, but the 'any result' phrasing and detailed payload examples provide enough usage guidance. Missing explicit when-not-to-use information keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_placeResolve place to GERS idARead-onlyIdempotent
Free-text place reference -> ranked, typed GERS ids to hold onto.
Turns something like "the Whole Foods on Lamar" or "Travis County" into
stable Overture ids: merges geocode()'s division matches (locality,
region, county, country, ...) with a name-filtered find_places search
(a business or POI), bbox-limited to near_lat/near_lon if given, else to
the ~20km vicinity of the top division match.
**Split the location out of the query, and pass `city`.** You know
things this server does not: that "san jose airport" means San Jose,
California, that the Eiffel Tower is in Paris, that a user asking about
"BASIS Silicon Valley" means Sunnyvale. This server knows only what
exists at which coordinates in the current Overture release. When the
location arrives inside one string, it has to guess which words are the
place β and it guesses from map data alone, where "san" names a division
in Henan and "palo" names one in Leyte. Given `city="San Jose, CA"` and
`query="airport"` there is nothing to guess.
A wrong hint costs a miss and a retry, never a wrong answer: `city`
only bounds where the search looks, and the returned rows still come
from the data. Pass `near_lat`/`near_lon` instead when you have real
coordinates β they are the strongest hint of all.
When nothing resolves for want of a location, the reply carries
`need: "location"` and a `retry_with` sketch rather than only prose,
so the second call can be made without parsing English.
Returns {"results": [{"id" (GERS), "kind": "division" | "place",
"name", "lat", "lon", "match": "exact" | "prefix" | "substring" |
"fuzzy", plus "admin_context" for a division or "category" for a
place}, ...]}, ranked by match tier then prominence ("fuzzy" β reached
by close spelling rather than by containing the query at all, #215 for
divisions and #373 for places β ranking below every literal match).
A place found through #373's alt-spelling/typo fallback additionally
carries "matched_by": "alt_name" | "fuzzy", and a top-level "note"
names the spelling actually matched. Budgeted like every other tool.
An unresolvable query returns {"results": []} β not an error. Returns a
structured {"error": ...} instead of raising if the remote scan fails
or the places dataset is missing columns this tool depends on.
lang (#410) requests Overture's language-tagged name variant, same as
geocode() β but only for "kind": "division" rows; "kind": "place" rows
(from find_places, out of scope for #410 this round) always carry
their primary name. Default: the stored `preferences()` lang, else the
primary name unchanged.
Division candidates come from geocode() (#406), so a configured
`PLACEROOT_HOME` nudges the same ambiguous-namesake ties this tool
merges from β see geocode()'s docstring. resolve_place does not add its
own disclosure note for that; its own ranking already leads with
distance to `near_lat`/`near_lon`/`city` when one is given.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | ||
| lang | No | Result-language code (2-3 lowercase letters, e.g. "de"). Overture-tagged name variants only β never transliterated or invented. Default: stored preference, else the primary name. | |
| limit | No | ||
| query | Yes | ||
| near_lat | No | ||
| near_lon | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only, idempotent, non-destructive behavior. The description adds substantial behavioral context beyond that: it merges geocode and find_places, ranks by match tier, returns empty results instead of errors for unresolvable queries, returns structured errors on remote failures, and explains lang behavior per row kind.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but front-loaded with the core purpose, and uses concrete examples and clear sections. Some references, such as internal issue numbers (#215, #373, #410) and 'Budgeted like every other tool', add marginal value for an agent and could be trimmed without losing essential guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite low schema coverage and a complex 6-parameter surface, the description covers input strategy, ranking semantics, return shape, error behavior, language handling, and even the impact of PLACEROOT_HOME. An agent has enough information to call the tool correctly and interpret its output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 17%, so the description carries the burden for most parameters. It richly explains query via examples, city, near_lat/near_lon, and lang. However, limit is never described beyond its schema default, and query's exact format is only implied rather than stated formally.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line 'Free-text place reference -> ranked, typed GERS ids' states a specific transformation with a clear resource. It further distinguishes itself by naming geocode() and find_places as the merged sources, so an agent can tell it apart from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs callers to 'Split the location out of the query, and pass city' and explains when to prefer near_lat/near_lon instead. It also names the failure/retry path with need: 'location' and retry_with, leaving little ambiguity about when and how to invoke the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_place_batchResolve GERS ids in batchARead-onlyIdempotent
Resolve up to 25 GERS ids to compact place rows in one call.
Collapses N place_details(id=...) round-trips into one: for each id,
resolves it via the same lookup place_details uses and keeps only a
compact row β {"gers_id", "name", "category", "lat", "lon"} β not the
full place_details payload (addresses, websites, phones, socials,
sources, brand, confidence, ...). Use place_details for full detail on
a single id. Results are returned in input order; an id that doesn't
resolve gets the standard error envelope {"gers_id", "error":
"not_found", "detail"} instead and does not fail the rest of the
batch. gers_ids is capped at 25; a longer list
returns a structured {"error": ...} rather than truncating silently.
An empty list returns {"results": []}. Budgeted like every other tool.
Returns a structured {"error": ...} instead of raising if the remote
scan fails or the places dataset is missing columns this tool depends
on.
| Name | Required | Description | Default |
|---|---|---|---|
| gers_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint and idempotentHint true, but the description adds substantial behavioral context: the 25-item cap, order preservation, per-id error envelopes for unresolved ids, empty-list behavior, budgeted execution, and structured errors instead of exceptions on remote scan failure or missing dataset columns. This goes well beyond the annotations and fully discloses side-effect-free but potentially failure-prone behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then adds a dense but focused set of behavioral details. Every sentence contributes: batch collapse rationale, comparison to place_details, output shape, ordering, per-id error handling, cap behavior, empty-list behavior, budgeting, and error fallback. Nothing is redundant or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover read-only/idempotent safety, the description fills every remaining gap an agent needs: max batch size, result ordering, exact compact row fields, error shapes for not-found and batch-level failures, empty-list behavior, and budget expectations. There is no missing context that would prevent correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only 'gers_ids' as an array of strings with zero description, so the description must carry the semantic weight. It does: it explains what the ids are (GERS ids), the maximum count, how each is resolved, the output shape, ordering, and error behavior. This is far more than the schema alone offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Resolve up to 25 GERS ids to compact place rows in one call.' It clearly distinguishes itself from place_details by emphasizing compact rows versus the full payload, and from the singular resolve_place by the batch dimension. The purpose is immediately clear even to an agent unfamiliar with the tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly explains when to use this tool: to replace N place_details round-trips, and explicitly says 'Use place_details for full detail on a single id.' This gives an agent a clear decision rule and a named alternative. The behavior for empty lists and oversized batches further clarifies expected usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reverse_geocodeReverse geocode a pointARead-onlyIdempotent
Point -> nearest address (street/number/postcode) and its containing division chain.
Degrades to a divisions-only result (source: "divisions_only", plus a
note) if the addresses theme is unreachable, missing, or has no nearby
coverage β addresses is Overture's newest, least complete theme, so
this is the expected degraded path. Returns a structured {"error": ...}
instead of raising if the remote scan fails outright.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint annotation by explaining the degraded divisions-only path, the source identifier 'divisions_only', the reason addresses may be missing, and the structured error return instead of an exception. This is rich, honest behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly packed sentences convey the core operation, the degraded mode, the cause, and the error behavior. No filler or redundancy; the most important output semantics are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple in inputs, has an output schema to cover result shape, and annotations to cover safety. The description adds exactly the missing context: the expected degraded path and error handling. Nothing critical is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description was responsible for explaining lat/lon semantics, but it only refers to a 'Point' generically. It does not state coordinate format, bounds, or how the point maps to the parameters, leaving the agent with only the property names 'lat' and 'lon'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific operation: converting a geographic point into the nearest address and its containing division chain. It distinguishes this from forward geocoding and batch reverse geocoding through the 'Point -> ...' framing and the tool name/title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage context is implied: it handles a single point and returns address plus divisions. However, it never explicitly says when to prefer this over reverse_geocode_batch, geocode, or address_at, and it names no alternatives or exclusion conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reverse_geocode_batchReverse geocode points in batchARead-onlyIdempotent
Reverse-geocode many points in one call, to cut N round-trips down to one.
Accepts at most 20 points; a longer list returns a structured
{"error": "bad_request"} instead of processing anything. Returns one
row per point in `points`, in the same order β each row is whatever
reverse_geocode(lat, lon) returns (address/divisions chain, or a
"divisions_only" degrade β see reverse_geocode's docstring). A
malformed point (missing/non-numeric lat/lon, or a lat/lon out of
range) doesn't fail the whole batch β it yields the standard error
envelope {"lat", "lon", "error": "bad_request", "detail"} in its slot
instead.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, non-destructive behavior, and the description adds substantial behavioral detail beyond that: the 20-point limit, whole-batch rejection on overflow, per-point ordering, degrade behavior, and per-slot error envelopes for malformed points. This is exactly the kind of context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then moves through behavior in a logical order: limit, success shape, and error handling. Every sentence adds necessary operational detail without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a batch tool with one parameter, no schema descriptions, and a rich behavioral surface, the description covers the critical execution semantics: limits, ordering, degraded mode, and partial failure behavior. It is complete enough for an agent to invoke the tool correctly without needing additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 0%, so the description carries the full burden. It explains that `points` is a list of points with lat/lon, imposes a batch size limit, defines what counts as malformed, and describes how each point is processed and returned. This compensates fully for the schema's lack of detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Reverse-geocode many points in one call.' It clearly distinguishes this batch tool from the single-point reverse_geocode sibling by emphasizing the batching behavior and round-trip reduction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames the tool for 'many points' and says its purpose is to cut N round-trips down to one, giving a clear when-to-use signal. It also references reverse_geocode as the per-point behavior source, which implicitly identifies the alternative for single-point use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
routeRoute between two pointsARead-onlyIdempotent
Route: shortest-path distance and duration between two points, by mode.
Give the two ends as from_lat/from_lon and to_lat/to_lon, or as
from/to β each a {"lat", "lon"} dict, a GERS id, or a free-text place
name β but not both (and not neither); either way returns
{"error": "bad_request"} naming the choice. Do not call geocode(),
resolve_place(), or geocode_batch() first: names and ids resolve in
parallel inside this call, and the "from"/"to" blocks come back
carrying whatever each end resolved to.
Compact directions, not turn-by-turn: builds a street graph from
Overture's transportation theme around the two points and returns
{"distance_m", "duration_s", "mode", "from", "to", "export"} for the fastest path β no polyline unless you ask for one. export is the pocket handoff: Google/Apple Maps directions URLs built from the same two coordinates (URL schemes only β no Maps API, no extra network), a GPX 1.1 document, and a printable stop list. Same cost model every routing tool uses (walk 1.4 m/s, cycle 4.2 m/s, drive per-edge from Overture's speed_limits or a class-based default table). drive's duration is a posted-speed model with no live traffic; all modes snap each endpoint to the nearest usable street-graph node (real routes rarely start/end exactly on a segment).
Each mode has a straight-line-distance cap on the two points, rejected
before any graph is built (see routing.ROUTE_MAX_STRAIGHT_LINE_M, derived
per-mode from the shared graph-extraction radius cap β roughly
walk 7.5km, cycle 23.5km, drive 95.5km) β real road distance only ever
exceeds straight-line, so anything past the cap can't produce a route
worth extracting for anyway; returns {"error": "route_too_long"} with
the exact cap in "max_distance_m". An unrecognized mode string returns
{"error": "unsupported_mode"}; non-finite or out-of-range coordinates
(lat outside [-90, 90], lon outside [-180, 180]) return
{"error": "bad_request"}. If no usable graph or street node is found
near either point, returns {"error": "no_graph_nearby"}. If both points
snap into the graph but no path connects them (e.g. disconnected
islands of road data), returns {"error": "no_route", "try": ...}
rather than raising β "try" is a mode-tuned next move (roadmap Β§4). If
the extraction graph hit its internal size cap, the result
carries "truncated": true β the route may be suboptimal or incomplete.
include_path=true adds "path", a GeoJSON LineString from the origin's
snapped node to the destination's that follows the streets' own
geometry (curves included), simplified to fit the token budget, with
"path_max_deviation_m" bounding how far it strays from the exact
street path. Off by default (the polyline dwarfs the rest of the
answer) β ask for it only to draw or trace the route. If even a fully
simplified line won't fit, you get "path_omitted": true instead of a
line that stops short of the destination.
include_elevation=true adds "elevation": a compact climb profile from
the same keyless Copernicus GLO-30 DEM reader as point elevation lookups
use, sampled along the route β
"total_climb_m", "total_descent_m", "max_grade_pct", and a small
"samples" array of [distance_along_m, elevation_m] points, thinned to
fit the token budget. Off by default. Where the DEM has no coverage
along part or all of the route, the affected numbers are never faked as
0.0 β you get a "note" saying so instead (and no climb/descent/grade
keys at all if there's no coverage anywhere on the route). If even the
note-only form can't fit the budget, you get "elevation_omitted": true.
prefer="flat" asks the router to trade distance for climb β steeper
detours cost more than gentler ones, so a longer-but-gentler path can
win over a shorter-but-steeper one. Only meaningful for mode="walk" or
"cycle" (returns {"error": "bad_request"} for mode="drive"); needs
per-node elevations for the extracted street graph, fetched from the
same Copernicus source (bounded β see routing.FLAT_MAX_ELEVATION_NODES),
so if that data isn't reachable or has no coverage here, the route falls
back to plain-distance routing and says so in "prefer_note" rather than
silently ignoring the preference. IMPORTANT: prefer="flat" minimizes
elevation grade only β it is NOT a step-free, stroller-, or
wheelchair-accessible mode. Overture's transportation data (as read
here) carries no step-count, kerb-ramp, or surface attributes, so a
flight of stairs classified as ordinary walkway geometry can still
appear on a "flat" route if it's short and roughly level. Don't offer
this as an accessibility guarantee to the user; it isn't one.
avoid=["motorway"] (and/or "trunk") is the "no highways" ask: those
classes and their on/off ramps are dropped from the street graph before
the search, and the answer echoes "avoid". Those two values are the
whole vocabulary β anything else is a bad_request listing them. There is
no toll or ferry option, deliberately: Overture's road data carries no
toll attribute at all, and this graph is road-only so ferries are never
routed over. Tell the user that rather than approximating either with
avoid=["motorway"]. On walk and cycle it is a no-op (both already
exclude those classes) and says so in "avoid_note" instead of erroring.
An avoiding route is a different graph, so the first one in an area can
need its own confirm even where a plain route is warm; if the avoided
roads were the only link, the usual no_route comes back with "try"
naming avoid.
confirm=true after the user agreed to wait for a first-time street-graph
build (about 5β25 seconds). Pass it only after a needs_confirm reply
and they said yes. A warm or cached graph never needs it.
Omit confirm unless you just asked and they said yes.
A from/to name matching several equally-ranked places returns
{"error": "ambiguous_place", "candidates": [...]} instead of picking a
city; an unresolvable name or id returns {"error": "not_found"}; a
malformed one (empty string, dict missing lat/lon, wrong type) returns
{"error": "bad_request"} β the offending side is named in "field".
Ends that resolve a city apart return {"error": "too_far"} with both
ends and the mode cap, before any graph is built. from_to is this same
routing with a walk default.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| from | No | ||
| mode | No | Travel mode. Default: stored preference, else drive. | |
| avoid | No | Road classes to keep the route off. No toll or ferry option exists: Overture carries no toll attribute, and the graph is road-only. Default: none (no class avoided). | |
| prefer | No | Grade preference. Default: none (plain-distance routing). | |
| to_lat | No | ||
| to_lon | No | ||
| confirm | No | ||
| from_lat | No | ||
| from_lon | No | ||
| include_path | No | ||
| include_elevation | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and idempotent, and the description layers on substantial real behavior: endpoints snap to the nearest graph node, drive duration has no live traffic, distance caps trigger route_too_long, and graph failures return no_route/no_graph_nearby rather than raising. It also discloses fallback behavior for prefer='flat' and the deliberate absence of toll/ferry options. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is front-loaded with a one-sentence definition and organized by parameter and edge case. A few explanatory asides, such as the extended rationale for the straight-line cap and the repeated confirm warning, could be trimmed without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all 12 parameters, every documented error state, output fields, mode-specific caps, optional flags, and failure fallbacks. An output schema is marked as present, so the agent is not left without return-structure information; the description is complete for a complex tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description carries nearly the entire burden. It fully compensates: it explains the two mutually exclusive endpoint formats, the accepted from/to value types, the avoid vocabulary, the prefer='flat' semantics and accessibility caveat, and the include_path/include_elevation tradeoffs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states an exact verb and resource: 'shortest-path distance and duration between two points, by mode.' It also distinguishes the tool from its sibling by noting 'from_to is this same routing with a walk default,' so an agent can tell which route-like tool is which.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-not guidance: 'Do not call geocode(), resolve_place(), or geocode_batch() first: names and ids resolve in parallel inside this call.' It also explains exactly when confirm is needed, when include_path should be used, and when avoid is a no-op, which gives the agent clear decision criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_categoriesSearch categoriesARead-onlyIdempotent
Free text -> valid Overture category slugs, for the category param
the place-search and area-summary tools take.
Lookup only β no geo filtering, no upstream dataset dependency; matches
against a bundled snapshot of Overture's places taxonomy (pinned to
schema v1.9.0). Ranks exact slug match > slug prefix > slug substring >
a match on any taxonomy path segment, so close siblings like "cafe" vs
"coffee_shop" both surface rather than one silently winning. If the
whole query matches nothing, falls back to a lexical phrase-intent
match against a curated synonym lexicon (e.g. "fix my cracked phone
screen" -> mobile_phone_repair). Returns {"results": [{"slug", "path",
"confidence"}, ...]} β path is the root-to-leaf taxonomy (e.g.
["eat_and_drink", "cafe", "coffee_shop"]), confidence is 0-1 and
descending, budgeted like every other tool. An empty/whitespace query
returns {"results": []}. limit is clamped to 0-50, matching every
other tool's limit handling (out-of-range values are not an error).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses the ranking priority (exact slug match > slug prefix > slug substring > path segment), synonym-lexicon fallback, output shape (`{"results": [{"slug", "path", "confidence"}, ...]}`), confidence ordering, empty-query behavior, and limit clamping to 0-50. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence contributes a distinct operational fact: purpose, data-source snapshot, ranking order, fallback, output format, empty-query behavior, and limit semantics. The description is detailed but tightly organized and front-loaded with the main purpose before diving into specifics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers input semantics, output format, edge cases (empty/whitespace query, out-of-range limit), and behavioral guarantees (confidence descending, budgeted like other tools). Even with an output schema present, the description adds the semantic context needed for correct invocation, and nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides no property descriptions (0% coverage), so the description carries the full burden. It explains that `query` is free text mapped to category slugs with a defined ranking and fallback, and that `limit` is clamped to 0-50 with out-of-range values not treated as errors. The schema only supplies type and default, so the description adds essential meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Free text -> valid Overture category slugs, for the `category` param the place-search and area-summary tools take,' which states a specific conversion purpose and names the consumer tools. It further distinguishes itself by declaring 'Lookup only β no geo filtering, no upstream dataset dependency,' separating it from sibling geo/search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly indicates when to use the tool: to produce the `category` parameter for place-search and area-summary tools. It also gives exclusion cues ('no geo filtering, no upstream dataset dependency') and describes fallback behavior, so an agent can decide between this and sibling tools without additional inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
simplify_geometrySimplify geometryARead-onlyIdempotent
Simplify a GeoJSON geometry to fit a token budget, reporting what was lost.
Works on caller-supplied GeoJSON (Polygon, MultiPolygon, LineString,
MultiLineString; Points/MultiPoints pass through unchanged). Binary
searches the simplification tolerance until the result fits max_tokens
instead of asking the caller to guess one. Returns {"geometry": ...,
"max_deviation_m": ..., "original_points": N, "kept_points": M}, or a
structured {"error": "invalid_geometry", ...} for malformed input.
| Name | Required | Description | Default |
|---|---|---|---|
| geojson | Yes | ||
| max_tokens | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, non-destructive behavior. The description adds valuable behavioral context: binary search on tolerance, point geometries passing through unchanged, and a structured error response for invalid geometry. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the main purpose, then efficiently covers algorithm, input types, output shape, and error behavior. Every sentence earns its place; there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover safety, the description is complete enough. It specifies valid input geometry types, pass-through behavior, the meaning of max_tokens, and error handling. Nothing critical is missing for invoking the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry parameter semantics. It explains max_tokens as the token budget and describes the binary-search behavior. It also clarifies which GeoJSON types are accepted. It could add more detail about geojson structure, but it compensates for the sparse schema well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: simplify a GeoJSON geometry to fit a token budget. It also states exactly which geometry types are handled and which pass through, clearly distinguishing this from sibling tools like geometry_op and render_map.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use this tool: when a caller-supplied GeoJSON geometry needs to be simplified to fit a token budget. It does not explicitly name alternatives or say when not to use it, but the scope is specific enough that an agent can infer its niche.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_areasSuggest areasARead-onlyIdempotent
Where within reach: neighborhoods ranked by travel budget + amenities.
The inverse of every other area tool β instead of "describe this place",
"find me a place". anchors is 1-3 {"lat", "lon", "mode"?, "minutes"?}
points (mode: walk/cycle/drive, default from stored preferences;
minutes: default 15). requirements is 1-8 free-text amenity/character
strings, scored the same way as area_score.score_locality β "parks",
"groceries", "coffee shop" resolve against the Overture taxonomy;
a subjective phrase ("quiet streets", "safe neighborhood", "good
schools") comes back {"measurable": false} rather than a guessed score
(see "honesty" in the response).
Method: the same street-graph reach analysis behind PlaceRoot's other
travel-time tools computes each anchor's reachable shed; with more than
one anchor, the sheds are intersected (a candidate must be reachable
within EVERY anchor's own time budget, not just one β "office" and
"gym" both mean both). divisions.divisions_in_polygon (#348) partitions
the (intersected) shed into candidate neighborhoods/localities; each
candidate is scored against requirements the same way
area_score.score_locality (#349) does. Returns {"anchors": [...],
"results": [{"division_id", "name", "subtype", "overlap_fraction",
"lat", "lon", "travel": [{"anchor_idx", "mode", "minutes_budget",
"travel_time_min", "distance_m"} or {..., "note": "unroutable"/
"no_graph_nearby"/...}, ...], "requirements": [...], "overall_score",
"reason"}, ...], "honesty"}, ranked by overall_score (unmeasurable-only
candidates sort last, never dropped) then overlap_fraction, capped at
`limit` (1-10, default 5). division_id is a stable GERS id β chain a
result into admin_lookup or summarize_area for more detail without
re-running the search. No polygons in the response by default.
An empty "results" list is a valid answer (e.g. two anchors' sheds don't
overlap at all, or nothing in the reachable area is a neighborhood/
locality) with a "note" saying which. A per-anchor travel leg that can't
be routed (the polygon-approximated shed boundary occasionally includes
a point routing itself can't reach) gets "note" instead of a time,
without dropping the whole candidate.
confirm=true after the user agreed to wait for a first-time street-graph
build (about 5-25 seconds per anchor that needs one). Every anchor is
checked before any graph is built, so a fan-out never starts some
anchors and then stalls needing confirm on the next. Omit confirm
unless you just asked and they said yes.
Returns a structured {"error": "bad_request", ...} if anchors isn't 1-3
points, a point is missing/non-numeric lat, lon, or minutes, minutes is
not > 0, or a mode isn't walk/cycle/drive; likewise if requirements
isn't 1-8 non-empty strings. Propagates the same structured errors as
the underlying reach analysis (unsupported_mode, no_graph_nearby,
radius_too_large) and divisions_in_polygon/score_locality (upstream_unavailable,
schema_degraded) β a partial shortlist from a failed anchor or scan is
never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| anchors | Yes | ||
| confirm | No | ||
| requirements | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, non-destructive behavior. The description goes well beyond this by disclosing the street-graph build cost, the confirm flow, per-anchor graph checks before building, intersection behavior for multiple anchors, how unroutable legs return 'note' instead of failing, and the honesty field for unmeasurable requirements. It also clearly states it never returns partial shortlists on errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but exceptionally well organized into purpose, parameter semantics, method, return structure, edge cases, and error behavior. Each sentence adds necessary operational detail for a complex tool, with the core one-line purpose front-loaded so an agent can quickly route the call.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 0% schema description coverage and complex interaction between anchors, requirements, graph building, and scoring, the description covers everything an agent needs: defaults, output fields, ranking order, capping, empty-result behavior, per-leg routing failures, confirmation timing, and propagated errors. The presence of an output schema does not reduce the need for this behavior-level context, and the description provides it fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden for parameter meaning, and it succeeds. It specifies anchors as 1-3 objects with lat/lon plus optional mode and minutes, defaults for mode and minutes, requirements as 1-8 free-text strings, limit as 1-10 defaulting to 5, and confirm semantics. It even covers validation error conditions for each parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Where within reach: neighborhoods ranked by travel budget + amenities', naming a specific verb, resource, and output. It also explicitly contrasts itself: 'The inverse of every other area tool β instead of "describe this place", "find me a place"', which clearly distinguishes it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent when to use this tool versus general area tools and frames it as the opposite of describing an existing place. It also gives concrete call-level guidance, such as 'Omit confirm unless you just asked and they said yes', and explains when an empty result is still valid, so the agent can avoid false error handling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_areaSummarize areaARead-onlyIdempotent
Summarize what's in an area: total places and top categories.
Give the center as lat/lon, or as `where` β a {"lat", "lon"} dict, a
GERS id, or a free-text place name β but not both (and not neither);
either way returns {"error": "bad_request"} naming the choice. A
`where` given as an id/name adds a compact "resolved": {"name", "id",
"lat", "lon", "matched_by"} to the answer; absent for lat/lon or a
{lat,lon} where.
Returns a structured {"error": ...} instead of raising if upstream is
unavailable or the dataset is missing columns this tool depends on.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| where | No | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the annotations: invalid calls return a structured {'error': 'bad_request'} naming the problematic choice, a 'resolved' object appears conditionally, and upstream failures return errors instead of raising exceptions. These are non-obvious runtime behaviors that an agent cannot infer from readOnlyHint or idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured into purpose, input contract, and error behavior. Every sentence earns its place, and line breaks make the key constraints easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description covers the essential call contract, input constraints, and error behavior. The only clear gap is the undocumented radius_m parameter, which prevents full completeness for an agent needing to set a custom radius.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It usefully explains lat/lon versus where formats, the exclusivity constraint, and the 'resolved' object behavior. However, radius_m is never described, leaving its units and meaning ambiguous, so the compensation is incomplete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Summarize what's in an area: total places and top categories.' This clearly defines the tool's output and differentiates it from sibling tools like summarize_buildings, compare_areas, and land_use_at.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to choose this tool over its many siblings, such as whether to prefer summarize_area over summarize_buildings or compare_areas. The description only explains the lat/lon vs. where calling constraint, which is parameter-level guidance rather than tool-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_buildingsSummarize buildingsARead-onlyIdempotent
Summarize building footprints in an area: count, footprint area, height/floor coverage, mix.
From Overture's buildings theme (issue #23). Returns count,
total/mean footprint area in m^2, height_known_pct/num_floors_known_pct
(height and floor count are sparse in real Overture data β this reports
coverage rather than pretending every building has a value, with
mean_height_m/mean_num_floors alongside when any are known), and
top_subtypes/top_classes (top 10 each by count). Returns a structured
{"error": ...} if upstream is unavailable or the dataset is missing
geometry/bbox.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the read-only/idempotent annotations by explaining data sparsity behavior: it reports height_known_pct/num_floors_known_pct as coverage rather than assuming complete data, and includes mean values only when any are known. It also discloses error behavior (structured {"error": ...}) for upstream unavailability or missing geometry/bbox.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description opens with a one-sentence summary of purpose and metrics, then adds necessary detail about data provenance, coverage semantics, and error handling. Every sentence contributes new information and is clearly structured without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only summary tool with an output schema, the description covers data provenance, output metrics, sparse-data handling, and error responses. It does not explain input parameters or contrast with sibling tools, leaving some context incomplete, but the essential operational details are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero descriptions for lat, lon, and radius_m, and the description does not compensate by defining these parameters or their units. It only says 'in an area', which implies a spatial scope but does not specify the role of each parameter or the meaning of radius_m.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Summarize'), a specific resource ('building footprints in an area'), and the exact metrics returned (count, footprint area, height/floor coverage, mix). It clearly distinguishes this from sibling tools like `buildings_at` (likely raw building access) and `summarize_area` (broader area summaries) by narrowing to building footprints.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies its use case through the word 'Summarize' and building-specific focus, but it does not explicitly state when to choose this tool over siblings like `buildings_at` or `summarize_area`. No exclusions or alternatives are mentioned, so usage guidance is only implied, not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
travel_time_matrixTravel time matrixARead-onlyIdempotent
Routed travel time + distance between every origin and destination, by mode.
origins and destinations are each a list of LocationRefs β a {"lat":
..., "lon": ...} dict, a GERS id, or a free-text place name, mixed
freely β capped at 5 each (25 pairs max). Unlike distance_matrix's plain
haversine, this is a real shortest-path search over Overture's open
street graph β roads, one-ways, and each mode's own speed model, the
same cost model route() uses for a single pair, one mode per call;
omit mode to use the stored preferences mode, else walk.
An id/name that failed to resolve returns an indexed error
(origins[i]: ... or destinations[i]: ...) with candidates on ambiguity
β checked after the 5-point cap. Any origin/destination given by
id/name adds "resolved": {"origins": [{"index", "name", "id", "lat",
"lon", "matched_by"}, ...], "destinations": [...]} covering just those
entries; each side present only if it had a string entry, absent when
every point was already coordinates.
Reuses a single cached street graph across every origin and
destination when every origin-destination pair fits the mode's
straight-line cap and the whole point set fits one extraction circle,
running one Dijkstra per origin against every destination at once
rather than a search per pair β for a same-city matrix this costs
about what a single isochrone does, not one route() call per pair.
When the points are too spread out for one shared graph, falls back to
a route() call per pair (up to 25).
Returns {"mode", "elements": [{"origin_idx", "dest_idx", "duration_min",
"distance_m"}, ...], "durations_note"}, flat and origin-major like
distance_matrix. durations_note says these are speed-model estimates
over the open street graph, not live traffic. An unroutable pair (off
the street network, or on a disconnected fragment of it) gets
{"duration_min": null, "distance_m": null, "note": "unroutable"}
instead of failing the whole call; if every pair in the matrix is
unroutable the response also carries a top-level "note" saying so.
If the street graph hit its size cap the response carries "truncated":
true plus a note β capped extractions may present reachable pairs as
unroutable. Empty origins or destinations returns {"elements": []}.
Returns a structured {"error": "bad_request", ...} instead of raising
if either list exceeds 5 points, a point is missing/non-numeric lat or
lon, or mode isn't walk/cycle/drive. If no street graph exists
anywhere near every point in the matrix, returns {"error":
"no_graph_nearby"} β the same top-level failure route() and
optimize_route() give when nothing in the area is on the mapped
network, rather than a matrix of nulls.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Travel mode. Default: stored preference, else walk. | |
| origins | Yes | ||
| destinations | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only and idempotent, and the description adds substantial behavioral context: cached graph reuse, fallback to per-pair route() calls, unroutable pairs returning nulls, truncation caveats, no_graph_nearby failure, and error shapes. This far exceeds what annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense and well-organized, with the core purpose and key constraint front-loaded. Each paragraph covers a distinct topic β input format, resolution behavior, graph caching, output/error shape β with no filler or redundant restatement of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers limits, edge cases, output structure, performance characteristics, and failure modes, including unusual cases like all-unroutable matrices and truncated street graphs. Nothing needed for correct selection or invocation appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33%, but the description compensates fully: it explains LocationRefs forms (dict, GERS id, or free-text name), the 5-per-list cap, the mode enum with omitted-mode default, and how unresolved id/name entries behave. This adds meaning far beyond the sparse input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Routed travel time + distance between every origin and destination, by mode', giving a specific verb, resource, and scope. It then distinguishes itself from distance_matrix's plain haversine and aligns with route()'s cost model, making sibling differentiation clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly contrasts with distance_matrix ('Unlike distance_matrix's plain haversine, this is a real shortest-path search') and clarifies the mode behavior ('one mode per call; omit mode to use the stored preferences mode, else walk'). It does not fully spell out when to choose route() or distance_matrix instead, but the context strongly implies the boundaries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_claimsVerify listing claimsARead-onlyIdempotent
Grade spatial listing claims ("8 min to the metro", "shops on the doorstep", "green space nearby") against real routing and places data.
Free-text claim parsing needs an LLM β this tool takes already-decomposed
structured checks; the verify_listing_claims prompt teaches an agent how
to turn listing text into them. Each of claims (max 8; max 5 of kind
travel_time, since each costs a routed call) is one of:
- {"kind": "travel_time", "to_category": str|None, "to_name": str|None,
"mode": "walk"|"cycle"|"drive" (default walk), "claimed_minutes": number}
Finds the nearest place matching to_category (an Overture taxonomy
slug) and/or to_name (a substring match), then routes to it and
compares the routed minutes against claimed_minutes.
- {"kind": "count_nearby", "category": str|None, "name": str|None,
"radius_m": number (default 500, capped at 2000), "claimed_at_least": int}
Counts matching places within radius_m and compares against
claimed_at_least.
- {"kind": "distance", "to_category": str|None, "to_name": str|None,
"claimed_max_m": number}
Straight-line distance (haversine, not routed) to the nearest match,
compared against claimed_max_m.
Every kind needs at least one of its category/name fields; giving
neither is a bad_request. A category is an Overture taxonomy slug,
matched exactly (including its taxonomy descendants), never as a
substring β "park" does not match a parking garage; a name is a
substring match.
Verdict per claim: "confirmed" when the measured number is within the
claimed number x1.15 (count_nearby: measured count >= claimed),
"stretched" within x1.5 (count_nearby: count >= half the claim, floor
1), otherwise "false". A claim asserting a place exists at all, when
none is found within the search bound, is "false" with a note β
absence is a verdict, not an error. A claim the measurement cannot
decide is "unverifiable" instead of "false": a travel_time claim whose
place is found but cannot be routed to (no street graph nearby, or the
network doesn't connect the two points), or whose failing measurement
came from a size-cap-truncated street graph, and a count_nearby claim
whose claimed_at_least exceeds the row cap the count stopped at.
Returns {"results": [{"claim": <echo of the input>, "verdict":
"confirmed"|"stretched"|"false"|"unverifiable", "measured": {...
kind-appropriate minutes/count/distance_m, plus the matched place's id
and name when there is one}, "note": optional}, ...], "verdict_rule":
a one-line summary of the thresholds above}.
Returns a structured {"error": "bad_request", ...} for anything
malformed in claims (unknown/missing kind, more than 8 claims, more
than 5 travel_time claims, a missing or non-numeric claimed value,
neither target field given, or an unsupported mode), {"error":
"bad_request", ...} for invalid lat/lon, or a structured {"error": ...}
if the upstream dataset is unavailable or missing columns this tool
depends on.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| claims | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations by detailing exact verdict thresholds (x1.15, x1.5), the semantics of 'unverifiable' vs 'false', how absence is treated, routing failure caveats, size-cap truncation effects, and structured error cases. This gives an agent a precise model of tool behavior that annotations alone could not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is densely informative and well-structured with bullets, bolded claim kinds, and clearly separated error/output sections. Every sentence adds a necessary behavioral or semantic constraint; there is no filler or repetition of schema/annotation data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with three required parameters, no schema-level parameter descriptions, and many edge cases. The description covers input shape, claim constraints, matching semantics, verdict rules, output format, and all error classes. Given the complexity and the minimal schema, nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the claims parameter is just a generic object array, so the description carries the full burdenβand it delivers. It thoroughly documents the three claim kinds, all allowed fields, defaults, caps, matching rules, and required field combinations, adding enormous meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Grade spatial listing claims ... against real routing and places data.' It clearly distinguishes this tool from sibling analysis tools by specifying its exact jobβverifying structured spatial claimsβand even states that free-text parsing belongs to a separate prompt/process, not this tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says the tool consumes already-decomposed structured checks, not free text, and points to the verify_listing_claims prompt for the decomposition step. It also gives practical usage constraints such as max 8 claims and max 5 travel_time claims due to routing cost. It stops short of naming an alternative sibling tool, but the usage context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
warmup_cityGet to know my cityARead-onlyIdempotent
Pre-cache a city.
Copies places and transportation tiles into the same local cache later
queries read. Does not build the routing graph (the first route still
pays that cost) and does not pre-cache buildings. The warmup call is
the slow one; later place searches over the area read locally.
radius_m defaults to 8000 (a city core) and is capped at 25 km so a
warmup cannot fan into a planet-sized tile fetch.
confirm=true after the user agreed to wait for a first-time tile
warmup (about 5β25 seconds). Pass it only after a needs_confirm reply
and they said yes. An already-cached city never needs it.
Omit confirm unless you just asked and they said yes.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| city | No | ||
| confirm | No | ||
| radius_m | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations declare readOnly, idempotent, and non-destructive, the description goes well beyond them: it discloses the cache side effect, the slow first-call behavior, expected wait time, radius cap, and the confirm flow. No contradiction with annotations exists because the cache write is internal and idempotent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded: purpose first, then scope, then operational constraints. There is slight redundancy in the confirm instructions ('Omit confirm unless...' repeats the prior condition), but every other sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is comprehensive about cache behavior, routing limitations, and confirmation protocol. However, it omits the location parameter contract (city vs lat/lon, requiredness, precedence), which is a meaningful gap for a 5-parameter tool with no schema descriptions. The output schema mitigates the need to document return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description explains radius_m (default 8000, cap 25 km) and confirm (only after user agrees) well. However, it never explains lat/lon/city semantics, whether one is required, or how they interact, leaving key location inputs to inference from their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Pre-cache a city' and precisely states what is copied into cache (places and transportation tiles) and what is not (routing graph, buildings). This makes the tool's purpose unambiguous and clearly distinguishes it from query tools like find_places or route.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete usage context: call it before place searches so later queries read locally, and note that it will not speed up routing or building queries. It also says an already-cached city never needs another call. It does not explicitly name sibling tools as alternatives, but the guidance is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
water_nearWater near a pointARead-onlyIdempotent
Water near a point, nearest first: waterfront check, distance to river/canal/lake.
From Overture's base theme (issue #200), type=water β oceans, bays,
lakes, ponds, reservoirs, rivers, streams, canals, springs, pools.
Returns {"center", "radius_m", "in_range_count", "results": [{"name"
(when named), "subtype", "class", "distance_m", "is_salt"/
"is_intermittent" (only when true)}, ...]}, plus "truncated": true and
a "note" when more matched than were returned. No raw geometry.
distance_m is to the closest point on the feature, not its centroid β
a canal bank you are standing on reads ~0 m. Water gets dense (an
Amsterdam canal district puts hundreds of rows in a 500 m circle),
which is what in_range_count and the filters are for:
subtype/water_class match Overture's `subtype`/`class` columns
(case-insensitive substring; water_class is `class` under a
non-reserved name) β e.g. subtype="canal", subtype="river",
water_class="lake".
"on_water": true plus "water_body" means the point is *inside* a water
polygon β a lake, a reservoir, a river. For oceans and seas that is a
coarse signal: Overture cuts them into 1-degree tiles whose landward
edge covers dry coastal land, so a waterfront building reads as inside
the ocean. Those bodies are reported this way rather than as a bogus
0 m "nearest water" row, and no distance-to-coast is derived from them
(their tile boundaries include phantom cuts through open water), which
also means subtype="ocean" cannot return distance rows. Lakes and
rivers carry none of that: however large, they appear in results with
a real edge distance. The "note" says which case applies.
An empty results list is a valid answer: coverage is OSM-derived, and
"no water within 500 m" is a real finding about an arid or unmapped
place. radius_m echoes the effective radius (large values are
clamped). Returns a structured {"error": ...} if upstream is
unavailable or the dataset is missing geometry/bbox, and {"error":
"bad_request"} for a bad coordinate.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | ||
| lon | Yes | ||
| limit | No | ||
| subtype | No | ||
| radius_m | No | ||
| water_class | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only and idempotent, but the description adds substantial behavior beyond them: distance is to the closest point rather than centroid, no raw geometry is returned, ocean tiles cause phantom land overlap, radius is clamped, and error response shapes are detailed. It also explains the dense-water scenario and in_range_count purpose. No annotation contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and each subsequent paragraph adds important caveats (distance semantics, ocean artifacts, empty-result validity, error behavior). It is dense and somewhat monolithic, and could be improved with bullet points or section breaks, but no sentence is pure filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex filtering/query tool, the description is nearly exhaustive: it covers output shape, distance semantics, water classes, ocean edge cases, truncation, clamping, error handling, and data-coverage caveats. The presence of an output schema reduces the need to enumerate return fields, and the description still adds the semantic details needed to interpret them correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates well for most parameters: radius_m (clamping, effective radius), subtype (case-insensitive substring, examples, ocean restriction), water_class (maps to class), and coordinates (bad_request error). It does not explicitly explain the 'limit' parameter as the maximum result count, only implying it through 'truncated': true and the results array.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence, 'Water near a point, nearest first,' names a specific resource (water bodies) and behavior (distance-ordered), and the phrase 'waterfront check, distance to river/canal/lake' scopes it. It is clearly distinguishable from sibling tools by focusing exclusively on water features and explicitly disclaiming raw geometry.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear use context: waterfront checks, distance queries to specific water subtypes, and how to filter with subtype/water_class. It also states a when-not ('subtype="ocean" cannot return distance rows') and notes that empty results are a valid answer. However, it never names alternative sibling tools, so an agent must infer which other tool to choose when water info is not the goal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
within_distanceCheck within distanceARead-onlyIdempotent
Is the nearest place matching category/name within max_distance_m of (lat, lon)?
Give the center as lat/lon, or as `where` β a {"lat", "lon"} dict, a
GERS id, or a free-text place name β but not both (and not neither);
either way returns {"error": "bad_request"} naming the choice. A
`where` given as an id/name adds a compact "resolved": {"name", "id",
"lat", "lon", "matched_by"} to the answer; absent for lat/lon or a
{lat,lon} where.
max_distance_m is required and must be a positive number of meters β a
zero, negative, non-finite, or missing value returns {"error":
"bad_request"} rather than silently searching a 0m (or omitted from a
call entirely, in which case the schema itself rejects it before this
tool ever runs) window and answering a confident-looking "false".
Returns {"within": bool, "nearest": {...place row with id...} | None,
"distance_m": float | None}. nearest is None if nothing matches within
a search window capped at max_distance_m * 2 β a real match further out
than that isn't found (documented, not a bug: keeps the search bounded).
name is a literal substring match only β no alt-spelling or typo
fallback applies here, so a misspelled name is an honest "no match",
never a silent yes about a different name.
Returns a structured {"error": ...} if upstream is unavailable or the
dataset is missing columns this tool depends on.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| name | No | ||
| where | No | ||
| category | No | ||
| max_distance_m | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly documents the error contract: bad_request for ambiguous center choices and for invalid max_distance_m, plus upstream/dataset failure errors. The detailed note about not silently returning a confident-looking 'false' for a zero or missing distance is especially valuable, and the conditional 'resolved' behavior is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into clear blocks: center choice, distance validation, and return value/errors. Every sentence adds operational value; the zero-distance parenthetical is slightly long but earns its place by preventing a subtle misuse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter tool with no schema-level descriptions, this covers input alternatives, validation, return shape, and error outcomes exceptionally well. The output schema supplies remaining return details, but a bit more clarity on category/name matching semantics would make it fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does well by explaining max_distance_m requirements, the three `where` forms, the exclusivity of lat/lon vs `where`, and the conditional `resolved` field. Minor gaps remain: it does not fully define how category/name matching behaves or explicitly require lat and lon as a pair.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening question defines a precise boolean check: whether the nearest place matching category/name is within max_distance_m of a center. It distinguishes this from sibling list/detail tools by its predicate and matching criteria, though it never explicitly names a sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly frames the tool as a proximity test and fully specifies acceptable center inputs, so an agent can infer when it applies. It does not mention alternative tools or provide explicit when-not-to-use guidance, which keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Several tools overlap or are explicit aliases: find_near is a thin alias of find_places, from_to is a legacy alias of route, resolve_place_batch is actually a batch of place_details rather than resolve_place, and geocode/resolve_place, reverse_geocode/address_at, and admin_lookup/reverse_geocode share overlapping outputs. However, the descriptions are unusually detailed and cross-reference canonical forms, so an agent reading them can usually pick correctly.
Most names are descriptive lowercase snake_case and there are coherent families (_at suffix, geocode*, *_matrix, summarize_*), but the set mixes verb_noun (find_places, summarize_area), noun_at (buildings_at, land_use_at), single nouns (isochrone, route, preferences), and awkward aliases (from_to, find_near). No case mixing, but the overall pattern is not uniform.
42 tools is a heavy surface for any MCP server. The broad domain justifies much of the count, but several tools are aliases or convenience composites that could be consolidated (find_near, from_to, within_distance, ground_location), and there are multiple geocoding/resolution variants plus batch versions. Agents face a large, navigationally dense tool list.
The server covers an unusually complete geospatial surface: place search/details, forward/reverse geocoding with batches, routing, matrices, isochrones, multi-stop optimization, meeting points, corridor search, area summaries/comparisons/verdicts, changes over time, building/land/water/infrastructure themes, geometry ops, map rendering, elevation, and system tools. Minor gaps include no arbitrary-GeoJSON-polygon place search, no division-boundary retrieval, and no direct address-to-place lookup, but these are workaroundable or consistent with the 'answers, not data' design.
Maintenance
Related MCP Connectors
The Google Maps MCP server is a fully-managed server provided by the Maps Grounding Lite API that connects AI applications to Google Maps Platform services. It provides three main tools for building LLM applications: searching for places, looking up weather information, and computing routes with details like distance and travel time. The server acts as a proxy that translates Google Maps data into a format that AI applications can understand, enabling agents to accurately answer real-world location and travel queries.
MCP server for Japan geodata: cadastral lot numbers (chiban) and reverse geocoding, for AI agents.
Ask in plain English, get a rendered, shareable map from live public data. 24 geospatial tools.
Capability registry for the agentic economy. Semantic search over verified MCP server listings.
Related MCP Servers
- AlicenseBqualityDmaintenanceA comprehensive MCP server providing 30 tools for geocoding, routing, and OpenStreetMap data analysis. It enables AI assistants to search for locations, calculate travel routes, and perform quality assurance checks on map data.304625MIT
- AlicenseAqualityCmaintenanceAn MCP server providing geocoding and place discovery services via Nominatim and OpenStreetMap. It enables users to perform forward and reverse geocoding, extract bounding boxes, and find nearby places or administrative hierarchies.10Apache 2.0
- AlicenseAqualityDmaintenanceAn MCP server that provides AI agents with geospatial analytics by querying Overture Maps data directly from S3, enabling place analytics, building composition, land use classification, and transportation analysis.134MIT
- AlicenseNot gradedqualityCmaintenanceFree geospatial MCP server for AI agents, providing geocoding, reverse geocoding, POI search, and route planning using OpenStreetMap data via Nominatim, Overpass, and OSRM.1GPL 3.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/chuofringer/placeroot'
If you have feedback or need assistance with the MCP directory API, please join our Discord server