MapMap
Server Details
Maps built for agents: routing incl. truck/ADR, geocoding, matrices, isochrones — 34 tools.
- Status
- Healthy
- Uptime
- 99.9% over 41 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 49 tools
Most tool families are distinct (geo_* local math, style tools, async job lane), but the routing/ordering cluster overlaps heavily: route, plan_day, order_stops, plan_errands, optimise_routes, and replan_routes all produce ordered stop sequences and differ mainly by nuance (hard arrival time, single run, fleet VRP). Similarly cheapest_fuel_along_route / cheapest_charging_along_route overlap with search_along_route's category browse and plan_ev_route. The unusually rich descriptions mitigate this, but an agent can still plausibly misselect among them.
All 49 names are lowercase snake_case with coherent prefix families (geo_, get_, set_, list_, plan_, check_, submit_, cheapest_) and consistent British spelling (optimise_routes, submit_optimise_job). Minor deviation is that several tools are bare nouns/verbs (route, cluster, matrix, elevation, geocode) rather than the dominant verb_noun pattern, but no convention is actually mixed.
49 tools is well past the 25-tool heavy threshold, landing just under the extreme-mismatch band. The platform's domain (routing, geocoding, VRP, styles, traffic, EV/fuel, geometry, verification) is genuinely broad and most tools earn their place, but the sheer surface imposes real selection cost on an agent.
Coverage is exceptionally deep: full routing/geocoding/matrix/isochrone/VRP lifecycle, sync plus async lanes, job polling, traffic reporting, EV/fuel planning, geometry utilities, and verification. The only visible gaps are in style management (no delete_style, no list_styles) and job control (no cancel), which are minor and workable around.
Available Tools
49 toolscamera_incidentsAInspect
Road incidents a TRAFFIC CAMERA SAW and a vision model CONFIRMED, in force now: near a point (near [lat, lon] with radius_m, default 1000, at most 10000), in a bbox [min_lon, min_lat, max_lon, max_lat], or along a route shape (polyline6 from route, corridor buffer_m default 60). Give exactly one. Each record says what it asserts (closed or a speed_override in km/h) on which OSM ways and carriageway, what was seen (collision, stalled vehicle, wrong-way vehicle), the camera, the clip URL the verdict was made on (evidence_url), the verifier and its confidence, and when it lifts (end, always within minutes: these records expire on their own). Camera records RANK BELOW official closures and never retract one. READ coverage_note ALOUD: an empty list means no camera-verified incident here, NEVER a clear road. Show attribution verbatim (Powered by TfL Open Data). Off unless the deployment arms camera incidents (SN_CAMERA_INCIDENTS_ENABLED): an unarmed gateway answers 501 and says so. Requires the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| bbox | No | `[min_lon, min_lat, max_lon, max_lat]`. | |
| near | No | `[lat, lon]` plus `radius_m` (default 1000). | |
| shape | No | A route shape as polyline6; the corridor rule of `/v1/incidents/along` applies (`buffer_m` default 60). | |
| buffer_m | No | Corridor half-width for `shape`, metres. | |
| radius_m | No | Radius for `near`, metres, at most 10000. | |
| min_confidence | No | Drop records below this confidence (default 0). | |
| include_recently_expired | No | Include records that have expired in the last hour, for the operator's timeline (default false). |
Output Schema
| Name | Required | Description |
|---|---|---|
| incidents | Yes | Records in force (and recently expired, if asked). |
| attribution | Yes | Attribution lines required by the camera providers, verbatim. |
| coverage_note | Yes | Plain-language statement of which cameras are covered and that camera records rank below official closures. Agents must read it aloud: an empty list means "no camera-verified incident", never "road clear". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full behavioral burden and does so: records self-expire 'within minutes', they rank below official closures and never retract one, the tool is feature-gated (SN_CAMERA_INCIDENTS_ENABLED, 501 when unarmed), and it requires GATEWAY_URL + GATEWAY_API_KEY. This is unusually rich disclosure for a read 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?
It is front-loaded with the core claim and every sentence carries information, but the single dense run-on paragraph mixes filter mechanics, record contents, caveats, and gating, making it harder to scan than a short structured form.
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 gated, credential-requiring tool this covers what an agent needs: how to scope the query, what each record asserts and includes, expiry behavior, the coverage_note caveat, and attribution requirements. An output schema exists, yet the description still usefully summarizes record contents.
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 100%, so the baseline is 3. The description restates the near/radius_m and shape/buffer_m defaults that the schema already documents and omits min_confidence and include_recently_expired entirely, adding little semantic value beyond the structured fields.
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 clause names the specific resource and its provenance (road incidents a traffic camera saw and a vision model confirmed, in force now), and the 'rank below official closures' line implicitly separates it from sibling closure/observation tools. An agent can tell what this returns without opening 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?
It gives an explicit selection rule for the spatial inputs ('Give exactly one' of near/bbox/shape) with defaults, warns that an empty list never means a clear road, and states the deployment gating ('Off unless the deployment arms camera incidents... an unarmed gateway answers 501'). Conditions for use and non-use are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cheapest_charging_along_routeAInspect
Find the best EV charge points along a route, with the REAL extra travel time of stopping at each one — never a straight-line guess. Provide origin + destination (a route is computed) or an existing route's geometry_polyline6, plus optional connectors ("ccs", "type2", "chademo", "type1", "tesla", "domestic", "other"), min_kw (e.g. 50 for rapid only), available_only and max_detour_minutes (default 10). Charge points come from operator-published feeds, are costed through the routing engine with your costing (a truck profile makes detours respect dimensional/ADR restrictions) and ranked most powerful first, since minutes off the clock are bought with kilowatts. Each result carries max_power_kw, connector_standards, best_connector, evse_count, detour_minutes/detour_km and, where a live feed backs it, available_now. IMPORTANT: there is no national charge-point registry — every deployment covers only the operators it has onboarded, so ALWAYS show the returned coverage_note alongside the results. An empty results means "none from these operators within the detour budget", NEVER "there are no chargers here". Statuses are live only when availability_live is true; otherwise they are the values captured at the last ingest and must not be described as current. say is ALWAYS present and is the whole answer as one short spoken line, composed by the gateway with the coverage already inside the claim rather than appended to it: it scopes its superlative to the operators this deployment holds, and an empty result's line says the emptiness is about those operators. Prefer reading it verbatim to writing your own summary. Requires the MapMap gateway; answers a clear error when the deployment has no charge-point dataset. Display the returned charging_attribution with the results.
| Name | Required | Description | Default |
|---|---|---|---|
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; the detours then respect dimensional/ADR restrictions. | |
| min_kw | No | Keep only charge points whose best connector is rated at least this many kW (e.g. 50 for rapid charging only). | |
| origin | No | Route origin (with `destination`, when no geometry is given). | |
| costing | No | Costing model for the route and detour matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| connectors | No | Keep only charge points offering at least one of these connector standards: "type2", "type1", "ccs", "chademo", "tesla", "domestic" or "other". Omitted ⇒ every standard. | |
| destination | No | Route destination. | |
| max_results | No | Maximum results (default 5, at most 25). | |
| available_only | No | Keep only charge points with a bay reported free right now. Needs the deployment to have a live availability feed; without one the call is refused rather than silently returning nothing. | |
| geometry_polyline6 | No | An existing route geometry as an encoded polyline6 (the `route` tool's `geometry_polyline6`). Provide either this or `origin` + `destination`, not both. | |
| max_detour_minutes | No | Largest acceptable detour in minutes (default 10, at most 120). |
Output Schema
| Name | Required | Description |
|---|---|---|
| say | Yes | **Always present.** The whole answer as one short spoken line, composed by the gateway. Coverage is inside the claim rather than appended to it: the line scopes its superlative to the operators this deployment holds, and an empty result's line says the emptiness is about those operators, never about the road. Safe to read to a driver verbatim. |
| note | No | Why `results` is empty, when it is — the cause, not a bare list. |
| costing | Yes | The costing the detours were computed with. |
| results | Yes | Charge points within the detour budget, most powerful first (power, then detour). |
| sources | Yes | Every operator in the dataset, with its own coverage note and licence. Present even when `results` is empty. |
| candidate_cap | Yes | The matrix fan-out cap in force. |
| coverage_note | Yes | **Always present.** What this deployment's charge-point dataset does and does not cover. An empty `results` means "none from these operators within the budget" — never "there are no chargers here". Show this to the user alongside the results. |
| route_length_m | Yes | Length of the route geometry in metres. |
| route_distance_m | No | Direct origin→destination distance in metres. |
| route_duration_s | No | Direct origin→destination travel time in seconds (same estimator as the detour legs), when routable. |
| availability_live | Yes | Whether statuses are live (a bring-your-own availability feed) or the values captured at the last ingest. |
| availability_note | Yes | Plain-language explanation of what the statuses mean here. |
| candidates_costed | Yes | Candidates actually costed through the engine (fan-out capped at `candidate_cap`, most powerful kept). |
| max_detour_minutes | Yes | The detour budget applied, minutes. |
| charging_attribution | No | Attribution string for the charge-point operators actually returned — display it with the results (a licence obligation). |
| candidates_considered | Yes | Charge points matching the filters that passed the corridor pre-filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: data comes from operator-published feeds, costing respects the selected profile (truck dimensions/ADR), results are ranked by power, empty results mean 'none from these operators' not 'no chargers', statuses are live only when availability_live is true, and the `say` field is the authoritative answer. It also covers error behavior for missing datasets and mandates displaying attribution. This is exemplary transparency beyond the schema.
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 operational significance. It front-loads the key differentiator (real detour time) and the coverage caveat early. It is dense but well-organized, avoiding fluff; the length is justified by the tool's complexity and 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?
Despite having an output schema, the description explains the interpretation of results (coverage_note, empty results meaning, live vs ingested statuses, say field composition) and error handling. It covers all parameters and their interdependencies, making it complete for an agent to call correctly without additional context.
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 100%, so baseline is 3. The description adds meaning: it explains connectors list, gives a min_kw example, clarifies that available_only requires a live feed, and explains how truck costing affects detours. It also ties parameters to output semantics (e.g., detour_minutes/detour_km). This adds value beyond the schema without redundancy.
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 verb ('Find') and resource ('EV charge points along a route') and highlights the distinctive real detour-time calculation versus straight-line guesses. It is clearly distinguished from siblings like cheapest_fuel_along_route (fuel vs EV) and search_along_route (generic search vs costed charging).
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 explicit input modes (origin+destination or geometry_polyline6, not both), conditions for available_only (requires live feed, otherwise refused), and the important caveat about operator coverage and the coverage_note. It does not explicitly name alternatives or when-not-to-use, but the context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cheapest_fuel_along_routeAInspect
Find the cheapest fuel along a route, with the REAL extra travel time of stopping at each station — never a straight-line guess. Provide origin + destination (a route is computed) or an existing route's geometry_polyline6, plus a fuel code ("diesel" default, "petrol_95", "petrol_98", "premium_diesel", "e85", "lpg") and max_detour_minutes (default 10). Stations come from the live open-data price feeds (UK CMA retailer scheme and/or the statutory Fuel Finder, FR prix-carburants, DE Tankerkoenig; the response's fuel_attribution names the ones actually matched), are priced through the routing engine with your costing (a truck profile makes detours respect dimensional/ADR restrictions) and ranked freshest-priced first and cheapest within that. Each result carries price {value, currency, updated_at, stale}, detour_minutes/detour_km, and saving_per_litre vs the cheapest on-route baseline (pass fill_litres to also get saving_total). stale = not verifiably fresher than 24 h: true unless BOTH the price's own updated_at and the snapshot's fetch time are inside that window, and true whenever either is missing. A stale price is ranked below every fresh one, is never the baseline, and carries NO saving_per_litre — quote it as "last seen at X on ", never as a saving. say is ALWAYS present and is the whole answer as one short spoken line, composed by the gateway with the number, the detour and the honest qualifier already in it. Prefer reading it verbatim to writing your own summary: a stale price's line states the figure and the day it was last seen and claims no saving, and an empty result's line names the cause rather than implying there is no fuel on that road. Requires the MapMap gateway; answers a clear error when the deployment has no fuel-price dataset. Display the returned fuel_attribution with the prices.
| Name | Required | Description | Default |
|---|---|---|---|
| fuel | No | Which fuel to price: "diesel" (default), "petrol_95", "petrol_98", "premium_diesel", "e85" or "lpg" (aliases "petrol", "unleaded", "e10", "super_unleaded", "e5", "b7" and "sdv" are accepted). | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; the detours then respect dimensional/ADR restrictions. | |
| origin | No | Route origin (with `destination`, when no geometry is given). | |
| costing | No | Costing model for the route and detour matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| destination | No | Route destination. | |
| fill_litres | No | Optional fill size in litres; each result then also carries `saving_total` = `saving_per_litre` × `fill_litres`. | |
| max_results | No | Maximum results (default 5, at most 25). | |
| geometry_polyline6 | No | An existing route geometry as an encoded polyline6 (the `route` tool's `geometry_polyline6`). Provide either this or `origin` + `destination`, not both. | |
| max_detour_minutes | No | Largest acceptable detour in minutes (default 10, at most 120). |
Output Schema
| Name | Required | Description |
|---|---|---|
| say | Yes | **Always present.** The whole answer as one short spoken line, composed by the gateway: the number, the detour, and the honest qualifier where one applies. Safe to read to a driver verbatim, and safe on an empty result, where it names the cause rather than implying there is no fuel on the road. A stale price's line states the figure and the day it was last seen and claims no saving. |
| fuel | Yes | The normalised fuel code that was priced (e.g. "diesel"). |
| costing | Yes | The costing the detours were priced with. |
| results | Yes | Stations within the detour budget, cheapest first (price, then detour). |
| baseline | Yes | The cheapest effectively-on-route option per currency (empty when no station sits on the route itself). |
| candidate_cap | Yes | The matrix fan-out cap in force. |
| route_length_m | Yes | Length of the route geometry in metres. |
| fuel_attribution | No | Attribution string for the fuel-price data sources actually returned — display it with the prices (a licence obligation). |
| route_distance_m | No | Direct origin→destination distance in metres. |
| route_duration_s | No | Direct origin→destination travel time in seconds (same estimator as the detour legs), when routable. |
| candidates_costed | Yes | Candidates actually priced through the engine (fan-out capped at `candidate_cap`, cheapest kept). |
| max_detour_minutes | Yes | The detour budget applied, minutes. |
| candidates_considered | Yes | Stations selling the fuel that passed the corridor pre-filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does an excellent job. It discloses live data sources, the definition of 'stale' with exact conditions, ranking rules, the behavior of stale prices (never baseline, no saving), and the instruction to quote them honestly. It also explains the 'say' field's composition and the error case for missing datasets. This is exceptional transparency.
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 contributes. It is well-structured with the purpose first, then input modes, data sources, output details, stale-price handling, and the 'say' field guidance. It is not overly verbose given the complexity, though it could be tightened slightly without losing essential information.
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 9 parameters, 100% schema coverage, and presence of an output schema, the description is remarkably complete. It covers all input modes, fuel types, costing models, the stale-price logic, the 'say' field composition, attribution display, and error conditions. Nothing essential 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?
The schema already describes all parameters (100% coverage), so baseline is 3. The description adds meaning beyond that: it explains the mutual exclusivity of origin/destination vs geometry_polyline6, the effect of fill_litres on saving_total, the truck profile's impact on detour restrictions, and the aliases for fuel codes. This is valuable added 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 states a specific verb ('Find the cheapest fuel'), a clear resource (fuel along a route), and distinguishes itself from the sibling 'cheapest_charging_along_route' by focusing on fuel types. It also contrasts with generic search tools by emphasizing real detour times and price freshness. The scope is unambiguous.
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 input modes (origin/destination or geometry_polyline6), defaults for fuel and max_detour_minutes, and explains the 'say' field should be read verbatim. It does not explicitly name alternative tools, but the usage context is clear. It also mentions the MapMap gateway requirement and error behavior, which helps the agent decide when to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_adr_tunnelAInspect
Check whether a vehicle may pass through a tunnel of a given ADR category ("A"–"E"). Provide hazmat and, when known, the load's ADR 8.6.4 tunnel restriction code (e.g. "B", "C5000D", "B/D", "none"). Applies the conservative worst-case reading: conditional clauses are assumed to apply, so a blocked answer may over-restrict but never under-restricts. No network access; answers instantly.
| Name | Required | Description | Default |
|---|---|---|---|
| hazmat | Yes | Whether the vehicle carries dangerous goods at all. When false the ADR tunnel matrix does not apply and every tunnel is permitted. | |
| tunnel_code | No | ADR 8.6.4 tunnel restriction code of the load, e.g. "B", "C5000D", "B/D", or "(—)"/"none". Leave unset for a hazmat load of unknown code (conservatively treated as code B). | |
| tunnel_category | Yes | ADR category of the tunnel to check: "A", "B", "C", "D" or "E". |
Output Schema
| Name | Required | Description |
|---|---|---|
| reason | No | Why passage is forbidden (present only when blocked); cites the ADR 8.6.4 rule that applied. |
| decision | Yes | Whether passage is allowed or blocked. |
| explanation | Yes | Human-readable explanation of how the decision was reached, including the conservative worst-case reading. |
| forbidden_tunnel_categories | Yes | ADR tunnel categories this load is forbidden from under the worst-case reading (conditional clauses assumed to apply). Empty when unrestricted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden and succeeds: it states the conservative worst-case reading ('a blocked answer may over-restrict but never under-restricts') and operational traits ('No network access; answers instantly'). This is exactly the kind of behavioral context agents need beyond the schema.
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?
Three sentences, purpose front-loaded in the first ('Check whether a vehicle may pass through a tunnel...'), with every sentence earning its place. No fluff; the behavioral caveat and operational notes are tightly packed in the final 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?
The description covers purpose, parameter usage, interpretation semantics, and operational behavior, while the output schema covers return values and the input schema covers all parameters. Slightly more could be said about edge-case handling (e.g., unrecognized tunnel codes), but nothing essential to selecting or invoking 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 description coverage is 100%, so the schema already documents all three parameters; baseline is 3. The description adds marginal value by reinforcing which parameters to supply and giving code examples ('B', 'C5000D', 'B/D', 'none'), though these overlap with the schema's own examples.
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: 'Check whether a vehicle may pass through a tunnel of a given ADR category ("A"–"E")'. The ADR tunnel category scope clearly differentiates it from geo siblings like check_clearance_on_route, which concerns route clearance rather than hazmat tunnel restrictions.
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 (determining hazmat tunnel passage) and instructs what to provide ('Provide hazmat and, when known, the load's ADR 8.6.4 tunnel restriction code'), but it never explicitly contrasts with alternatives such as check_clearance_on_route or states when not to use it. Usage context is present but left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_clearance_on_routeAInspect
Measure a vehicle's overhead clearance along a route against surveyed point cloud geometry, wherever survey coverage exists. Routes with truck costing (so the search already avoids the height restrictions the map has tagged), then measures that corridor. Give origin, destination and height_m; optional width_m asks the corridor-width axis too, and optional margin_m adds your operating margin to the vehicle before the verdict. Returns pass, fail, indeterminate or no_verdict with the limiting point, the measured headroom, its uncertainty bound (safe_headroom_m, sigma_m, sampling_gap_m) and a link to that exact view in the survey viewer. An indeterminate carries indeterminate_reasons as codes to branch on and the same reasons as English inside explanation; read out the English. A pass may carry no limiting point at all, which means the survey found nothing above that corridor, and the width axis may answer not_assessed where the corridor edges are too sparsely surveyed while the height axis still answers. Honesty, and it matters here: this measures physical geometry from a dated survey. It is not a signed or posted height, clearance_enforcement.route_certified is always false, and the caveat is on every answer including the clear one. Ground the survey did not cover comes back as not_surveyed_m and is never judged, so a pass is possible over complete coverage and nowhere else; sparse or stale coverage comes back separately as insufficient_data_m. Reach for this when a truck route came back unchanged and you need to know whether that means anything: an unchanged route avoids what the map records, which is a different claim from measured headroom, because a structure nobody tagged is routed through like open road. Needs the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY), which holds the surveys; there is no fallback, and it will not answer from the routing step alone. The mapmap://guide/clearance resource sets out what each answer proves.
| Name | Required | Description | Default |
|---|---|---|---|
| origin | Yes | Route origin. | |
| width_m | No | Vehicle width in metres. Supplying it asks the width axis as well as the height axis; the width answer is reported separately and is never a headroom. | |
| height_m | Yes | Vehicle height in metres. Required: there is no default vehicle, because a default vehicle is how somebody gets an answer about a lorry that is not theirs. | |
| margin_m | No | Operating margin in metres, added to the height before the verdict is decided (default 0). Your compliance policy, not ours: the measured figure and the safe bound are both reported whatever you set here, and the margin is echoed back. It is applied to the measurement, not to the routing step, where the map's own posted heights already carry a margin of their own. | |
| destination | Yes | Route destination. |
Output Schema
| Name | Required | Description |
|---|---|---|
| basis | Yes | Always `"surveyed_geometry_not_signage"`. |
| width | Yes | The width axis, answered separately when `width_m` was given. |
| verdict | Yes | `pass`, `fail`, `indeterminate` or `no_verdict` for the height axis. A `pass` is possible over completely surveyed ground and nowhere else: unsurveyed ground yields `no_verdict`, never a pass. |
| datasets | Yes | The surveys drawn on, with their capture dates and staleness. |
| limiting | No | The limiting point on a `fail`, the tightest point on a `pass`, the worst contested point on an `indeterminate`. Absent on a `no_verdict`, and absent on a `pass` where the survey found nothing at all above the corridor. |
| view_url | No | Deep link to that exact view in the survey viewer, so the reading can be looked at rather than taken on trust. |
| advisories | Yes | Notes on stretches of the route: vegetation age, a reading limited by a wire, a seam between surveys. |
| assessed_m | Yes | Metres of route measured against survey data good enough to decide on. |
| explanation | Yes | What was measured, when, with what bound, and what the tool declined to conclude. It may over-restrict; it never under-restricts. |
| not_surveyed_m | Yes | Metres of route no survey covers. This is the absence of a measurement, and it is never the same statement as a measured open sky. No verdict is drawn over it. |
| resolution_hint | No | What would resolve an `indeterminate`, in one sentence, as the measuring service phrased it. |
| route_distance_m | Yes | Length of the route the vehicle was routed over, metres. |
| route_duration_s | Yes | Estimated driving time for that route, seconds. |
| geometry_polyline6 | Yes | The route as a six-digit-precision encoded polyline, so the same shape can be drawn or re-measured without routing again. |
| insufficient_data_m | Yes | Metres of route a survey covers but too sparsely, or too stale, to decide on. Also an absence, and reported apart from `not_surveyed_m` because the two have different remedies. |
| clearance_enforcement | Yes | What this answer does and does not prove. Read it. |
| indeterminate_reasons | Yes | Why an `indeterminate` could not be called, as machine-readable codes (`inside_uncertainty_band`, `vegetation_age_exceeded`, `artefact_stale`, `artefact_freshness_unchecked`). Empty on every other verdict. These are for branching on, not for reading out: the same reasons appear as English in `explanation`, and a person shown `artefact_freshness_unchecked` has been failed by whatever displayed it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full disclosure burden and succeeds. It reveals return verdicts, honesty caveats, that clearance_enforcement.route_certified is always false, that unsurveyed ground returns not_surveyed_m and is never judged, and that the MapMap gateway and API key are required with no fallback. This is extensive behavioral transparency beyond the schema.
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 the tool is complex and the length is mostly justified by caveats, return semantics, and infrastructure requirements. It is front-loaded with the core purpose, though a few phrases are slightly convoluted or repetitive, such as the explanation about the route step and gateway requirements.
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 and the presence of an output schema, the description covers all necessary operational context: when to use it, what parameters mean, what each answer type implies, survey coverage limitations, and authentication/gateway requirements. Nothing an agent needs to call this correctly appears 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 100%, so the baseline is 3, but the description adds meaningful semantics: it explains that width_m only triggers a separate width-axis check, that height_m is required because there is no default vehicle, and that margin_m is added to the measurement before the verdict, not to the routing step. This materially improves parameter understanding.
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: measuring overhead clearance along a route against surveyed point cloud geometry. It distinguishes itself from routing and map-tagged height tools by framing the output as physical measured headroom, not posted height, and by contrasting with the routing step and other 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?
It explicitly says 'Reach for this when a truck route came back unchanged' and explains the difference between route-level avoidance and measured headroom. It also states the tool cannot answer from the routing step alone and that there is no fallback, providing clear usage context, though it does not name many alternative sibling tools explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_style_contrastAInspect
Audit a map style's colour contrast against WCAG 2.1 (4.5:1 for label text, 3:1 for graphics like the route line), across both the light and dark palette variants. Pass a hosted style_id OR an inline theme document (as accepted by create_style). Advisory: failing pairs list the palette slots to adjust with set_palette; publishing is never blocked on contrast.
| Name | Required | Description | Default |
|---|---|---|---|
| theme | No | …or an inline theme document (as accepted by `create_style`). Exactly one of `style_id`/`theme` must be given. | |
| style_id | No | Hosted style id whose latest theme should be checked… |
Output Schema
| Name | Required | Description |
|---|---|---|
| passes | Yes | True when every audited pair meets its WCAG threshold. |
| findings | Yes | Every audited pair, failing pairs first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the two palette variants checked, the exact thresholds, that failing pairs list slots to adjust, and that contrast never blocks publishing. It does not explicitly state it is read-only, but 'Audit' and 'Advisory' imply no mutation.
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?
Three front-loaded sentences carry purpose, input, thresholds, and advisory behavior with no filler. Every 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 tool has only two parameters, an output schema exists, and the description supplies thresholds, input alternatives, palette variants, and follow-up guidance via set_palette. Nothing needed to invoke it 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 100% and the schema already documents the exactly-one-of style_id/theme rule and theme format. The description adds only a concise restatement and a pointer to create_style, which is useful but not a major increment over 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?
The description opens with a specific verb ('Audit'), a precise resource ('a map style's colour contrast'), and an explicit standard (WCAG 2.1 thresholds for label text and graphics). This clearly distinguishes it from sibling tools like check_adr_tunnel or set_palette.
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 a clear invocation condition ('Pass a hosted style_id OR an inline theme document') and directs failed pairs to set_palette. It lacks an explicit 'when not to use' contrast, but the advisory note that publishing is never blocked on contrast conveys the appropriate context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clusterAInspect
Group stops into balanced geographic clusters, so a day too large for one optimisation can be optimised one cluster at a time. This is the front half of the recipe for a thousand-stop day: cluster here, then call optimise_routes per cluster, where the routing engine's own matrix decides the visiting order. IMPORTANT — this is STRAIGHT-LINE clustering. Distances are measured between coordinates, not along the road network: no road, river, motorway junction or one-way system is consulted, and two stops either side of an estuary look adjacent. That makes it the right tool for deciding which stops belong TOGETHER and the wrong one for deciding what ORDER to visit them in. The answer carries a basis sentence saying exactly this; show it, so a centroid is never read as a plan. Provide locations ([{id, lat, lon, load?}], ids unique, at most 5,000) and EXACTLY ONE of clusters (how many groups, balanced by stop count), max_cluster_locations or max_cluster_load (a per-cluster ceiling the count is derived from). Optional territories keep a cluster from straddling a round: each is clustered on its own, and so are the stops inside none of them. Optional seed (default 42) drives the seeding — the same request with the same seed always returns the same clusters, on every deployment, so a re-run is a re-run. Returns each cluster's member ids, count, summed load, centroid and territory, plus a balance block naming the constraint applied and whether it had to be relaxed to place every stop: a load ceiling with lumpy loads is a bin-packing problem and may have no solution at the derived count. Requires the MapMap gateway.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | Seed for the k-means++ seeding (default 42). The same request with the same seed always returns the same clusters, on every deployment. | |
| clusters | No | How many clusters to produce, balanced by stop count. Give exactly one of `clusters`, `max_cluster_locations` or `max_cluster_load`. | |
| locations | Yes | The stops to group. Ids must be unique; at most 5,000. | |
| territories | No | Optional territories. Given, no cluster straddles one: each territory is clustered on its own, and so are the stops inside none of them. | |
| max_cluster_load | No | At most this much summed `load` per cluster; the cluster count is derived from it. A load ceiling with lumpy loads is a bin-packing problem and may have no solution at the derived count — the response says so rather than pretending. | |
| max_cluster_locations | No | At most this many stops per cluster; the cluster count is derived from it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| basis | Yes | The method statement: this is STRAIGHT-LINE clustering. Distances are between coordinates, not along roads — two stops either side of an estuary look adjacent. Show it. It is the sentence that stops a centroid being read as a plan. |
| balance | Yes | The constraint applied, the largest cluster produced, and whether the ceiling had to be relaxed to place every stop. |
| clusters | Yes | The clusters: each with its `id`, member `locations` (your ids), `count`, summed `load`, `centroid` and the `territory` it belongs to. |
| parameters | Yes | The seed, the cluster count, the locations seen, how many territories were used, the iterations run and whether it converged. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers richly. It discloses the key behavioral trait: 'STRAIGHT-LINE clustering' with no road, river, or one-way system consulted, including the estuary example. It also discloses determinism across deployments, the bin-packing relaxation behavior, the `basis` output caveat, and the MapMap gateway requirement.
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 the description is long, every sentence earns its place: purpose, recipe, critical caveat, parameter rules, determinism promise, balance-block explanation, and gateway dependency. It is front-loaded with the use case and the key straight-line warning, and uses bold markers to guide attention. There is no filler or 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?
The description is complete for a 6-parameter tool with an output schema. It covers the recipe's place in the workflow, the clustering distance model, the exact-one parameter selection, determinism, how territories interact, the bin-packing relaxation possibility, and the required gateway. Since an output schema exists, the description's brief summary of the response shape is adequate.
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 100%, so the baseline is 3 and the schema already documents every parameter thoroughly. The description adds emphasis (e.g., 'EXACTLY ONE of') and restates the derived-count logic, but it does not add materially new meaning beyond the schema's own parameter descriptions. A score of 3 reflects that the schema does the heavy lifting.
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 names a specific verb and resource: 'Group stops into balanced geographic clusters,' and immediately explains the purpose with the one-cluster-at-a-time use case. It distinguishes itself from siblings by explicitly saying it is the 'front half of the recipe' and the 'right tool for deciding which stops belong TOGETHER and the wrong one for deciding what ORDER to visit them in,' contrasting with optimise_routes and order_stops.
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?
Usage is fully explicit: use cluster when a day is 'too large for one optimisation,' then 'call `optimise_routes` per cluster.' It gives an exclusion rule — straight-line clustering makes it wrong for ordering — and names the specific alternative to use for order. It also states the exact-one-of constraint among `clusters`, `max_cluster_locations`, and `max_cluster_load`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_styleAInspect
Create a hosted map style. Provide a name, optionally a named base to start from (light, dark, streets, midnight, navigator-day, navigator-night, fleet, outdoor, dataviz, backdrop, print - call list_style_layers for what each one is for), and optionally a theme document ({base: "light"|"dark", palette: {slot: colour}, layers: {layer_id: overrides}}). The named base is laid down first and the theme document is merged over it, so "streets with darker water" is one call; with neither, the style starts from the default theme. A theme may also set worldview (ISO 3166-1 alpha-2, accepted: AE, KR, SA, US) to display that jurisdiction's official names for a small curated registry of renamed features; omitted, labels keep the OSM on-the-ground names. Returns the generated style_id (pass it to set_palette / set_layer_paint) and the compiled style URL for MapLibre.
| Name | Required | Description | Default |
|---|---|---|---|
| base | No | Optional named base to start from, e.g. "streets", "midnight", "navigator-night", "fleet". Call `list_style_layers` for the catalogue, including which bases expect an overlay of their own. The base's whole document is laid down first and `theme` is merged over it, so a base plus two palette entries is a complete style. Omitted, the style starts from the default light theme as it always did. | |
| name | Yes | Human-readable style name; its kebab-case slug seeds the style id. | |
| theme | No | Optional theme document (palette/layer overrides). Merged over `base` when one is given; on its own, it replaces the default theme outright. |
Output Schema
| Name | Required | Description |
|---|---|---|
| theme | Yes | The theme document that was stored. |
| version | Yes | The published version (always 1 on create). |
| style_id | Yes | The generated style id — pass it to `set_palette`, `set_layer_paint` and `get_style`. |
| style_url | Yes | Immutable URL of the compiled style at this version. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full behavioral burden. It discloses the merge order (base first, theme merged over it), the default behavior when neither is provided, the special worldview behavior with accepted values and fallback behavior, and the return contract. This is rich, accurate behavioral context beyond the schema.
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: creation intent, parameter choices, merge behavior, worldview behavior, and return value. It is front-loaded with the core purpose and organized so the reader learns the default case before the 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?
For a tool with three parameters, no annotations, and a nontrivial merge model, the description is complete. It explains how base, theme, and defaults interact, names the downstream tools for the returned style_id, and specifies the compiled style URL. 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?
The schema already provides 100% coverage for parameter names, but the description adds significant extra meaning: the exact list of base values, the theme document structure with base/palette/layers, the merge semantics, and the worldview field with allowed country codes. This materially helps an agent construct valid arguments.
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: 'Create a hosted map style.' It distinguishes itself from sibling tools like get_style, set_palette, set_layer_paint, and list_style_layers by focusing on creation and by stating the generated style_id is meant for the set_* tools. No ambiguity remains about what this tool does.
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 create_style: to lay down a base, merge a theme, or start from the default theme. It also routes the agent to list_style_layers for base details and to set_palette/set_layer_paint for follow-up modifications. It does not explicitly state when not to use create_style versus get_style, but the creation-oriented guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
elevationAInspect
Sample terrain elevation. Provide points (a bare list of coordinates) for point elevation, or encoded_polyline (optionally with resample_distance_m) for an along-route profile — not both. Returns one sample per point/resampled point in order; elevation_m is null wherever the engine's DEM tile set has no coverage at that point (never a guess). The encoded_polyline form also returns each sample's resampled lat/lon and cumulative range_km from the start.
| Name | Required | Description | Default |
|---|---|---|---|
| points | No | Points to sample. Provide this or `encoded_polyline`, not both. | |
| encoded_polyline | No | A route as a Google encoded polyline with six digits of precision. Provide this or `points`, not both. | |
| resample_distance_m | No | Resamples `encoded_polyline` at this spacing in metres before sampling height (ignored for `points`). |
Output Schema
| Name | Required | Description |
|---|---|---|
| samples | Yes | One sample per input point (or per resampled shape point, in the `encoded_polyline` form), in order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does this thoroughly: it states that elevation_m is null where DEM coverage is missing and 'never a guess', and it discloses that the encoded_polyline form returns resampled lat/lon and cumulative range_km. This goes well beyond a basic 'returns elevation' statement and gives the agent confidence about edge 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 compact and front-loaded: the core purpose is in the first sentence, and the key constraint ('not both') appears early. Every sentence earns its place, covering purpose, input modes, return behavior, and edge cases without redundancy. It is appropriately sized for a tool with three parameters and a rich output schema.
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 (two mutually exclusive input modes, optional resampling, null-coverage behavior) and the presence of a rich output schema, the description covers everything an agent needs to invoke it correctly. It explains the trade-off between the two modes, the resampling parameter's scope, and the null semantics. The output schema handles return-value details, so the description doesn't need to repeat them.
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 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema: it explains the mutual exclusivity of points and encoded_polyline, clarifies that resample_distance_m is ignored for points, and describes the return behavior (one sample per point, null for missing coverage). It doesn't add much about the LatLon format, but the schema already covers that thoroughly. The extra behavioral context justifies a 4.
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 ('Sample terrain elevation') and immediately distinguishes the two input modes (points vs encoded_polyline). It clearly states what the tool does and how it differs from the many sibling tools, which are mostly routing/geospatial operations rather than elevation sampling.
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 'not both' for the two mutually exclusive input modes, and explains when to use each: point elevation vs along-route profile. It also clarifies that resample_distance_m applies only to encoded_polyline and is ignored for points. This is direct, actionable guidance with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_areaAInspect
Area in square metres enclosed by a ring of 3+ coordinates, computed geodesically. Always positive: the answer does not depend on whether the ring is wound clockwise or anticlockwise. Intended for zones and boundaries, not for polygons covering more than half the globe. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | The coordinates to consider. |
Output Schema
| Name | Required | Description |
|---|---|---|
| area_sq_m | Yes | Enclosed area in square metres, always positive regardless of winding order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses that the result is always positive regardless of winding order, that computation is geodesic, and that it is local with no quota. It does not mention edge cases like degenerate rings or the exact return format, but the output schema likely covers the return value. The description adds meaningful behavioral context beyond the schema.
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 four sentences, each earning its place: what it computes, the winding-order invariance, the intended scope, and the local-computation note. It is front-loaded with the core purpose and avoids redundancy with the schema.
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 single-parameter tool with a rich schema and an output schema, the description is nearly complete. It covers the main behavioral traits and usage constraints. The only minor gap is not stating what happens with fewer than 3 points or degenerate rings, but the description already says '3+ coordinates' and the schema requires an array, so this is adequately implied.
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 100%, so the schema already documents the 'points' parameter and the LatLon format. The description adds the key semantic constraint that the ring must have 3+ coordinates and that the area is computed geodesically, which is not fully explicit in the schema. This compensates for the schema's generic 'coordinates to consider' phrasing.
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 ('Area in square metres enclosed by a ring of 3+ coordinates') and a clear resource, distinguishing it from sibling geo tools like geo_distance, geo_length, and geo_centroid. It also clarifies the geodesic computation and the intended use case, so an agent can tell it apart from other geometry tools without opening 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 explicitly says when to use it ('Intended for zones and boundaries') and when not to ('not for polygons covering more than half the globe'). It also notes the local computation ('no network call, no quota'), which helps an agent choose it over network-dependent alternatives. This is clear usage guidance with exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_bboxAInspect
The axis-aligned bounding box enclosing 1+ coordinates, as {min_lat, min_lon, max_lat, max_lon}. Useful for fitting a map view to a set of stops. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | The coordinates to consider. |
Output Schema
| Name | Required | Description |
|---|---|---|
| max_lat | Yes | Maximum latitude (north edge). |
| max_lon | Yes | Maximum longitude (east edge). |
| min_lat | Yes | Minimum latitude (south edge). |
| min_lon | Yes | Minimum longitude (west edge). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral disclosure burden. It covers the computed result, the axis-aligned nature, and the important side-effect signals: no network call and no quota. It does not discuss edge cases like invalid coordinates or wrapping behavior, but the schema already constrains coordinate ranges.
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 sentences with no filler: the first explains the behavior and output format, the second gives a practical use case and cost/performance note. The most important semantic information is 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?
For a simple one-parameter computation with a rich input schema and an output schema present, the description covers what the tool does, the returned fields, a typical use case, and the local/no-quota behavior. Nothing essential 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 100%, so the schema already documents the points parameter and LatLon formats thoroughly. The description adds minimal parameter-level nuance beyond '1+ coordinates' and the output field names, which does not substantially exceed the baseline.
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 operation ('axis-aligned bounding box enclosing 1+ coordinates') and gives the exact output shape {min_lat, min_lon, max_lat, max_lon}. This clearly distinguishes it from sibling geo tools like geo_centroid, geo_area, or geo_distance.
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 a concrete use case ('fitting a map view to a set of stops') and adds that it is a local computation with no network call and no quota. It does not explicitly name sibling alternatives or exclusions, but the stated context is clear enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_bearingAInspect
Initial bearing from one coordinate to another, in degrees clockwise from true north (0-360). This is the bearing at the START of the geodesic; over long distances the bearing changes en route. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End coordinate. | |
| from | Yes | Start coordinate. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bearing_deg | Yes | Initial bearing from `from` to `to`, degrees clockwise from true north, normalised to 0–360. Note this is the bearing at the start of the geodesic: over long distances the bearing changes en route. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses three important traits: the result is the initial bearing (not final), the bearing changes en route for long distances, and the operation is local with no network or quota implications. It does not describe error behavior or what happens with invalid coordinates, but for a pure geometry calculation this is a minor gap. 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?
Two sentences with zero filler. The first sentence states the result and unit; the second adds the geodesic nuance and the local-computation performance trait. Each sentence earns its place, and the most important information is 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 a simple geometry computation with a rich input schema and an output schema. The description covers the essential behavioral context (initial bearing, change along the geodesic, local computation) and does not need to explain return values because an output schema exists. An agent reading this description has everything necessary to invoke the tool correctly and interpret the result in context.
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 100%. The 'from' and 'to' parameters are clearly named and described as 'Start coordinate' and 'End coordinate,' and the shared LatLon definition explains both object and array forms, including the 'longitude FIRST' order. The tool description itself adds no parameter-level semantics, so it neither improves nor harms the schema's already sufficient documentation. The baseline 3 applies.
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 names a highly specific operation and output: 'Initial bearing from one coordinate to another, in degrees clockwise from true north (0-360).' It also clarifies the geodesic context ('bearing at the START of the geodesic'), which distinguishes this from an average or final bearing. None of the sibling tools compute bearing, so there is no ambiguity.
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 contextual guidance: the bearing is the initial one and changes over long distances, implying that for navigation along a route one should not assume a constant bearing. It also notes 'Local computation: no network call, no quota,' which helps an agent decide when a cheap local calculation suffices. However, it does not explicitly name alternative tools (e.g., geo_destination or geo_distance) or state exclusion conditions, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_centroidAInspect
The centroid (geometric mean position) of 1+ coordinates, e.g. to pick a depot location or centre a map. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | The coordinates to consider. |
Output Schema
| Name | Required | Description |
|---|---|---|
| point | Yes | The computed coordinate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden, and it does well by explicitly stating 'Local computation: no network call, no quota.' This clarifies that the operation is synchronous, offline, and quota-free, which is valuable for an agent deciding whether to invoke it.
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 two short, information-dense sentences. The definition is front-loaded, followed by practical examples and a key behavioral note, with no filler or repetition of schema 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?
For a simple one-parameter computation tool with a rich schema and an output schema present, the description covers the essential context: what it computes, when to use it, and its local non-quota behavior. No critical information for invoking it 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?
The schema already documents the points array and the LatLon format with 100% coverage, so a baseline of 3 applies. The description adds meaning by specifying '1+ coordinates', clarifying the minimum input count that the schema does not enforce, and by explaining the geometric meaning of the result.
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: it computes the centroid (geometric mean position) of coordinates. The examples 'pick a depot location or centre a map' make the function’s intent immediately clear and help distinguish it from sibling geo tools like geo_distance or geo_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 description gives concrete use cases ('pick a depot location or centre a map'), making its intended application clear. It does not explicitly name alternative tools or when not to use it, but the purpose is specific enough that an agent can select it confidently.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocodeAInspect
Turn a place (address, POI, town) into coordinates. Ask two ways, and they combine: query is free text — one run-together string, the way a person types into a search box — and street, housenumber, city, postcode and country name the parts of an address separately. At least one of the two is required. Pass the parts whenever you already hold the address in parts (a form, a CRM row, a manifest): components are REQUIREMENTS, not hints, so city: "London" means a result outside London cannot come back at all, where "London" inside query only reorders. country takes an ISO 3166-1 alpha-2 code or a country name ("GB", "United Kingdom"); a value naming no country is refused rather than silently matching nothing. Returns up to limit (default 10) candidates with name, one-line label, lat/lon, type and address parts. Pass focus {lat, lon} to rank results near a location higher. A bare city or town name (no comma) lists that city's airports and main railway stations directly behind it, ahead of namesakes elsewhere. Each hit also carries match: a per-component matched/inferred/unmatched verdict, the score_gap to the runner-up, and which backend answered. READ IT before acting on an address — an unmatched or inferred postcode on the top hit means the answer does not carry the address you asked for, and a small score_gap means the ranking barely chose, so show the alternatives instead of picking one. Use verify_places when the address came from a model or a user and needs checking rather than using. Results are matched in lang (default "en"), so English exonyms — "Munich", "Cologne", "Geneva" — resolve to the place meant; pass lang when querying in another language, or "default" for each place's local name.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | Structured component: town or city, e.g. "London". Matches the containing city as well as the immediate locality, so a suburb name works here too. | |
| lang | No | Language of the place names to match and return, as a two-letter code. Defaults to "en", which is what makes English exonyms ("Munich", "Cologne", "Geneva") resolve to the place meant rather than a same-named town elsewhere. Set it to the language your query is written in; "default" asks for each place's own local name. Deployments support a fixed set (this one: "en", "de", "fr"), and anything outside it is refused. | |
| focus | No | Optional location bias: results near this point rank higher. | |
| limit | No | Maximum number of results (1–50, default 10). | |
| query | No | Free-text place query, e.g. "Dover ferry terminal". Required unless at least one structured component is supplied. | |
| street | No | Structured component: street name, e.g. "Downing Street". Matches the street of addresses and POIs (transliterated street names included) as well as the street itself. | |
| country | No | Structured component: ISO 3166-1 alpha-2 code or country name — "GB", "gb", "United Kingdom" and "UK" all mean the same country. A value naming no country is refused rather than quietly applied as a filter that matches nothing. | |
| postcode | No | Structured component: postcode in any spacing or case — "SW1A 2AA" and "sw1a2aa" are one query. A bare UK outward code ("SW1A") selects the whole district. | |
| housenumber | No | Structured component: house number, e.g. "10" or "221B". Only meaningful alongside `street` — a house number on its own excludes nearly everything and identifies nothing. |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes | Matching places, best first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so richly: components are REQUIREMENTS not hints, an unknown `country` is refused rather than silently matching nothing, `lang` outside the supported set is refused, and unmatched/inferred `match` verdicts plus small `score_gap` signal unreliable answers. This is far beyond what the schema states.
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?
Dense and largely front-loaded — the core action and the two input modes come first, then behavioral caveats. It runs long, with the `lang`/exonym material at the end feeling somewhat expendable, but nearly every sentence carries operational information.
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, zero-required tool with an output schema, this covers the gaps well: mutual requirement of query/components, return count and fields, ranking bias, and how to interpret `match`/`score_gap`. An agent could invoke and correctly act on results 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 100%, so the baseline is 3, but the description adds real meaning the schema lacks: the requirement-vs-hint distinction between structured components and `query`, the 'at least one of the two is required' rule, and the ranking effect of `focus`. It stops short of fully decoupling from the schema's own parameter text.
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+resource: 'Turn a place (address, POI, town) into coordinates.' It implicitly distinguishes itself from reverse_geocode (coordinates→place) by naming the inverse direction, and from siblings like nearby_places/places_in_view by framing itself as the forward geocoder.
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?
Explicit routing to the alternative: 'Use `verify_places` when the address came from a model or a user and needs checking rather than using.' It also gives a concrete selection rule for the two input modes: 'Pass the parts whenever you already hold the address in parts (a form, a CRM row, a manifest).'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_destinationAInspect
The coordinate reached by travelling distance_m metres from from on bearing_deg (degrees clockwise from true north). The inverse of geo_distance + geo_bearing. Local computation: no network call.
| Name | Required | Description | Default |
|---|---|---|---|
| from | Yes | Starting coordinate. | |
| distance_m | Yes | Distance to travel in metres. | |
| bearing_deg | Yes | Bearing in degrees clockwise from true north. |
Output Schema
| Name | Required | Description |
|---|---|---|
| point | Yes | The computed coordinate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full behavioral disclosure. It clearly states this is a local computation with no network callchers, and it explains the calculation semantics with exact units and reference directions. It could add edge-case behavior (e.g., poles, antimeridian) but is transparent about the core side-effect-free nature.
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 dense sentences with no filler. The core result is front-loaded first, then the inverse relationship and local-computation note follow logically.
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 simple geometric computation with an output schema presentlor, the description covers the essential selection and side-effect context: what it computes, how it relates to sibling tools, and that it is local. The lack of geodetic model details is a minor gap given the inverse-relationship hint.
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 100%, so the schema already documents each parameter thoroughly. The description adds contextual meaning about the inverse relation and gives units, but these mostly mirror the schema definitions rather than adding substantial new 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?
Description states a precise calculation: the coordinate reached after travelling a distance from a point on a given bearing. It names the inverse relationship to geo_distance and geo_bearing, which clearly distinguishes it from those 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 phrase 'The inverse of geo_distance + geo_bearing' tells an agent when this tool is conceptually appropriate, and 'Local computation: no network call' gives a clear practical context for preferring it for offline or quick calculations. It does not explicitly state when not to use it, but the inverse framing is sufficient for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_distanceAInspect
Distance in metres between two coordinates. Computed geodesically on the WGS84 ellipsoid, so it is the straight-line (as-the-crow-flies) distance, NOT a driving distance — use route or matrix for travel distance and time. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | End coordinate. | |
| from | Yes | Start coordinate. |
Output Schema
| Name | Required | Description |
|---|---|---|
| distance_m | Yes | Distance in metres along the WGS84 ellipsoid. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It goes beyond a plain function summary by stating that it computes on the WGS84 ellipsoid, is a local computation, makes no network call, and consumes no quota. This gives the agent trustworthy operational expectations.
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 three sentences with no filler. The core result and unit are front-loaded, the critical distinction from driving distance follows immediately, and the local-computation note is valuable behavioral context rather than 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?
The description is complete for a two-parameter computational tool: it explains the algorithm, the unit, the coordinate system, the limitation, and the alternatives. The input schema is detailed, and an output schema exists, so return-value details are not required in the description.
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 100%, and the schema already defines the two coordinate formats, including the GeoJSON [lon, lat] ordering. The description adds only the unit ('metres') and the general notion of 'two coordinates', which is minimally additive. The baseline of 3 is appropriate because the schema does the heavy lifting.
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: 'Distance in metres between two coordinates' and clearly identifies the computation as geodesic straight-line distance. It also distinguishes itself from route/matrix by explicitly stating what it is NOT, which differentiates it from the many geo_* siblings.
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 tells the agent when not to use this tool ('NOT a driving distance') and names the alternatives ('use `route` or `matrix` for travel distance and time'). It also adds a practical usage signal by noting that computation is local, with no network call or quota.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_lengthAInspect
Total length in metres of a polyline through 2+ coordinates, summed geodesically. This measures the line you supply, NOT a driven route — use route for that. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | The coordinates to consider. |
Output Schema
| Name | Required | Description |
|---|---|---|
| length_m | Yes | Total geodesic length in metres. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral disclosure burden. It adds useful context: geodesic summation, local computation with no network call or quota, and the explicit non-route scope. It does not discuss error handling or precision limits, but for a read-only measurement tool these are minor.
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?
Three sentences, each with distinct value: purpose, route exclusion, and computational behavior. The main purpose is front-loaded and there is 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?
With only one parameter, a detailed schema, and an output schema, the description covers the essential decision factors: what it measures, the geodesic method, the route distinction, and resource impact. Nothing an agent needs to invoke it 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 100% and the LatLon definition thoroughly documents both coordinate formats and longitude-first ordering. The description adds the important 2+ minimum for the points array, something the schema does not enforce, and clarifies the line/order semantics through 'polyline'.
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?
Clearly states it computes the total geodesic length in metres of a supplied polyline of 2+ coordinates. The explicit 'NOT a driven route' and pointer to `route` distinguishes it from the routing sibling, and the polyline framing separates it from point-to-point distance 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?
Explicitly tells the agent to use `route` when a driven route is needed rather than the supplied line, giving a concrete when-not and alternative. The phrase 'the line you supply' implies the intended use case (measuring arbitrary geometry) and the local-computation note reinforces when it is safe to call without quota concerns.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_nearest_point_on_lineAInspect
The closest position on a polyline to a given coordinate, plus the geodesic distance to it in metres. The answer may lie between vertices, not only on them. Useful for 'how far is this address from the route?'. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | The polyline's coordinates, 2 or more. | |
| point | Yes | The coordinate to measure from. |
Output Schema
| Name | Required | Description |
|---|---|---|
| point | Yes | The closest position on the line, which may lie between vertices. |
| distance_m | Yes | Geodesic distance from the input point to that position, metres. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and handles it well: it discloses local computation, no network/quota, geodesic distance, and interpolation between vertices. It implies a read-only calculation without side effects, though it does not explicitly state that or describe edge-case 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?
Four sentences, each earning its place: result, interpolation caveat, use case, and execution traits. The most important information is front-loaded and there is no redundant boilerplate.
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 local calculation with a rich input schema and an output schema present, the description gives all needed call-time context: result meaning, units, interpolation behavior, and cost model. Nothing critical for invoking 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 description coverage is 100%, so the baseline is 3; the description adds no parameter-level syntax beyond the schema. It correctly maps the two inputs to 'coordinate' and 'polyline', but the schema already documents the {lat, lon} object vs [lon, lat] array distinction and the 2+ vertex requirement.
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: it returns the closest point on a polyline to a coordinate plus the geodesic distance in metres. It clearly distinguishes itself from generic geo_distance/geo_length by noting the answer may lie between vertices, and the use case 'how far is this address from the route?' reinforces its identity.
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 provides an explicit use case and a practical execution trait: local computation with no network call and no quota. It does not name sibling alternatives or state when not to use it, but the context is clear enough to guide an agent toward this tool over generic distance or geometry helpers.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_point_in_polygonAInspect
Whether a coordinate lies inside a polygon: delivery zones, catchments, congestion or clean-air zones, site boundaries. Provide point {lat, lon} and polygon as 3+ {lat, lon} coordinates of the outer ring (closed automatically if the last does not repeat the first). Points exactly on the boundary count as OUTSIDE. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| point | Yes | The coordinate to test. | |
| polygon | Yes | The polygon's outer ring, 3 or more coordinates. Closed automatically if the last point does not repeat the first. |
Output Schema
| Name | Required | Description |
|---|---|---|
| inside | Yes | True when the point is strictly inside the ring. Points exactly on the boundary are **not** counted as inside. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the boundary-counts-as-outside behavior, automatic polygon closing, and local computation with no network call or quota. These are meaningful behavioral traits beyond what the schema shows. It doesn't mention performance limits or error cases, but for a pure geometry predicate the disclosed traits are the important ones.
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?
Three sentences, each earning its place: the first states purpose and use cases, the second specifies inputs and the boundary rule, the third adds the local-computation trait. No filler, no repetition of schema 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?
For a two-parameter geometry predicate with a rich schema and an output schema present, the description covers the essential behavioral context: boundary handling, polygon closing, and local execution. It doesn't describe the output format, but the output schema exists, so that's not required. A small gap is not mentioning what happens with invalid polygons (e.g., self-intersection), but that's minor.
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 100%, so the schema already documents both parameters thoroughly, including the GeoJSON [lon, lat] array alternative. The description adds the '3+ coordinates' requirement and the auto-closing behavior, which are useful, but most parameter meaning is already in the schema. Baseline 3 is appropriate.
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: 'Whether a coordinate lies inside a polygon', then lists concrete use cases (delivery zones, catchments, congestion/clean-air zones, site boundaries). This clearly distinguishes it from sibling geo tools like geo_distance, geo_centroid, or geo_area, which answer different spatial questions.
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 states the exact inputs needed ('Provide point {lat, lon} and polygon as 3+ {lat, lon} coordinates') and clarifies the boundary rule ('Points exactly on the boundary count as OUTSIDE'). It doesn't explicitly name sibling alternatives or say when not to use it, but the use-case list and local-computation note give enough context for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geo_simplifyAInspect
Reduce the number of coordinates in a polyline while keeping its shape (Douglas-Peucker). tolerance_deg is in DEGREES, not metres: about 0.0001 drops detail finer than roughly 10 m at the equator. Endpoints are always kept. Returns the retained points and how many were removed. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | The polyline's coordinates, 2 or more. | |
| tolerance_deg | Yes | Douglas-Peucker tolerance in **degrees**, not metres. Around 0.0001 drops detail finer than roughly 10 m at the equator. |
Output Schema
| Name | Required | Description |
|---|---|---|
| points | Yes | The retained coordinates, endpoints always preserved. |
| removed | Yes | How many coordinates were removed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses unit semantics (degrees not metres), an approximate conversion to metres, endpoint preservation, return contents, and the fact that computation is local with no network call or quota. This is unusually thorough and lets an agent predict side effects and cost.
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?
Three tight sentences carry the essential information: purpose, unit warning, endpoint behavior, returns, and local computation. The most critical caveat (degrees not metres) is front-loaded, and every sentence earns its place without redundant prose.
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 tool with an output schema, the description covers all agent-critical aspects: purpose, input units with magnitude intuition, endpoint guarantee, return shape, and execution characteristics. An agent has everything needed to invoke it correctly; any remaining details, such as coordinate format variants, are already fully handled by the rich input 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?
The input schema already describes both parameters with 100% coverage, so the baseline is 3. The description adds genuine value beyond the schema by quantifying the tolerance in real-world terms ('0.0001 drops detail finer than roughly 10 m at the equator') and by clarifying that endpoints are always kept, which affects how the points parameter is interpreted.
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 ('Reduce the number of coordinates') and a concrete resource ('a polyline') while naming the algorithm (Douglas-Peucker). This clearly distinguishes it from sibling geo tools like geo_length or geo_area, which perform different operations on geometries.
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: this tool is for reducing coordinate density while preserving shape. It implies when to use it, though it does not explicitly name alternatives or state when not to use it. For a tool with a specialized geographic purpose, that context is sufficient for an agent to choose it over siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_jobAInspect
Read an asynchronous job submitted with submit_optimise_job: its status, and once it has finished, its result inline — exactly the body the synchronous tool would have returned. Status is queued, running, succeeded or failed; the answer's terminal field says whether the job will ever leave the status it is in, so poll while that is false. POLLING IS FREE: the gateway meters the submission and not the reads, deliberately, because a poll that costs quota is a poll a caller rations, and a rationed poll is how a job that finished in ten seconds gets noticed four minutes later. Check every few seconds rather than guessing at a duration. units_charged is what the SUBMISSION drew, and refunded says whether a failure handed it back — a failed job shows both, because reporting zero would be a lie about what was charged. Webhooks are the alternative to polling and exist for humans wiring infrastructure, not for agents in a loop. A job belongs to the key that submitted it (or another key of the same identity); anyone else's id answers NOT FOUND rather than forbidden, because confirming an id exists is itself a disclosure. Requires the MapMap gateway.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The job id returned by `submit_optimise_job`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The job id. |
| kind | Yes | `optimise`, `replan` or `matrix`. |
| error | No | Why it failed, once `status` is `failed`. |
| result | No | The answer, inline, once `status` is `succeeded` — exactly the body the synchronous tool would have returned. A matrix job answers `durations_s` and `distances_m`, as the `matrix` tool does; it also still carries the same numbers as `durations` and `distances`, which are DEPRECATED and will be removed in a future release. |
| status | Yes | `queued`, `running`, `succeeded` or `failed`. Only `succeeded` and `failed` are terminal; keep polling on the other two. |
| refunded | Yes | Whether a failure refunded the submission's units. |
| terminal | Yes | Whether `status` is one this job will never leave. |
| created_at | Yes | RFC 3339 UTC submission time. |
| started_at | No | RFC 3339 UTC time a worker picked it up. |
| finished_at | No | RFC 3339 UTC time it finished, either way. |
| units_charged | Yes | Metered units the SUBMISSION drew. This is what was charged; `refunded` says whether it came back. |
| webhook_status | No | `delivered` or `delivery_failed`, once a webhook was attempted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries full responsibility and satisfies it thoroughly. It discloses status values, the terminal flag semantics, metering/refund behavior, the NOT FOUND rather than forbidden privacy behavior, and the gateway requirement.
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 average but every sentence contributes behavioral or operational context. The rationale-laden sections on free polling and refund reporting are slightly verbose, but they are purposeful and help an agent trust the behavior rather than ration calls.
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 single-parameter read tool with an output schema available, the description covers everything an agent needs: how to obtain the id, what statuses exist, how to know when to stop polling, cost implications, and auth/privacy edge cases. No critical gap remains.
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 100% for the id parameter, so the baseline is 3. The description adds meaningful semantics beyond the schema: the id must come from submit_optimise_job and belongs to the submitting key, with a privacy-motivated NOT FOUND response for foreign ids.
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 names a specific verb (read), a resource (asynchronous job from submit_optimise_job), and the exact payload (status, result inline, body the synchronous tool would return). This clearly distinguishes it from submission and other 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?
It tells the agent exactly when to call this tool (after submitting a job, while polling), how often to poll (every few seconds), and what to check (the terminal field). It also explicitly dismisses webhooks as unsuitable for agent loops, giving clear when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_styleAInspect
Fetch a hosted style's latest theme document (the editable source) and the URL of its latest compiled MapLibre style. Use the theme to inspect current palette and layer overrides before editing.
| Name | Required | Description | Default |
|---|---|---|---|
| style_id | Yes | Hosted style id, e.g. "midnight-fleet-a1b2c3". |
Output Schema
| Name | Required | Description |
|---|---|---|
| theme | Yes | The latest theme document — the editable source the next version is published from. |
| style_id | Yes | Hosted style id. |
| style_url | Yes | URL of the latest compiled MapLibre style (point MapLibre GL at it). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. It does convey read-only intent through 'Fetch' and 'inspect before editing,' and it usefully distinguishes the editable theme document from the compiled style. However, it does not explicitly state side-effect-free behavior, permission requirements, or error handling, leaving some transparency gaps.
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 sentences with no filler: the main fetch action is front-loaded, and the second sentence adds practical guidance. Every word 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?
For a single-required-parameter read operation with an output schema present, the description is largely self-sufficient. It explains the two outputs and the intended editing context, though it could name related sibling tools or explicitly confirm the operation is non-mutating.
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 100%, including an explicit example for style_id. The description adds only a mild hosted-style framing and does not meaningfully enhance understanding beyond 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?
The description uses a specific verb ('Fetch') and names precise resources: the latest theme document and the URL of the compiled MapLibre style. It also ties the tool to an inspection-before-editing workflow, which clearly differentiates it from editing-focused siblings like set_palette and set_layer_paint.
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 usage context: use the theme to inspect current palette and layer overrides before editing. It does not explicitly name alternatives or state when not to use the tool, but the intended workflow is evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_usageAInspect
Check what your own API key has spent, so you can decide mid-task whether to keep going. Reading it is free: it costs no quota. Optional from and to (YYYY-MM-DD UTC, inclusive, at most 92 days apart) bound the report; omitted, it covers the current month to date. Returns days (per-day, per-endpoint), totals per endpoint over the range, total_units, plus month_used_units against monthly_quota_units and the prepaid balance_millipence (thousandths of a penny). Everything is counted in UNITS — weighted quota units, where a heavier endpoint costs more than one unit per request — so never report these figures as a number of calls. When identity_pooled is true the quota is shared with the other keys belonging to the same owner, so these figures are not yours alone. The key that authenticates the call is the key reported on: there is no way to read another caller's usage. Needs the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Last day to report, `YYYY-MM-DD` (UTC) inclusive. Defaults to today. | |
| from | No | First day to report, `YYYY-MM-DD` (UTC) inclusive. Defaults to the first day of the current month. At most 92 days may separate `from` and `to`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| to | Yes | Last day covered, `YYYY-MM-DD` inclusive. |
| days | Yes | Per-day breakdown over the range, oldest first. A day with no usage is absent rather than reported as zero. |
| from | Yes | First day covered, `YYYY-MM-DD` inclusive. |
| key_id | Yes | Identifier of the key this usage belongs to. |
| totals | Yes | Units per endpoint over the whole range. |
| total_units | Yes | Total units over the whole range. |
| identity_pooled | Yes | Whether quota is pooled across every key belonging to the same identity. When true, these figures are the identity's shared consumption, so another key of the same owner also spends them. |
| month_used_units | Yes | Units counted against the monthly quota right now: the very number the quota check enforces on, independent of `from`/`to`. Quota is monthly, so this — not `total_units` — is what to compare with `monthly_quota_units`. It includes units recorded but not yet written to the daily counters, so over a whole-month range it can exceed `total_units`; that is not a discrepancy. |
| balance_millipence | Yes | Prepaid balance in millipence (thousandths of a penny), for usage beyond the monthly allowance. |
| monthly_quota_units | Yes | The key's monthly allowance in units. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does so thoroughly. It discloses that the call costs no quota, that figures are weighted units rather than raw request counts, that identity_pooled may make the numbers shared across keys, and that only the authenticating key's usage can be read. It also warns against misreporting units as calls.
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 minimal one, but every extra sentence addresses a real interpretation risk: units vs. calls, pooled quota, and inability to query other keys. It is front-loaded with purpose and cost, then moves through parameters, return semantics, and caveats in a logical order.
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 simple two-optional-parameter read tool with an output schema, the description is exceptionally complete. It covers purpose, cost, default ranges, date-bound behavior, output semantics, unit weighting, pooled identity, authentication key ownership, and the required gateway setup. An agent has everything needed to call and interpret this 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 100%, so the schema already documents both optional parameters including defaults, format, inclusiveness, and the 92-day cap. The description repeats and lightly contextualizes this ('bound the report; omitted, it covers the current month to date') but does not add substantial new parameter-level meaning beyond 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?
The description opens with a specific verb and resource: 'Check what your own API key has spent.' It also adds a clear use case ('decide mid-task whether to keep going') and is plainly distinct from all sibling tools, which concern routing, geocoding, style, or planning rather than quota usage.
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 states exactly when to use the tool: mid-task to decide whether to continue. It also gives an explicit when-not: 'there is no way to read another caller's usage,' and clarifies that reading is free, so there is no quota cost concern. No alternative tool is relevant among siblings, so no alternative routing is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
heritage_narrationAInspect
Three to five short spoken lines an hour about the ground a route is on: one sentence, at the point the driver reaches the thing it is about, and then silence. Not a tour and not a chatbot. NOTHING IS GENERATED HERE: every line is a sentence a person wrote from a public-domain plaque inscription and a person reviewed, compiled into the gateway binary, so no model runs in this path and the lines are identical for every driver. Give geometry_polyline6 from the route tool and, IMPORTANT, duration_s from the same answer: without it the silence budget falls back to a distance, and "four lines an hour" is a claim about time that a distance answers wrongly at both ends. Optional min_gap_s, min_gap_m, max_offset_m (default 60, hard ceiling 80), max_lines and voice_format ("opus" or "m4a", which adds each line's audio cache key and URL and NEVER synthesises). COVERAGE IS ONE CORRIDOR, deliberately: the Chelsea riverside, 18 reviewed lines over 5 km. EVERY OTHER ROUTE ANSWERS WITH NO LINES, and that is a correct answer rather than a failure. ALWAYS READ THE CENSUS, which is the record of WHAT WAS NOT SAID: no lines with every entry in beyond_reach means this feature does not cover the journey; no lines with entries in silenced_by_budget means the corridor is covered and the budget is holding them back. They are different answers and must never be relayed the same way. On the reference route the census reports 1 spoken and 17 silenced, which is the design working, not a thin corpus. Every line publishes offset_m, the measured distance from the plaque to the route, because it is the entire warrant for the word "here", and plaque_ids so any claim can be taken back to its source. TWO OMISSIONS ARE DELIBERATE: no line says anything is visible, still standing or unchanged (a plaque records that somebody was somewhere, and nothing more), and NO LINE SAYS WHICH SIDE OF THE ROAD anything is on, because nothing in the source records it and a look that finds nothing spends the driver's trust in everything else. Do not add either. COSTS 1 UNIT a call: it reads no tiles and opens no archive. Requires the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| max_lines | No | Ceiling on how many lines come back, 1 to 50 (default 12). | |
| min_gap_m | No | Least distance between two lines, metres (default 400). A floor under the time budget in every case. | |
| min_gap_s | No | Least time between two lines, seconds (default 900, which is four an hour). Applied only with `duration_s`. | |
| duration_s | No | That route's own duration, seconds: `duration_s` from the same answer. **Supply it.** Without it the silence budget falls back to a distance, and "three to five lines an hour" is a claim about time that a distance answers wrongly at both ends. | |
| max_offset_m | No | How near a plaque must come to the route before its line may be spoken, metres (default 60, hard ceiling 80). | |
| voice_format | No | Container to address each line's audio clip in: `opus` or `m4a`. Given, every line gains a `clip` with its synthesis cache key and URL. It NEVER synthesises: the key is a pure function of the sentence, so asking here buys nothing. | |
| geometry_polyline6 | Yes | The route shape, precision-6 encoded: `geometry_polyline6` straight out of the `route` tool's answer. |
Output Schema
| Name | Required | Description |
|---|---|---|
| lines | Yes | The lines, in route order. Empty is the ordinary answer nearly everywhere: read `census` before saying anything about it. |
| caveat | Yes | The standing limits, for relaying to users. |
| census | Yes | The census of what was NOT said: `corpus_entries`, `within_reach`, `beyond_reach`, `spoken`, `silenced_by_budget`, the gap that was applied and what it was derived from. An empty `lines` with every entry in `beyond_reach` means this feature does not cover the journey; an empty `lines` with entries in `silenced_by_budget` means the budget is working. They are different answers and must not be reported the same way. |
| corridor | Yes | The corridor that was consulted: its id, name, the road it runs on and the date its lines were reviewed. |
| attribution | Yes | The licence notice for this answer. |
| route_length_m | Yes | The route's own length, metres. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the behavioral burden and does so exceptionally: no model runs, lines are pre-reviewed and identical for every driver, audio is never synthesised, deliberate omissions are listed, census semantics are explained, and the cost/unit and gateway requirement are stated. This is far beyond typical 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 and emphatic, but nearly every sentence earns its place by preventing a specific misuse or misinterpretation. The all-caps warnings hurt readability slightly, and the single dense paragraph could be better structured, but it remains information-dense 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 with unusual coverage limits, silent-failure semantics, and deliberate omissions, the description is complete: it covers inputs, output expectations, coverage scope, census interpretation, cost, authentication gateway, and what not to add. Since an output schema exists, the tool's return structure does not need to be spelled out in the description.
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 100%, so the baseline is 3, but the description adds cross-parameter meaning: `geometry_polyline6` and `duration_s` must come from the same `route` answer, and it explains why `duration_s` changes the silence budget from a distance to a time. It reinforces defaults and the no-synthesis meaning of `voice_format` beyond the schema's isolated descriptions.
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 names a specific deliverable ('three to five short spoken lines an hour'), ties it to a concrete resource (the route ground and plaque inscriptions), and sharply distinguishes it from a tour or chatbot. It also states the deliberate single-corridor coverage, which prevents an agent from treating it as a general narration 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 gives explicit operational context: feed it `geometry_polyline6` and `duration_s` from the same `route` answer, and interpret no-lines as a correct answer outside the Chelsea corridor. It does not name a specific sibling alternative, but 'not a tour and not a chatbot' plus the corridor coverage effectively bounds when it should be chosen.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_place_categoriesAInspect
List the canonical place categories you can pass as category to nearby_places and search_along_route (and browse on with geocode). Each entry is a category token (the exact value to send, e.g. "fuel", "charging_station", "hgv_parking"), the aliases that colloquially name it ("petrol station", "EV charger", "lorry park"), and a one-line description of what it covers. Read this before guessing a category: a token that is not on this list matches nothing, and quietly returns an empty result rather than an error. Cuisines, brands and names are NOT categories — search those as free text. Sorted by category and identical on every call. Local lookup, no network, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| categories | Yes | Every category `nearby_places`, `search_along_route` and `geocode` recognise, sorted alphabetically by `category`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly. It discloses that the list is sorted, identical on every call, local, offline, quota-free, and that invalid category tokens silently return empty results. This goes well beyond a simple 'list' statement and gives the agent important behavioral expectations.
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 information-dense but every sentence earns its place: what the tool lists, what each entry contains, critical usage warnings, exclusions, and determinism. The most important purpose is front-loaded, and the warnings are positioned where they are most relevant.
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 tool with an output schema, the description is complete. It covers purpose, return structure, relationship to sibling tools, failure mode for invalid tokens, excluded categories, determinism, and performance characteristics. Nothing an agent needs to decide whether to call it 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 tool has zero parameters, so there is no parameter schema to augment; the baseline is 4. The description still explains that the output entries are exact category tokens, aliases, and descriptions, which helps the agent understand how the category value is meant to be used in sibling tools.
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: it lists canonical place categories for use with nearby_places and search_along_route. It clearly distinguishes this from sibling tools like list_style_layers by tying it to place-category tokens and related geocoding workflows. The exact purpose is unambiguous.
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 to read this before guessing a category, and warns that unrecognized tokens return an empty result rather than an error. It also states that cuisines, brands, and names are not categories and should be searched as free text, giving clear guidance on when not to use this tool and what to do instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_style_layersAInspect
List everything a MapMap style theme can style: the first-party named bases a style can start from (pass one as create_style's base, or as the static-map API's style=), the named palette slots with their light/dark default colours, the skeleton layer ids (paint order) that set_layer_paint accepts, and the OpenMapTiles source-layers extra layers may reference. Attribution is enforced on every compiled style and cannot be themed away. Local lookup, no network; always works.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| bases | Yes | The first-party named bases a style can start from, in display order: pass one to `create_style`'s `base`, or to the static-map API's `style=`. |
| layer_ids | Yes | The skeleton layer ids a theme's `layers` may override, in paint order (first = bottom). |
| attribution | Yes | The attribution contract: enforced on every compiled style, not themable. |
| palette_slots | Yes | The named palette slots a theme's `palette` may override, with their light/dark defaults, in presentation order. |
| source_layers | Yes | The OpenMapTiles source-layers the tiles emit; `extra_layers` must reference one of these. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description assumes the behavioral disclosure burden. It states that lookup is local, requires no network, and always works, and it discloses that attribution is enforced on compiled styles and cannot be themed away. It does not describe the output shape, but an output schema exists, so that is not required.
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?
It is one long, information-dense sentence, but every clause contributes either a content category, a consumer tool, or a behavioral caveat. It could be split into multiple sentences for readability, but 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?
For a no-argument enumeration tool with an output schema, the description fully covers the returned categories, the downstream consumers of those categories, and the notable behavioral constraints. Nothing an agent needs to invoke it 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?
The tool has zero parameters, making parameter-level explanation unnecessary. The description still adds semantic value by showing how the returned identifiers plug into create_style and set_layer_paint, which is more than the empty input schema can convey.
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 a concrete verb–resource pair ('List everything... can style') and enumerates four distinct content categories: named bases, palette slots, skeleton layer ids, and source-layers. It references sibling tools such as create_style, set_layer_paint, and the static-map API, making it easy to distinguish from the many nearby style/route 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 explains what the listed values are for: pass a base to create_style or the static-map style= parameter, and pass skeleton layer ids to set_layer_paint. It does not explicitly frame when to use this tool over alternatives like get_style, but the usage context is clear and no exclusions are needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
match_traceAInspect
Snap a recorded GPS trace to the road network and say what it actually travelled over. Provide shape (2 to 2000 recorded points, oldest first) or encoded_polyline (the same trace as a polyline6 string) — not both — plus the costing it was travelled under: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". Costing decides which roads the trace may match onto, so a walk matched as "auto" snaps to the carriageway rather than the footpath. Returns the matched path as geometry_polyline6 (the snapped roads, not your raw points) with its distance_m and duration_s, then the roll-ups: by_road_class and by_admin (distance and time, longest first), by_surface (distance), and toll, bridge and tunnel totals. This is how you turn a dashcam or telematics log into a report — which country and region the driving happened in, how much of it was motorway, how much was tolled, how much was unpaved. Honesty: the roll-ups are summed per matched road segment, so they need not add up to distance_m exactly, and segments the map records no surface or admin area for are left out of that breakdown rather than filed under a guess — an entry in by_admin with null codes is exactly that, counted and not attributed. Needs the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY); there is no direct-backend fallback.
| Name | Required | Description | Default |
|---|---|---|---|
| shape | No | The trace as an ordered list of recorded points, oldest first. Between 2 and 2000 points. Provide this or `encoded_polyline`. | |
| costing | No | Costing model the trace was travelled under: `auto` (default), `truck`, `bicycle`, `pedestrian` or `motor_scooter`. It decides which roads the trace may be matched onto, so a walked trace matched as `auto` snaps to the carriageway rather than the path. | |
| encoded_polyline | No | The trace as a Google encoded polyline with six digits of decimal precision (polyline6) — the geometry `route` and `match_trace` themselves return. Provide this or `shape`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| toll | Yes | Tolled portion of the matched path. |
| bridge | Yes | Bridge portion of the matched path. |
| tunnel | Yes | Tunnel portion of the matched path. |
| costing | Yes | Costing the trace was matched under. |
| summary | Yes | One-line human summary of the match, for reading aloud. |
| by_admin | Yes | Distance and time by administrative area, longest first. An entry whose codes are all null covers segments the graph could not place in any admin area — counted honestly rather than guessed at. |
| by_surface | Yes | Distance by road surface (`paved`, `paved_smooth`, `gravel`, …), longest first. Empty when the graph records no surface for any matched segment. |
| distance_m | Yes | Length of the matched path in metres. |
| duration_s | Yes | Travel time along the matched path in seconds, from the engine's own time model. |
| edge_count | Yes | How many road segments the trace matched onto. |
| by_road_class | Yes | Distance and time by road class (`motorway`, `primary`, `residential`, …), longest first. |
| geometry_polyline6 | Yes | The matched path as a Google encoded polyline with six digits of decimal precision (polyline6). This is the trace snapped to real roads, not the raw input. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure, and it does so thoroughly. It explains what is returned (snapped roads, not raw points), the roll-up caveat that segments need not sum exactly to distance_m, that unknown admin/surface areas are omitted rather than guessed, and the hard dependency on the MapMap gateway with no fallback. This is exemplary transparency for a complex 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 long but information-dense; every sentence adds operational or semantic value, including the honesty caveat and gateway requirement. It front-loads the core purpose and then layers in invocation details, output semantics, and limitations. Slightly verbose, but no filler—each clause 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?
For a tool with three parameters, no annotations, and a rich output schema, the description is complete: it covers input formats, parameter interplay, output symbols, aggregation caveats, unknown-value handling, and the required gateway configuration. An agent has enough context to call it correctly and interpret results, even without the output schema in front of 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 coverage is 100%, so the baseline is 3, and the description adds genuine meaning beyond the schema. It clarifies that costing determines which roads the trace may match onto with a concrete example, explicitly says 'not both' for shape/encoded_polyline, and defines encoded_polyline as polyline6, the same format route and match_trace return. That extra context helps invocation without redundancy.
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: 'Snap a recorded GPS trace to the road network' and clearly explains the output is the matched path plus road-class and admin roll-ups. It explicitly distinguishes use from route planning by framing it as 'a dashcam or telematics log into a report', making it easy to tell apart from siblings like route or route_observations.
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 usage context: when you have a recorded trace and want to know what roads it travelled, with concrete costing guidance (a walked trace matched as 'auto' snaps to the carriageway rather than the footpath). It does not explicitly name sibling alternatives or state when not to use this tool, but the input-vs-route framing is clear enough to route an agent correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
matrixAInspect
Compute a travel time/distance matrix between origins (rows) and destinations (columns). Costing "auto", "truck" (with optional truck profile as in route), "bicycle", "pedestrian" or "motor_scooter". Returns durations_s[i][j] in seconds and distances_m[i][j] in metres; null cells are unreachable pairs. Up to 10,000 cells per call (origins × destinations). Optional exclude_polygons for before/after scenarios ("close this bridge and recompute the matrix"): an array of polygons, each an array of [lon, lat] pairs forming one ring — longitude FIRST — whose intersecting roads are excluded from every cell's path finding. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored.
| Name | Required | Description | Default |
|---|---|---|---|
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck". | |
| costing | No | Costing model: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| origins | Yes | Origin locations (matrix rows). | |
| destinations | Yes | Destination locations (matrix columns). | |
| exclude_polygons | No | Areas to avoid — scenario analysis ("close this bridge and recompute the matrix"): an array of polygons, each an array of `[lon, lat]` pairs forming one exterior ring (GeoJSON-style, longitude FIRST). Roads intersecting any ring are excluded from every cell's path finding. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored. |
Output Schema
| Name | Required | Description |
|---|---|---|
| distances_m | Yes | Travel distances in metres, same shape as `durations_s`. Null cells are unreachable pairs. |
| durations_s | Yes | Travel times in seconds; `durations_s[i][j]` is origin `i` → destination `j`. Null cells are unreachable pairs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the output format (durations_s, distances_m), the null-cell semantics for unreachable pairs, the 10,000-cell limit, and the engine-specific behavior of exclude_polygons. This is substantial behavioral context beyond the schema.
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 well-organized: it opens with the core function, then covers costing, output, limits, and the optional parameter. Every sentence adds value. It is slightly long but justified by the complexity of the tool.
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 (5 params, output schema, engine-specific behavior), the description covers the essential operational details: output units, null semantics, cell limit, and engine caveat. It does not explain how to interpret the output schema in detail, but the output schema exists and the description need not repeat 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 coverage is 100%, so the baseline is 3. The description adds meaningful semantics: it explains the row/column mapping of origins/destinations, the cell limit calculation, and the scenario-analysis use case for exclude_polygons. It also clarifies the coordinate order for polygons. This goes beyond the schema's field descriptions.
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 ('Compute') and resource ('travel time/distance matrix between origins (rows) and destinations (columns)'), and enumerates the supported costing modes. It clearly distinguishes this from sibling routing tools like 'route' and 'reachable_area' by focusing on the matrix structure and cell-based output.
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 (matrix computation, scenario analysis with exclude_polygons) and even names the engine-specific behavior (Valhalla vs GraphHopper). It does not explicitly name sibling alternatives or state when NOT to use it, but the context is strong enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nearby_placesAInspect
Find places near a point, nearest first with distance in metres — by category (cafes, fuel, EV charging, parking), by name or brand ("the nearest Lloyds bank", "nearest Sainsbury's"), or both. Use this instead of geocode whenever the question is about what is NEAR a location: geocode ranks a brand's branches everywhere and only biases by proximity, so it will happily return a Lloyds in another city over the one 100 m away. Provide lat, lon and at least one of category or name. category is matched against the map's lowercased OSM tag values (amenity/shop/tourism/…), e.g. "cafe", "fuel", "charging_station", "parking", "pharmacy", "supermarket", "hotel", "restaurant", "fast_food", "atm", "bakery", "hospital", "station"; common colloquial names are normalised ("coffee" -> cafe, "ev_charging" -> charging_station, "petrol" -> fuel, "chemist" -> pharmacy). name matches the place's name or alternative names word by word, case- and accent-insensitively, with the last word also matching as a prefix. Combine the two to disambiguate a brand — "Lloyds" plus "bank" excludes Lloyds Pharmacy. A category or name the map does not carry returns an empty list, never an error. Optional radius_m (default 2500, max 100000) bounds the straight-line search distance and limit (default 5, max 10) the result count. Each result has name, one-line label, lat/lon, address parts, distance_m, categories and a details object of display tags (opening_hours, website, phone, ...) when the map carries them. Every result also carries bearing_deg and a spoken direction. Pass heading_deg (degrees clockwise from true north, 0 = north, 90 = east) and results are described from where the user stands — "ahead and slightly to your right, about 80 metres" — with a signed relative_bearing_deg (negative left, positive right); without a heading the phrasing falls back to cardinals ("to the north-east"), so this works with or without a compass. Add fov_deg to keep only what lies within that cone of the heading — it is the FULL width of the cone, so 90 keeps what lies within 45 degrees either side of dead ahead; anything dropped is counted in out_of_view, so a non-zero count means there ARE matching places nearby, just not in front of the user — say that rather than "nothing nearby". Prefer reading direction aloud over coordinates. Requires the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude of the search point in decimal degrees (−90 to 90). | |
| lon | Yes | Longitude of the search point in decimal degrees (−180 to 180). | |
| name | No | The name or brand of the place to find — "Lloyds", "Lloyds Bank", "Sainsbury's" — for "where is the nearest X" questions. Every word must appear in the place's name or one of its alternative names, case- and accent-insensitively, with the last word also matching as a prefix ("Sains" finds Sainsbury's). Combine with `category` to disambiguate a brand used by more than one kind of place ("Lloyds" plus "bank" excludes Lloyds Pharmacy). Optional when `category` is given; at least one of the two is required. | |
| limit | No | Maximum number of results (1–10, default 5). | |
| fov_deg | No | Field of view: the full width in degrees of a cone centred on `heading_deg`, outside which results are dropped — it is the FULL width, so 90 keeps only what lies within 45 degrees either side of dead ahead. Needs `heading_deg` — a cone has to point somewhere. The count of results removed is reported as `out_of_view`. | |
| category | No | The kind of place to find. The gateway matches it against the index's lowercased OSM tag values (the value of the POI's `amenity`/`shop`/`tourism`/`railway`/… tag) — e.g. "cafe", "fuel", "charging_station", "parking", "pharmacy", "supermarket", "hotel", "restaurant", "fast_food", "atm", "bakery", "hospital", "station" — and normalises common colloquial names first ("coffee" → cafe; "ev_charging", "ev charging" → charging_station; "petrol" → fuel; "chemist" → pharmacy). A category the index does not carry matches nothing: the result is an empty list, not an error. Optional when `name` is given; at least one of the two is required. | |
| radius_m | No | Maximum straight-line distance of any result from the point, in metres (1–100000, default 2500). | |
| heading_deg | No | Which way the user is facing, in degrees **clockwise from true north** (0 = north, 90 = east, 180 = south, 270 = west). Supply it and every result is also described from the user's point of view ("just ahead on your right"); omit it and results fall back to cardinal directions ("to the north-east"), so the tool works with or without a compass. |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes | Matching places, nearest first. Empty when the index has no such place within the radius. |
| out_of_view | No | How many otherwise-matching places were dropped for falling outside `fov_deg`. Non-zero means there are matching places near the user that are simply not in front of them — say so rather than reporting nothing nearby. Always 0 when no field of view was set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and delivers: empty-list-not-error, case/accent-insensitive prefix matching, category normalization examples, fov_deg full-width semantics, heading fallback behavior, and out_of_view meaning. It even notes the gateway requirement. Exceptionally transparent.
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 given the 8-parameter tool with complex matching/bearing logic. It front-loads the core purpose and then flows into parameter details and edge cases. A bit dense, but structurally organized and appropriately sized for the 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?
Covers input requirements, output result fields (name, distance, bearing, details), edge cases (empty list, out_of_view), and gateway prerequisites. With an output schema present, it still effectively explains all necessary call parameters and expected behavior. Nothing an agent needs 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 100%, so the baseline is 3. The description adds value beyond schema by clarifying the 'at least one of category or name' requirement (not in required collection), explaining the disambiguation strategy ('Lloyds' plus 'bank'), and mentioning the 'Prefer reading direction aloud' tip. Slight redundancy with schema, but meaningful extra 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 opens with a specific verb and resource: 'Find places near a point, nearest first with distance in metres' and immediately scopes by category or name. It distinctly separates itself from geocode by explaining the proximity focus, so an agent can tell it apart from the sibling without ambiguity.
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 instructs to 'Use this instead of geocode whenever the question is about what is NEAR a location' and explains why geocode is unsuitable (returns far branches over nearby ones). This direct comparison gives clear when-to-use guidance with no left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
optimise_routesAInspect
Optimise multi-vehicle, multi-stop delivery plans (VRP). Provide vehicles (id, start/end, capacity, skills, time_window), jobs (id, location, service_s, delivery/pickup, skills, time_windows) and/or shipments (pickup+delivery pairs that ride the same vehicle). Costing "auto", "truck", "bicycle", "pedestrian" or "motor_scooter" (cargo-bike and courier fleets welcome): with a truck profile (dimensions + ADR declaration, as in route), the travel-time matrix respects dimensional and dangerous-goods restrictions, so every optimised route is truck-legal. Returns a summary, unassigned tasks and per-vehicle routes with ordered steps (arrival_s/duration_s in seconds, distance_m in metres). Fair use: at most 200 unique locations per problem, and no wider than the routing engine's matrix span (1,500 km on the hosted endpoint for motor costings, 400 km stock on a self-host). Past that, cluster the stops with cluster and optimise each group, or submit the whole problem to the asynchronous lane with submit_optimise_job (2,000 locations). Optional territories are named polygons ([{id, polygon}], GeoJSON [lon, lat] rings, LONGITUDE FIRST) that bound who serves what: a vehicle listing territory_ids may serve a task only if that task sits inside at least one of the territories it names, while a vehicle listing none is unrestricted and may serve anything, inside a round or outside every one. The response's territories block says which vehicle was eligible for what and names any task no vehicle could take. A vehicle may also declare reloads {max_trips 2-5, reload_time_s, depot?} to return to a depot, reload and go out again — the tipping round. It needs a time_window, because the shift is what gets split: it is cut into that many consecutive non-overlapping windows separated by the reload time, each trip carrying the vehicle's FULL capacity and task caps. That split is fixed BEFORE the solve, so the plan is conservative and never optimistic — it cannot put a lorry in two places at once — but it is an approximation: a trip that finishes early cannot lend its spare time to the next, so stops can come back unassigned that a truly sequential model would have served, and max_trips is a budget rather than a prediction (ask for five on a shift that supports three and every window shrinks to a fifth). Read the returned reloads block before quoting arrival times, and re-plan after each tip with replan_routes for the tighter answer. relax_if_unassigned {time_windows_by_s?, allow_overtime_s?} re-solves ONCE with those relaxations if the first plan left work unassigned, and the relaxation block says honestly which plan came back: at most one second solve, never beyond the caps stated, and the relaxed plan is returned ONLY if it assigns more work than the first. Breaks are never widened — a driver's rest is not a preference to trade for a fuller van — and neither are capacities, skills, territories or task caps; only time windows move. It bills as two solves when the second one runs. Always check relaxation.relaxed_plan_used before telling anyone the day fits: a plan produced under relaxation has had promises moved. emissions {vehicle_category, fuel, euro_standard} annotates the plan with the clean-air zones its own stops sit in and what this vehicle pays in each; add avoid_zones: true to steer the travel-time matrix out of them, which changes the plan itself. Territories, reloads, relaxation and zones are computed by the MapMap gateway; without one configured the tool refuses rather than returning a plan that quietly ignored them.
| Name | Required | Description | Default |
|---|---|---|---|
| jobs | No | Single-stop jobs (at least one job or shipment overall). | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; the travel-time matrix then respects dimensional and dangerous-goods restrictions, so the whole plan is truck-legal. | |
| costing | No | Costing model for the travel-time matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| vehicles | Yes | The fleet (at least one vehicle, each with a start and/or end). | |
| emissions | No | The fleet's emission declaration, for UK clean-air / low-emission zone assessment. On its own it annotates: the response's `zones` block names every zone containing one of the problem's own locations and what this vehicle would pay there. With `avoid_zones` it also steers the internal travel-time matrix away from those zones, so the plan itself changes. | |
| shipments | No | Pickup+delivery pairs. | |
| avoid_zones | No | Keep the optimisation's travel-time matrix out of every zone the declared vehicle would be charged or banned in. Requires `emissions`. | |
| territories | No | Fleet territories: named polygons that bound which vehicle may serve which stop, referenced by `vehicles[].territory_ids`. These are request data — caller-drawn rounds, validated per call and never stored. Nothing to do with clean-air zones or with the offline map packages of the same word. | |
| relax_if_unassigned | No | Re-solve ONCE with these relaxations if the first solve leaves work unassigned, and say honestly which plan came back. At most one second solve, never beyond the caps you state, and the relaxed plan is returned only if it assigns MORE work than the first — giving away constraints for nothing is strictly worse than not giving them away. Breaks are never widened, nor are capacities, skills, territories or task caps: only time windows move, and only by the stated amounts. Bills as two solves when the second one runs. |
Output Schema
| Name | Required | Description |
|---|---|---|
| zones | No | Clean-air / low-emission zones touching the problem's own locations, and what the declared vehicle pays in each. Present only when `emissions` was declared. |
| routes | Yes | One optimised route per used vehicle. |
| profile | Yes | The matrix costing profile the plan was computed with ("auto", "truck", "bicycle", "pedestrian" or "motor_scooter"). |
| reloads | No | The multi-trip split: each vehicle's trips, their windows, the depot each returns to, and the stated approximation. Present only when a vehicle declared `reloads`. Read the `basis` inside it before quoting arrival times. The trip windows are fixed BEFORE the solve, so a lorry that tips early cannot lend the spare time to its next trip: stops can come back unassigned that a truly sequential model would have served. The plan is feasible, never optimistic — it cannot put a vehicle in two places at once — but it is not optimal. Re-plan after each tip through `replan_routes` for the tighter answer. |
| summary | Yes | Solution summary. |
| relaxation | No | The relaxation report: the caps requested, whether a second solve ran, whether ITS plan is the one returned, what was widened, and what is still unassigned. Present only when `relax_if_unassigned` was declared. Always read `second_solve` and `relaxed_plan_used` before telling anyone the day fits. A plan produced under relaxation has had promises moved, and the block is what says so. |
| unassigned | Yes | Tasks the solver could not assign to any vehicle. |
| territories | No | How the territories bound the plan: which vehicle was eligible for what, and any task no eligible vehicle existed for. Present only when `territories` was declared. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it does so comprehensively. It explains that reloads split the shift before the solve (making the plan conservative), that `max_trips` is a budget not a prediction, that relaxation runs at most one second solve and only returns the relaxed plan if it assigns more work, that breaks/capacities/skills/territories are never widened, and that the tool refuses to run when the MapMap gateway isn't configured. It also discloses billing (two solves) and the requirement to check `relaxation.relaxed_plan_used`. This is exemplary transparency.
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 dense; every sentence carries actionable information. It is front-loaded with the core purpose and then logically proceeds through vehicles/jobs/shipments, costing, territories, reloads, relaxation, and emissions. There is no fluff or redundancy—each section earns its place by explaining behaviour or constraints an agent must know.
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 (9 parameters, nested specs, multiple optional subsystems), the description is remarkably complete. It covers input requirements, output structure (summary, unassigned, per-vehicle routes with steps), units, edge cases (unassigned tasks, relaxed plans), and failure modes (refusal without gateway). With an output schema also present, nothing an agent needs to call this 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?
Although schema coverage is 100% and the schema already documents each parameter, the description adds substantial meaning beyond the schema: it explains the semantic of `max_trips` as a budget, how territory bounding works, what the `relaxation` block reports, and how `emissions`/`avoid_zones` interact. It also clarifies units (seconds, metres) and response blocks. This goes far beyond the bare parameter descriptions, fully compensating for any gaps an agent might have from the schema alone.
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 and resource: 'Optimise multi-vehicle, multi-stop delivery plans (VRP).' It immediately distinguishes itself from siblings by naming `cluster` and `submit_optimise_job` as alternatives for larger problems, and by referencing `replan_routes` for re-optimisation. The purpose is unambiguous and the scope is 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 gives explicit when-to-use and when-not-to-use guidance, including hard limits (200 unique locations, 1,500 km matrix span) and concrete alternatives: 'cluster the stops with `cluster` and optimise each group, or submit the whole problem to the asynchronous lane with `submit_optimise_job`.' It also explains when to use optional features like reloads and relaxation, and warns about their consequences, so an agent can make an informed choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
order_stopsAInspect
Put a single run's stops in the best visiting order ("order my errands"). Provide start {lat, lon} and stops (1-100 entries of {location, label?, service_s?}); optionally an end destination or round_trip: true to return to the start. Costing "auto" = car, "truck" = lorry (pass truck as in route for a truck-legal order). Returns the stops in visit order with arrival offsets in seconds, plus total duration and distance.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | Optional fixed final destination. Mutually exclusive with `round_trip`; omitted (and not a round trip), the run ends at whichever stop the solver visits last. | |
| start | Yes | Where the run starts. | |
| stops | Yes | The stops to put in the best visiting order (1–100). | |
| truck | No | Truck profile (dimensions + ADR declaration); requires costing "truck". The travel-time matrix then respects dimensional and dangerous-goods restrictions. | |
| costing | No | Costing model: "auto" (default) or "truck". | auto |
| round_trip | No | Return to `start` after the last stop (default false). |
Output Schema
| Name | Required | Description |
|---|---|---|
| ordered | Yes | The stops in optimal visiting order. |
| profile | Yes | The matrix costing profile ("auto" or "truck"). |
| distance_m | No | Total travel distance in metres, when reported. |
| duration_s | Yes | Total travel time in seconds. |
| unassigned_stop_indexes | Yes | 0-based indexes of stops the solver could not fit (empty in the normal, unconstrained case). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the disclosure burden. It clearly discloses the output shape (ordered stops, arrival offsets, total duration/distance), round-trip behavior, and truck/costing semantics. It does not discuss error or failure behavior, but no hidden side effects or contradictions are left ambiguous.
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?
Four sentences with the purpose front-loaded; every sentence adds required information about inputs, optional modes, costing, and output. There is no filler or redundant restating of the tool name.
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, combined with the detailed input schema and output schema, covers required and optional parameters, costing, truck profile, and return values. Nothing an agent needs to invoke this tool correctly is missing, and any remaining details live in 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 description coverage is 100%, and the schema already documents every parameter, including LatLon, OrderStopSpec, TruckSpec, and the end/round_trip mutual exclusivity. The description adds only shorthand notation and costing glosses, so it stays at the baseline 3.
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 names a specific operation ('Put a single run's stops in the best visiting order') and a concrete resource (stops with start/end). It is clear, but it does not explicitly differentiate from siblings like plan_errands or optimise_routes, so an agent must infer the scope from the phrase 'single run'.
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 communicates the single-run errand context and explains costing choices, but it never states when to prefer this tool over route, optimise_routes, or plan_errands, nor when not to use it. Usage guidance is therefore implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
places_in_viewAInspect
What is over THERE: given a position and the direction the user is facing, the places inside that cone, and whether the ground and the buildings in between let them actually be seen. Use this for "what is that over there", "is there a pub in that direction", "what am I looking at". Use nearby_places instead when the question is about what is NEAR a point rather than what is in a direction. Provide lat, lon, bearing_deg (degrees CLOCKWISE FROM TRUE NORTH: 0 north, 90 east, 180 south, 270 west) and at least one of category or name; category=building reaches named buildings. Optional fov_deg is the FULL width of the cone (default 60, so 30 degrees either side), radius_m the range (default 1000, max 5000), eye_height_m the observer's eye height (default 1.6). Each result carries distance_m, bearing_deg, a signed angular_offset_deg (negative left, positive right), a spoken direction, and a visibility block. READ THE VISIBILITY BLOCK BEFORE SAYING ANYTHING: clear means nothing in the data stands in the way, occluded names what does (a hill, or a building with its height), and unknown means NO check could run: with unknown say you cannot tell, never that it is visible. Read basis too: terrain-only in a town means hills were checked and buildings were not, which is weak. A non-zero out_of_sector means there ARE matching places nearby, just not in that direction, so say that rather than "nothing nearby". coverage names the datasets that answered and caveat is the standing limit: visibility is modelled from maps, not observed, and trees, walls, scaffolding and weather are not in it. Requires the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude of the observer in decimal degrees (−90 to 90). | |
| lon | Yes | Longitude of the observer in decimal degrees (−180 to 180). | |
| name | No | A place name or brand to look for. At least one of `category` and `name` is required. | |
| limit | No | Maximum number of results (1–25, default 5). | |
| fov_deg | No | Full width in degrees of the cone centred on `bearing_deg` (1–360, default 60, so 30 degrees either side). The FULL width, not the half angle. | |
| category | No | The kind of place to look for, from the same vocabulary `nearby_places` uses ("cafe", "pub", "fuel", "charging_station" …). Use "building" to ask what a named building over there is. At least one of `category` and `name` is required. | |
| radius_m | No | Maximum straight-line range in metres (1–5000, default 1000). | |
| bearing_deg | Yes | Which way the observer is facing, in degrees **clockwise from true north** (0 = north, 90 = east, 180 = south, 270 = west). Required: this tool answers "what is over there", and "there" has to point somewhere. | |
| eye_height_m | No | Height of the observer's eye above the ground in metres (0–500, default 1.6, a standing adult). A driver's eye is nearer 1.2 m. | |
| visible_only | No | When true, return only places whose visibility verdict is `clear`. Default false, which returns everything in the cone WITH its verdict, usually the better answer, because "it is there but you cannot see it from here" is worth saying. |
Output Schema
| Name | Required | Description |
|---|---|---|
| caveat | Yes | The standing caveat: visibility here is modelled, not observed. |
| results | Yes | Places inside the cone, best first: everything visible before everything unchecked before everything occluded, and within each of those, nearest and most nearly dead-ahead first. |
| coverage | Yes | One sentence naming which datasets the visibility verdicts were actually checked against. Worth repeating when a verdict is being relied on. |
| out_of_sector | No | How many otherwise-matching places were dropped for lying outside the cone. Non-zero means there ARE matching places near the observer, just not in the direction they are facing, so say that rather than "nothing nearby". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description bears the full burden of behavioral disclosure, and it delivers: it explains the three visibility verdicts, instructs the agent to read the visibility block before speaking, warns that `unknown` must not be reported as visible, explains `basis`, `out_of_sector`, `coverage`, `caveat`, and the model's limits (trees, walls, scaffolding, weather). It even mentions the required MapMap gateway. This is exemplary transparency.
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 clause earns its place: purpose, examples, sibling routing, parameter defaults, output-reading rules, and caveats are all packed densely without repetition. The most important direction semantics and visibility-reading instructions are front-loaded, and the auth requirement is saved for the end. Nothing is wasted.
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 10 parameters, an output schema, no annotations, and subtle output semantics, the description is complete: it tells the agent what inputs to supply, what the key output fields mean, how to react to `unknown` and `out_of_sector`, what the standing limitations are, and what infrastructure is required. An agent has everything needed 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 coverage is 100%, so the baseline is 3. The description adds meaningful parameter semantics beyond the schema: `bearing_deg` is clockwise from true north, `fov_deg` is the FULL cone width (30 degrees either side of default), `eye_height_m` has a standing-adult default, and `category=building` is a named-building shortcut. It doesn't explicitly discuss `visible_only` or `limit`, but the schema documents those well, so the added value receives a 4.
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, memorable framing—'What is over THERE'—and states the exact inputs (position, facing direction) and outputs (places in the cone, visibility verdicts). It also explicitly names the sibling it is not: `nearby_places`. This makes the tool's identity and scope immediately distinguishable.
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 concrete example queries ('what is that over there', 'is there a pub in that direction') and an explicit routing rule: use `nearby_places` when the question is about proximity rather than direction. It also tells the agent that `category=building` reaches named buildings and warns about reading `out_of_sector`. The when-to-use guidance is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plan_dayAInspect
Turn an itinerary into one navigable multi-stop route. Provide a start and stops (each a location {lat, lon} or a free-text name to geocode, plus optional dwell_minutes time at the stop), optional depart_at (RFC 3339) for absolute ETAs, optimise: true to reorder stops for the shortest day (VROOM solver), and return_to_start. Costing "auto", "truck" (with a truck profile the whole day respects dimensional/ADR restrictions), "bicycle", "pedestrian" or "motor_scooter". Returns the stops in visit order with per-leg duration/distance and arrival/departure times, totals, and the full route geometry (polyline6). Geocoded names carry a resolution — when ambiguous is true, check alternatives and re-run with an explicit location rather than trusting the guess.
| Name | Required | Description | Default |
|---|---|---|---|
| start | Yes | Where the day starts (name or location; `dwell_minutes` ignored). | |
| stops | Yes | The stops to visit (1–20). Visited in the given order unless `optimise` is true. | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck". | |
| costing | No | Costing model: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| optimise | No | Reorder the stops for the shortest day (VROOM solver; requires the optimisation sidecar). Default false: visit in the given order. | |
| depart_at | No | Departure time as RFC 3339 (e.g. "2026-07-18T09:00:00Z"); when given, every ETA is also returned as an absolute timestamp. | |
| return_to_start | No | End the day back at the start (default false). |
Output Schema
| Name | Required | Description |
|---|---|---|
| start | Yes | The day's starting point. |
| stops | Yes | The stops in visit order, each with leg, ETAs and any geocoding resolution to double-check. |
| costing | Yes | The costing the plan was routed with. |
| summary | Yes | One-line human-readable summary of the day. |
| depart_at | No | The departure time echoed back, when one was given. |
| finish_at | No | Absolute end of the day (RFC 3339), when `depart_at` was given. |
| optimised | Yes | Whether the stop order was optimised (VROOM) or kept as given. |
| return_leg | No | The leg back to the start, when `return_to_start` was set. |
| total_dwell_s | Yes | Total time at stops, seconds. |
| finish_offset_s | Yes | End of the day (last arrival + dwell), seconds after departure. |
| total_distance_m | Yes | Total travel distance, metres. |
| geometry_polyline6 | Yes | Full multi-stop route geometry (polyline6) — hand it to the map SDK or the `route` tool consumers directly. |
| total_travel_duration_s | Yes | Total driving/travel time, seconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses key behaviors: geocoding fallback, ambiguous resolution handling, VROOM optimisation, truck ADR restrictions, absolute ETAs with depart_at, and return geometry as polyline6. It also warns about ambiguous geocoding and tells the agent to re-run with explicit coordinates. This is strong behavioral disclosure beyond the schema.
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 well-organized: it front-loads the core purpose, then walks through parameters in a logical order, and ends with the geocoding caveat. Every sentence adds information. It's slightly long but justified given the tool's complexity and the absence of 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?
The tool has 7 parameters, an output schema, and no annotations. The description covers the main behaviors, return values, and edge cases (ambiguous geocoding). It doesn't mention error conditions (e.g., what happens if optimise is requested without the sidecar, or if truck is supplied without costing 'truck'), but the schema already notes the sidecar requirement. Overall, it's complete enough for an agent to call 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 100%, so the baseline is 3. The description adds value by explaining how parameters interact: start + stops, dwell_minutes shifting ETAs, optimise reordering via VROOM, truck profile affecting the whole day, and depart_at enabling absolute ETAs. It also clarifies the return_to_start behavior. This goes beyond the schema's individual field descriptions.
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: 'Turn an itinerary into one navigable multi-stop route.' It clearly distinguishes this from siblings like route, optimise_routes, order_stops, and plan_errands by focusing on a full day's itinerary with stops, dwell times, costing, and return-to-start. The scope is unambiguous.
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 it (planning a multi-stop day) and contrasts with alternatives by mentioning the VROOM solver and costing options. It doesn't explicitly say 'use X instead when...' but the context is clear enough for an agent to select it over route or optimise_routes. A small gap: no explicit exclusion of single-leg routing or when to prefer plan_errands.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plan_errandsAInspect
Order a handful of errands against a hard arrival time, and say honestly whether they fit. This is the "pick up a prescription, get petrol, and be at the school by quarter past three" tool. Give origin, destination (+ destination_name), arrive_by (RFC 3339 with an offset: convert "quarter past three" yourself), optional depart_at, and 1 to 5 errands. Each errand is EITHER a category (a kind of place: "pharmacy", "fuel", "supermarket", or a colloquial phrase the server normalises; use list_place_categories for the vocabulary) OR a place {lat, lon} the driver already knows ("the school", "the nursery"). Resolve a named place with geocode first and pass the coordinate: never invent one. Optional dwell_minutes per errand (default 5). The server chooses the order and the actual shops, exhaustively, over engine-computed travel times -- do NOT attempt the ordering or the arithmetic yourself. IMPORTANT: feasible: false is an ANSWER, not an error to retry. It names the errand that costs the most (blocking_errand), says how late the whole chain would be (over_by_s), and returns the stops of the chain that DOES fit with dropped naming what had to go. Tell the driver what to drop. Every stop is a real indexed place carrying its id: never mention a shop the answer did not return. hours is "open_on_the_tag" (the map's tag covers your arrival, which is evidence and not a promise) or "unknown" (most places carry no hours at all); a place the tag proves shut is never proposed. ALWAYS show usage_note: this is planned before setting off or by a passenger, never at the wheel. Requires the MapMap gateway.
| Name | Required | Description | Default |
|---|---|---|---|
| origin | Yes | Where the driver sets off from. | |
| errands | Yes | The errands, in any order: the answer decides the order. One to five. | |
| arrive_by | Yes | The hard arrival time, RFC 3339 with an offset ("2026-09-21T15:15:00+01:00"). Convert "quarter past three" to an absolute instant in the driver's own offset before calling. | |
| depart_at | No | When they set off, RFC 3339. Defaults to now. | |
| destination | Yes | Where they have to be by `arrive_by`. | |
| destination_name | No | What to call the destination in the answer ("the school"). | |
| max_detour_minutes | No | How far off the direct route a candidate place may sit, as a detour in minutes (default 12, at most 45). |
Output Schema
| Name | Required | Description |
|---|---|---|
| stops | Yes | The stops, in visit order. On an infeasible answer these are the stops of the reduced plan, the one that DOES fit. |
| reason | No | The same cause in plain language, for the driver. |
| arrival | No | When the plan arrives, RFC 3339. Present whenever there is a plan, including the reduced plan on an infeasible answer. |
| dropped | Yes | Errands that had to be dropped for the plan to fit. Empty when feasible. |
| slack_s | No | Spare seconds before the deadline. |
| feasible | Yes | **Whether every errand fits before the deadline.** False is an ANSWER, not an error: report `reason`, the errand named in `blocking_errand`, and what `dropped` says has to go. |
| arrive_by | Yes | The deadline, echoed. |
| departure | Yes | When the driver sets off, RFC 3339. |
| over_by_s | No | How late the whole chain would be, seconds. |
| usage_note | Yes | **Always present.** Why this is planned stationary rather than at the wheel. Show it. |
| attribution | No | Credit owed for the place data, when the answer used the index. |
| reason_code | No | Machine token for why the chain does not fit: "deadline_missed", "destination_unreachable_in_time", "no_candidates_in_corridor", "all_candidates_closed" or "unroutable". |
| corridor_note | Yes | **Always present.** What the corridor search did and did not look at. An empty answer is a statement about this index and this corridor, never about what exists on the ground. |
| failed_errand | No | The errand a "no_candidates_in_corridor" or "all_candidates_closed" answer is about. |
| total_drive_s | No | Total driving time, seconds. |
| total_dwell_s | No | Total time out of the car, seconds. |
| blocking_errand | No | The errand that costs the most time, when the deadline is missed. |
| verification_note | Yes | **Always present.** That every stop is an indexed place or a supplied coordinate, never a generated one. |
| geometry_polyline6 | No | The planned journey as an encoded polyline6. |
| opening_hours_note | Yes | **Always present.** How opening hours were used, and how little of the map carries them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so richly: feasible:false is an answer not an error, blocking_errand/over_by_s/dropped semantics, hours being evidence not promise, closed places never proposed, stop provenance, usage_note, and gateway requirement. This goes well beyond a generic 'plans errands' statement.
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 dense and front-loaded with purpose and example, followed by critical call semantics and warnings. No filler; every sentence adds operational or safety 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?
For a complex 7-parameter tool with no annotations, it covers required inputs, optional inputs, output semantics, failure semantics, safety, and environmental dependency. An output schema exists for return values, so not restating them is appropriate.
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 100%, so baseline is 3, but the description adds meaning: convert colloquial times to RFC 3339 yourself, resolve named places via geocode before passing coordinates, use list_place_categories, 1-5 errands, dwell default 5. It does not mention max_detour_minutes, but the schema already documents it.
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 the verb+resource precisely: 'Order a handful of errands against a hard arrival time, and say honestly whether they fit.' The example ('pick up a prescription...') and domain-specific framing separate it from sibling routing/planning tools like route, order_stops, or plan_day.
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?
Gives clear operational context: use list_place_categories for vocabulary, geocode named places first, don't do ordering or arithmetic yourself, and never at the wheel. It does not explicitly name sibling alternatives or exclusions, but the when-not ('planned before setting off or by a passenger, never at the wheel') and task-specific framing are clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plan_ev_routeAInspect
Plan a whole electric-vehicle journey, charge stops included. Give origin and destination (plus optional waypoints) and a vehicle — a published profile ("small_hatch", "saloon", "suv", "van") and/or inline figures (battery_kwh, mass_kg, drag_area_m2, aux_kw, connectors) — with start_soc (default 0.9), min_arrival_soc (default 0.1), reserve_soc (default 0.1, the floor the charge must never drop below mid-route), optional connectors and min_kw filters and ambient_temperature_c. Energy comes from a published road-load physics model over the route's own legs; charge times are integrated over the vehicle's charging curve capped by the charge point, NOT energy divided by peak power, which is the single biggest error in naive EV planners. Returns the stops with arrive/depart state of charge, charge time and detour, a per-leg state-of-charge trace, and the journey's driving and charging time. IMPORTANT: when no plan exists — a charger desert, a connector mismatch, a gap wider than the car's range — the answer comes back with feasible: false, a reason and the furthest point on the route the car can actually reach. That is an ANSWER, not an error to retry: report the reason and never describe it as a plan. gradient_data says whether elevation was available: "absent" means consumption was modelled on the flat and under-reads a hilly route. There is no national charge-point registry, so ALWAYS show the returned coverage_note — an infeasible plan means "none from these operators", never "there are no chargers here" — and statuses are current only when availability_live is true. Requires the MapMap gateway; answers a clear error when the deployment has no charge-point dataset. Display the returned charging_attribution with the plan.
| Name | Required | Description | Default |
|---|---|---|---|
| min_kw | No | Keep only charge points with a usable connector rated at least this many kW (e.g. 50 for rapid charging only). | |
| origin | Yes | Where the journey starts. | |
| vehicle | No | The vehicle. Omitted ⇒ the published "saloon" default, and the answer says which vehicle it used. | |
| start_soc | No | State of charge at the start, 0–1 (default 0.9). | |
| waypoints | No | Intermediate points the route must pass through, in order (at most 8). Charge stops are inserted around them. | |
| connectors | No | Keep only charge points offering at least one of these connector standards: "type2", "type1", "ccs", "chademo", "tesla", "domestic", "other". This narrows the vehicle's own set, never widens it. | |
| destination | Yes | Where it ends. | |
| reserve_soc | No | The floor the state of charge must never fall below mid-route (default 0.1). Distinct from the arrival figure. | |
| min_arrival_soc | No | Lowest acceptable state of charge on arrival (default 0.1). | |
| max_detour_minutes | No | How far off the route a charge point may sit, as a detour in minutes (default 15, at most 120). | |
| ambient_temperature_c | No | Ambient temperature in °C. Derates traction energy from a published study; cabin heating belongs in the vehicle's `aux_kw`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| legs | Yes | The driving legs, in order. |
| stops | Yes | The charge stops, in visit order. Always empty when `feasible` is false: a journey that cannot be completed has no stop list. |
| reason | No | The same cause in plain language, for the user. |
| summary | Yes | The plan at a glance. |
| vehicle | No | The vehicle the plan was computed for. |
| feasible | Yes | **Whether the journey is possible at all.** False means no plan exists — a charger desert, a connector mismatch, or a gap wider than the car's range. Report the `reason` and the furthest reachable point; never describe an infeasible answer as a plan. |
| soc_trace | Yes | State of charge at every point of the journey. |
| reason_code | No | Machine token for why no plan exists, when none does: "no_chargers_in_corridor", "connector_mismatch", "out_of_range", "dead_end", "below_min_kw", "chargers_unrated", "stop_limit", "dataset_empty", "no_charge_curve" or "unroutable". |
| coverage_note | Yes | **Always present.** What this deployment's charge-point dataset does and does not cover. An infeasible plan means "none from these operators", never "there are no chargers here". Show this alongside the answer. |
| gradient_data | Yes | "complete", "partial" or "absent". **"absent" means the deployment had no elevation data and consumption was modelled on the flat**, which under-reads a hilly route. Say so rather than presenting the figure as measured. |
| profile_source | No | "default" when a published profile supplied the figures, "inline" when the caller did. |
| route_distance_m | No | Distance of the planned route, metres. |
| route_duration_s | No | Driving time of the planned route, seconds. |
| availability_live | Yes | Whether charge-point statuses came from a live availability feed. A static planner is the default: without a feed, nothing in this answer is a claim about which bays are free right now. |
| geometry_polyline6 | No | The planned journey's geometry as an encoded polyline6, through the charge stops. |
| charging_attribution | No | Attribution string for the charge-point operators actually used — display it with the plan (a licence obligation). |
| furthest_reachable_lat | No | Latitude of that furthest reachable point. |
| furthest_reachable_lon | No | Longitude of that furthest reachable point. |
| furthest_reachable_position | No | How far along the route the vehicle can get unaided, 0.0–1.0, when no plan exists. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral burden, and it does so exceptionally. It discloses the charging-curve integration model, the critical `feasible: false`/`reason` behavior as an answer rather than a retryable error, `gradient_data` caveats, the need to always display `coverage_note`, the `availability_live` freshness condition, the MapMap gateway dependency, and the display requirement for `charging_attribution`. This goes far beyond the schema and gives an agent actionable expectations.
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 important operational information: inputs, model assumptions, infeasible-result handling, data caveats, and display instructions. It is front-loaded with the purpose and then packs in critical warnings. It could be better structured with bullets for the caveats, but for a tool with this complexity, the length is justified and not 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?
Given the tool's complexity, the high number of parameters, the existence of an output schema, and the absence of annotations, the description is remarkably complete. It covers inputs, vehicle semantics, failure modes, data quality caveats, live-status conditions, deployment prerequisites, and output display requirements. An agent has enough context to call the tool correctly and interpret results sensibly.
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 100%, so the baseline is 3. The description adds extra semantic value by explaining relationships and defaults: 'reserve_soc' as the mid-route floor, vehicle profiles versus inline overrides, connector/min_kw filtering, and the key modeling caveat that charge time is integrated over the charging curve rather than energy divided by peak power. This is more than the schema provides, though not every parameter is individually elaborated in prose.
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: 'Plan a whole electric-vehicle journey, charge stops included.' This clearly distinguishes it from generic routing tools like `route` or `optimise_routes` by emphasizing EV-specific charge-stop planning. It also covers the core inputs and output at a glance, so an agent can immediately identify what the tool does.
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: planning a full EV journey with charge stops, vehicle specification, and charging constraints. It does not explicitly name sibling alternatives or say 'use route instead when no charging is needed,' so it stops short of a 5. However, the context is specific enough that an agent would not confuse this with non-EV routing tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reachable_areaAInspect
Compute the area reachable from an origin within one or more travel-time budgets — walkability/cyclability rings. Costing "pedestrian" answers "how far can I walk in 15 minutes?", "bicycle" the cycling equivalent; "auto", "truck" and "motor_scooter" work too (e.g. delivery coverage). contours_minutes lists the ring boundaries in minutes (1-10 values, each up to 120); set polygons true for filled polygons ready to render as a map fill layer instead of contour lines. Returns a GeoJSON FeatureCollection, one feature per contour. Optional exclude_polygons for before/after scenarios ("close this bridge and recompute reachability"): an array of polygons, each an array of [lon, lat] pairs forming one ring — longitude FIRST — whose intersecting roads are excluded from the reachability search. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored.
| Name | Required | Description | Default |
|---|---|---|---|
| origin | Yes | Origin the reachable area is computed from. | |
| costing | No | Travel mode: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| polygons | No | Return filled polygons instead of contour linestrings (default false). Polygons draw directly as a MapLibre fill layer. | |
| contours_minutes | Yes | Contour boundaries in minutes of travel time, e.g. [5, 10, 15] for 5/10/15-minute rings. 1–10 values, each between 0 and 120 minutes. | |
| exclude_polygons | No | Areas to avoid — scenario analysis ("close this bridge and recompute reachability"): an array of polygons, each an array of `[lon, lat]` pairs forming one exterior ring (GeoJSON-style, longitude FIRST). Roads intersecting any ring are excluded from the reachability search. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored. |
Output Schema
| Name | Required | Description |
|---|---|---|
| geojson | Yes | GeoJSON FeatureCollection of the reachability contours, one feature per requested minute value (each feature's `contour` property is its minutes), as returned by the routing engine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden, and it delivers: it discloses the return format (GeoJSON FeatureCollection, one feature per contour), the line-vs-polygon output switch, longitude-first coordinate ordering, and the critical engine caveat that exclude_polygons is silently ignored on GraphHopper. It stops short of discussing error conditions or performance, but these are minor for a read-only compute 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?
Front-loaded with the core purpose, then flows logically through costing, contours, polygons, exclusion, and engine caveat. Every sentence earns its place for a 5-parameter tool, though the exclude_polygons section is somewhat dense and partially mirrors schema text.
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 an output schema exists, 100% parameter coverage, and the tool's read-only nature, the description covers purpose, parameter intent, return format, and cross-engine behavior. The main gap is the absence of an explicit safety/read-only statement, which matters more because no annotations were provided.
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 100%, setting baseline at 3, and the description adds real value above it: it maps each costing enum value to an intent, explains polygons as a map-rendering convenience, and gives the exclude_polygons scenario meaning beyond the schema's literal definition.
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+resource: 'Compute the area reachable from an origin within one or more travel-time budgets' and immediately grounds it with 'walkability/cyclability rings'. This clearly distinguishes it from siblings like route, matrix, nearby_places, and geo_area — no other sibling computes isochrones.
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?
Gives concrete usage context: translates costing modes into user questions ('how far can I walk in 15 minutes?'), names delivery coverage as an auto/truck use case, and frames exclude_polygons as a before/after scenario ('close this bridge and recompute reachability'). However, it never explicitly names sibling tools or states when to prefer route/matrix instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replan_routesAInspect
Re-plan a fleet part-way through its shift. Send the day back; nothing is stored. MapMap holds NO dispatch state — no plan, no vehicle position, no completion log — so a re-plan is not a delta against something we remember: you pass the ORIGINAL optimise_routes problem in full, plus progress (per vehicle: completed_stop_ids IN THE ORDER SERVED, an optional current_position, and unavailable: true for a breakdown or an end of hours) and/or changes (cancel_job_ids, add_jobs, add_shipments), and get a fresh plan for what is left. That costs bandwidth and buys the absence of a server-side plan that can go stale, leak, or fall out of step with the telematics platform that actually owns the truth — and it makes a re-plan reproducible: the same body always yields the same answer. Completed stops are LOCKED by construction: they are removed from the problem entirely and each vehicle starts from where it actually is, so the solver cannot move a stop that has already happened — a guarantee the solver cannot break, rather than a hint it is free to ignore. At least one progress entry or one change is required. Returns the same plan shape as optimise_routes for the REMAINING work, plus a replan block: the prefix locked per vehicle, where each re-plans from and how that was decided, stops released from a vehicle that can no longer serve them, tasks forced unassigned, and a note for every id that did not resolve. Read that block — a stop that vanished from the plan is named there rather than left for a dispatcher to notice at four in the afternoon; a cancelled id that matched nothing is reported there too rather than refused. Multi-trip vehicles cannot be re-planned: a completion does not say which trip it belongs to, so a problem whose vehicles declare reloads is refused with what to send instead. Billed on the remaining problem, not the original. Requires the MapMap gateway.
| Name | Required | Description | Default |
|---|---|---|---|
| jobs | No | Single-stop jobs (at least one job or shipment overall). | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; the travel-time matrix then respects dimensional and dangerous-goods restrictions, so the whole plan is truck-legal. | |
| changes | No | Changes to the work itself. Optional, on the same condition. | |
| costing | No | Costing model for the travel-time matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| progress | No | Per-vehicle progress. Optional, but at least one progress entry or one change is required — a re-plan that reports nothing new is the original problem. | |
| vehicles | Yes | The fleet (at least one vehicle, each with a start and/or end). | |
| emissions | No | The fleet's emission declaration, for UK clean-air / low-emission zone assessment. On its own it annotates: the response's `zones` block names every zone containing one of the problem's own locations and what this vehicle would pay there. With `avoid_zones` it also steers the internal travel-time matrix away from those zones, so the plan itself changes. | |
| shipments | No | Pickup+delivery pairs. | |
| avoid_zones | No | Keep the optimisation's travel-time matrix out of every zone the declared vehicle would be charged or banned in. Requires `emissions`. | |
| territories | No | Fleet territories: named polygons that bound which vehicle may serve which stop, referenced by `vehicles[].territory_ids`. These are request data — caller-drawn rounds, validated per call and never stored. Nothing to do with clean-air zones or with the offline map packages of the same word. | |
| relax_if_unassigned | No | Re-solve ONCE with these relaxations if the first solve leaves work unassigned, and say honestly which plan came back. At most one second solve, never beyond the caps you state, and the relaxed plan is returned only if it assigns MORE work than the first — giving away constraints for nothing is strictly worse than not giving them away. Breaks are never widened, nor are capacities, skills, territories or task caps: only time windows move, and only by the stated amounts. Bills as two solves when the second one runs. |
Output Schema
| Name | Required | Description |
|---|---|---|
| zones | No | Clean-air / low-emission zones touching the problem's own locations, and what the declared vehicle pays in each. Present only when `emissions` was declared. |
| replan | Yes | What the re-plan locked and why: the prefix held per vehicle, where each vehicle re-plans from and how that was decided, stops released from a vehicle that could no longer serve them, tasks forced unassigned, and a note for every id that did not resolve. Read it. A stop that vanished from the plan is named here rather than left for the dispatcher to notice at four in the afternoon. |
| routes | Yes | One optimised route per used vehicle. |
| profile | Yes | The matrix costing profile the plan was computed with ("auto", "truck", "bicycle", "pedestrian" or "motor_scooter"). |
| reloads | No | The multi-trip split: each vehicle's trips, their windows, the depot each returns to, and the stated approximation. Present only when a vehicle declared `reloads`. Read the `basis` inside it before quoting arrival times. The trip windows are fixed BEFORE the solve, so a lorry that tips early cannot lend the spare time to its next trip: stops can come back unassigned that a truly sequential model would have served. The plan is feasible, never optimistic — it cannot put a vehicle in two places at once — but it is not optimal. Re-plan after each tip through `replan_routes` for the tighter answer. |
| summary | Yes | Solution summary. |
| relaxation | No | The relaxation report: the caps requested, whether a second solve ran, whether ITS plan is the one returned, what was widened, and what is still unassigned. Present only when `relax_if_unassigned` was declared. Always read `second_solve` and `relaxed_plan_used` before telling anyone the day fits. A plan produced under relaxation has had promises moved, and the block is what says so. |
| unassigned | Yes | Tasks the solver could not assign to any vehicle. |
| territories | No | How the territories bound the plan: which vehicle was eligible for what, and any task no eligible vehicle existed for. Present only when `territories` was declared. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It transparently explains that nothing is stored server-side, that the call is reproducible, that completed stops are locked by construction, that multi-trip problems are refused, that billing is on the remaining problem, and that the MapMap gateway is required.
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 the tool is complex and no annotations or short schema can carry the needed context. It is front-loaded with the core purpose and major constraints, though the single-block prose style and some rhetorical flourishes add length without much structural aid.
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 an 11-parameter tool with a full output schema, the description is unusually complete. It covers prerequisites, input requirements, failure modes, response contents, limitations, and billing. An agent has everything needed to decide when to call it and how to construct a valid request.
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 100%, so the baseline is 3. The description adds meaningful cross-parameter semantics beyond the schema: the original `optimise_routes` problem must be passed in full, at least one progress entry or change is required, `completed_stop_ids` are a locked prefix, and vehicles declaring `reloads` cannot be re-planned.
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 action and resource: "Re-plan a fleet part-way through its shift." It clearly distinguishes this from `optimise_routes` by explaining that the original problem plus `progress` and/or `changes` is sent back and a fresh plan for remaining work is returned.
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 context and clear exclusions: at least one progress entry or change is required, multi-trip vehicles cannot be re-planned, and a re-plan reporting nothing new is essentially the original problem. It references `optimise_routes` as the source of the problem shape but does not explicitly name an alternative tool to use instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
report_map_issueAInspect
Report that the live world disagrees with the map — a closed road, a wrong or missing restriction, a bad speed limit, a missing road, a wrong one-way, or changed access. Use it when you observe the mismatch mid-task. Provide location {lat, lon}, a category (road_closed, wrong_restriction, wrong_speed_limit, missing_road, wrong_oneway, access_changed, other) and optionally a description, the OSM way_id and an evidence_url. This is a first-party observation: it is QUEUED for human/agent review and NEVER changes routing immediately or edits any map. Returns the queued report_id.
| Name | Required | Description | Default |
|---|---|---|---|
| way_id | No | The OSM way id the observation concerns, when the caller knows it. Optional — the report stands on its own as a first-party observation and is never tied to OSM data beyond this hint. | |
| category | Yes | What kind of mismatch this is. | |
| location | Yes | Where the mismatch was observed (WGS84 decimal degrees). | |
| description | No | Free-text detail of what was observed on the ground, e.g. "barrier across the lane, diversion signed via the B4009". Bounded length. | |
| evidence_url | No | A URL backing the observation (photo, notice, news item), when one exists. Bounded length. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | Always "queued": the report awaits human/agent review and changes nothing about routing immediately. |
| category | Yes | The category, echoed back as its snake_case wire tag. |
| report_id | Yes | The generated id of the queued report (cite it in follow-ups). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and delivers: it discloses that the action is queued for human/agent review, NEVER changes routing immediately, and NEVER edits any map. It also states it returns the queued report_id. This fully informs the agent of the asynchronous, non-mutating nature of the call, which is critical for a reporting 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 front-loaded with the purpose, then gives usage instructions, then behavioral caveats. It is a bit longer than strictly necessary but every sentence contributes (categories, parameters, non-mutating guarantee, return value). It is well-structured and not redundant with the schema.
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 has 5 parameters (2 required) and a non-trivial LatLon type, but the schema fully documents them. The description adds the essential behavioral context (queued, non-mutating) and the return value. It does not describe error cases or the exact shape of the response beyond report_id, but that is sufficient for an agent to call it correctly. Minor gap: it does not mention that the array form of location uses longitude-first, but the schema does.
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 100% – every parameter and enum has a description, so the schema already carries the semantic weight. The description merely restates the required fields and lists the category enum values, adding no new meaning. It even says 'Provide `location` {lat, lon}' while the schema also allows a GeoJSON [lon, lat] array, which could slightly mislead, but the schema clarifies it. Baseline 3 is appropriate.
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+resource: 'Report that the live world disagrees with the map' and enumerates concrete mismatch types (closed road, wrong restriction, etc.). It is immediately distinct from all sibling tools, which are routing/geo utilities, and no other tool on the list performs reporting. The purpose is unambiguous and scoped.
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 states when to use it: 'Use it when you observe the mismatch mid-task.' It does not name alternatives because none exist among siblings, but it does clarify the tool is for first-party observations and that reports are queued, implying it is not for immediate routing changes. The context is clear, though it lacks an explicit 'do not use when…' clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reverse_geocodeAInspect
Turn coordinates into the nearest places: addresses, POIs and localities with distance in metres. The inverse of geocode. Provide lat and lon; returns up to limit (default 5, max 10) results, nearest first, each with name, one-line label, lat/lon, type, address parts and distance_m, plus categories and a details object of display tags (opening_hours, website, phone, wikipedia, ...) on POI hits when the index carries them. Every result also carries bearing_deg and a spoken direction. Pass heading_deg (degrees clockwise from true north, 0 = north, 90 = east) and results are described from where the user stands — "ahead and slightly to your right, about 80 metres" — with a signed relative_bearing_deg (negative left, positive right); without a heading the phrasing falls back to cardinals ("north-east of you"), so this works with or without a compass. Add fov_deg to keep only what lies within that cone of the heading — it is the FULL width, so 90 keeps what lies within 45 degrees either side of dead ahead; anything dropped is counted in out_of_view. Prefer reading direction aloud over coordinates.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude in decimal degrees (−90 to 90). | |
| lon | Yes | Longitude in decimal degrees (−180 to 180). | |
| limit | No | Maximum number of results (1–10, default 5). The hosted first-party index answers at most 5 nearest hits per lookup. | |
| fov_deg | No | Field of view: the full width in degrees of a cone centred on `heading_deg`, outside which results are dropped — it is the FULL width, so 90 keeps only what lies within 45 degrees either side of dead ahead. Needs `heading_deg` — a cone has to point somewhere. The count of results removed is reported as `out_of_view`. | |
| heading_deg | No | Which way the user is facing, in degrees **clockwise from true north** (0 = north, 90 = east, 180 = south, 270 = west). Supply it and every result is also described from the user's point of view ("just ahead on your right"); omit it and results fall back to cardinal directions ("to the north-east"), so the tool works with or without a compass. |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes | Nearby places, nearest first. |
| out_of_view | No | How many otherwise-matching places were dropped for falling outside `fov_deg`. Non-zero means there are places near the user that are simply not in front of them — say so rather than reporting nothing nearby. Always 0 when no field of view was set. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure and exceeds it. It details the output structure (name, label, lat/lon, type, address parts, distance_m, categories, details object, bearing_deg, direction), dynamic behavior (heading-based relative_bearing_deg, FOV-based out_of_view count), and even advises to 'Prefer reading direction aloud over coordinates.' This is exceptionally transparent about how the tool behaves across different inputs.
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 well-structured and front-loaded with purpose, then logically flows into output details, heading behavior, FOV, and a recommendation. However, it repeats the 'FULL width' explanation of fov_deg that already exists verbatim the schema description, and it restates the default/max for limit that is also in the schema. While not wasteful, these redundancies could be trimmed without losing value. The density is justified by complexity but slightly over-lengthy.
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 5 parameters and rich output behavior, and the description covers everything an agent needs: input requirements, output field descriptions, edge cases (FOV without heading), fallback behavior (cardinals vs relative), and even a usability recommendation. The output schema exists but the description still explains return fields in detail, which is helpful. No gaps are evident 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?
Schema coverage is 100%, so the baseline is 3, but the description adds substantial semantic value beyond the schema. It explains the interplay between fov_deg and heading_deg (a cone must point somewhere), the full-width vs. half-width interpretation of fov_deg, the default/max for limit, and the meaning of signed relative_bearing_deg. It also clarifies that out_of_view reports dropped results, which is not in the schema property descriptions. This enriches parameter understanding significantly.
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: 'Turn coordinates into the nearest places: addresses, POIs and localities with distance in metres.' It explicitly frames itself as 'The inverse of geocode,' immediately distinguishing it from the sibling tool. This gives an agent a precise understanding of what it does and how it relates to geocode.
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 names geocode as the inverse, which guides when to use this tool. It also explains two usage modes (with or without heading_deg) and how that changes output phrasing. However, it does not mention any other sibling tools like nearby_places, nor does it state when NOT to use this tool. The inverse reference and mode explanations provide strong contextual guidance, but exclusions are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
routeAInspect
Compute a turn-by-turn route between origin and destination (optionally via waypoints). Costing "auto" = car, "truck" = lorry, "bicycle", "pedestrian" = walking, "motor_scooter" = moped. Pass truck {height_m, width_m, length_m, gross_weight_t, hazmat, tunnel_code} to apply dimensional limits and the ADR dangerous-goods tunnel matrix to the search; pedestrian {use_lit 0-1, type "wheelchair"|"blind", max_hiking_difficulty 1-6} for lit-street walking, accessibility and trail limits; bicycle {bicycle_type, use_roads 0-1, use_living_streets 0-1, avoid_bad_surfaces 0-1, use_hills 0-1} for quiet-ride and surface preferences. Returns distance (m), duration (s), maneuvers, polyline6 geometry and the ADR costing that was applied. Any of truck, auto, bicycle, pedestrian or motor_scooter routes may set rationale: true (opt-in, costs up to 1 + N extra routing calls) to learn which declared truck constraints or avoidance-side preferences (hills, surfaces, tolls, unlit streets, …) actually changed the route (rationale.avoided[], basis route_divergence — it proves a field was binding, it does not identify the physical restriction or feature, and no live traffic or incident data is ever attributed). ADR honesty: applied_adr.forbidden_tunnel_categories describes the LOAD, not the returned route, and applied_adr.tunnel_enforcement states the boundary: roads are excluded only where the routing graph records an ADR tunnel category, so an unchanged route is not a clearance. Set landmarks: true for turn instructions anchored to recognisable places — each manoeuvre that passes one gains a landmark_instruction like "Turn right just after the Shell garage" beside the engine's own street-name instruction, which is never replaced. Prefer reading it aloud: it is how a passenger gives directions. Nothing is named unless it is recognisable from the road, within 40 m of the junction and not tagged as closed, so many routes return none and a landmarks.annotated of 0 with no note means this route genuinely passes nothing recognisable. Needs the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY), whose place index does the lookup. Through the gateway each manoeuvre also carries the road it starts on: country, subdivision, ref (route numbers only), road_class, speed_limit_unit (mph or km/h, from the road's country), speed_limit_sign (vienna or mutcd), speed_limit_posted (the limit as the sign shows it, in the road's unit) and driving_side; each is absent when the map does not know it, never guessed. Optional exclude_polygons for what-if scenarios ("close this bridge and re-route"): an array of polygons, each an array of [lon, lat] pairs forming one ring — longitude FIRST — whose intersecting roads are excluded from the search. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored. Optional avoid and exclude name road features to keep off, and the difference between them is not cosmetic. avoid ("tolls", "highways", "ferries") is a PREFERENCE: it sets the costing's willingness to zero, and the engine's own reference says that is not guaranteed to avoid the feature — measured, avoiding tolls across the Dartford Crossing returns the same tolled route, because the untolled alternative is fifty kilometres further. exclude ("tolls", "highways", "ferries", "bridges", "tunnels") is a hard exclusion: it can answer NO ROUTE rather than a detour, and it depends on the routing engine's own hard-exclusion setting, which the engine does not report and this server cannot read — so it is requested, never promised. "tolls" and "highways" under avoid exist only on motorised costings; asking for one on a bicycle is refused rather than silently ignored. Whatever is applied comes back in avoidance, with the caveats — relay them, because "avoid tolls" read as a guarantee is the failure mode here. Each location also takes a kerbside approach: preferred_side "same" (alias "curb") stops on the door's side of the road, resolved against the locale's driving side — the left kerb in the UK, the right in Germany — with "opposite" and "either" (alias "unrestricted") for the rest. It is a snapping preference, not a manoeuvre guarantee, and it needs a coordinate genuinely offset from the road centreline; street_side_tolerance_m and street_side_max_distance_m bound the window in which it applies, and a pair leaving no window is refused rather than answered with the preference silently inert. Pass emissions {vehicle_category, fuel, euro_standard} for UK clean-air-zone assessment: the response's zones block then names every zone the route enters and what THIS vehicle pays there, with the publishing authority cited. Without it a zone can only be named, never priced. Needs the gateway, which holds the curated zone dataset; the whole dataset — every scheme, charge, boundary and provenance record — is readable at GET /v1/zones on the HTTP API when an agent needs to audit a figure or list zones without routing. Set scenic: true (auto costing only) to ask whether there is a prettier way. It is a PEER OFFER, never a substitution: the route in geometry_polyline6 is byte-for-byte what the same request returns without the flag, and the prettier way, when there is one, arrives beside it in scenic, with its own geometry in scenic.alternative_geometry_polyline6 and what it costs in scenic.spoken ("About seven minutes longer than the quick way"). EVERY OFFER STATES ITS REASON OR THERE IS NO OFFER: a route that scores well but cannot support a plain sentence is dropped rather than dressed up, so a scenic.reason of null means nothing here measured above the floor. That is an ANSWER, not a failure, and it is the one to relay. A REJECTION IS ALSO AN ANSWER: every candidate that lost says why in scenic.rejections[] (same_route, no_scenic_gain, not_scenic_enough, over_time_budget with the minutes it would have cost, nothing_to_say), so "no prettier way" is always attributable and raising the budget is an informed choice. It is a re-ranking of routes the engine already proposed, not a scenic search: a beautiful road the engine never offered was never considered, and scenic.caveats says so. Like rationale, IT COSTS EXTRA METERED COMPUTATIONS, at most two, which is why it is opt-in and never on by default. available: false with a note means this deployment could not look, which is not the same claim as nothing being there. Needs the gateway, whose basemap archive the scoring is measured against.
| Name | Required | Description | Default |
|---|---|---|---|
| avoid | No | Road features to avoid as a PREFERENCE. Rendered as the costing's willingness factor set to zero — a thumb on the scale, not a ban. The engine's own reference is explicit that a value of zero is not guaranteed to avoid the feature entirely, and it does not: asking to avoid tolls across the Dartford Crossing returns the same tolled route, because the untolled alternative is fifty kilometres further. Use `exclude` when you mean a ban. | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; when present, ADR dangerous-goods costing options are merged into the request. | |
| origin | Yes | Route origin. | |
| scenic | No | Ask whether there is a prettier way (default false, `auto` costing only). The route in `geometry_polyline6` is NEVER swapped: what comes back is a peer offer beside it, in `scenic`, carrying the plain sentence that justifies it. No sentence, no offer: a route that scores well but cannot support one is dropped rather than dressed up, and `scenic.reason` is then null, which is an answer. Every candidate that lost says why in `scenic.rejections[]` (`same_route`, `no_scenic_gain`, `not_scenic_enough`, `over_time_budget`, `nothing_to_say`), so "no prettier way" is always attributable. Opt-in because it costs: at most two extra metered route computations, the same billing shape as `rationale`. Needs the MapMap gateway, whose basemap archive the scoring is measured against. | |
| bicycle | No | Bicycle options (bicycle type, road/surface/hill preferences). Requires costing "bicycle". | |
| costing | No | Costing model: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| exclude | No | Road features to exclude outright, rendered as the costing's hard exclusion flag. Two things follow from that and both matter: a hard exclusion can return NO ROUTE rather than a detour (excluding tunnels on a Rotherhithe crossing has no answer), and the flags depend on the routing engine's `allow_hard_exclusions` setting, which the engine does not expose and nothing here can read — so this is never promised, only requested. | |
| emissions | No | The vehicle's emission declaration, for UK clean-air / low-emission zone assessment. Given, the response's `zones` block names every zone the route enters and what THIS vehicle pays there, with the publishing authority cited. Without it a zone can only be named, never priced. Needs the MapMap gateway, which holds the curated zone dataset; the full dataset is readable at `GET /v1/zones`. | |
| landmarks | No | Name landmarks in the turn instructions (default false): each manoeuvre that passes a recognisable place — a petrol station, a supermarket, a household-name chain — gains a `landmark_instruction` like "Turn right just after the Shell garage" beside the engine's own street-name instruction, which is never replaced. Nothing is named unless it is recognisable from the road, within 40 m of the junction and not tagged as closed, so many routes come back with none: a wrong landmark is worse than no landmark. Needs the MapMap gateway, whose place index does the lookup. | |
| rationale | No | Explain the route (default false): re-routes with each declared truck constraint (truck costing) or avoidance-side routing preference (auto, bicycle, pedestrian, motor_scooter) relaxed and reports the ones that actually changed the route as `rationale.avoided[]`. Opt-in — it costs up to 1 + N extra routing calls, one per declared field plus one combined probe, and it is billed for the ones it actually makes: at most 8 in total, typically fewer, and 1 when there is nothing to probe. Against the hosted gateway each probe is its own metered route call, which is exactly what `POST /route` with `rationale: true` charges for its own fan-out, so the two surfaces price the same explanation the same way. | |
| waypoints | No | Optional intermediate stops, visited in order between origin and destination. | |
| pedestrian | No | Pedestrian options (lit-street preference, wheelchair/blind type, hiking difficulty). Requires costing "pedestrian". | |
| destination | Yes | Route destination. | |
| exclude_polygons | No | Areas to avoid — scenario analysis ("close this bridge and re-route"): an array of polygons, each an array of `[lon, lat]` pairs forming one exterior ring (GeoJSON-style, longitude FIRST). Roads intersecting any ring are excluded from the search. Applies to the Valhalla engine; unsupported on the GraphHopper engine, where it is ignored. |
Output Schema
| Name | Required | Description |
|---|---|---|
| zones | No | Clean-air / low-emission zones this route enters and what the declared vehicle pays in each, with the publishing authority cited (only when `emissions` was declared). Passed through verbatim from the gateway's curated dataset — the same figures `GET /v1/zones` publishes, so a charge can always be audited back to its source. |
| scenic | No | The scenic peer offer (only when `scenic: true` was requested): whether there is a prettier way, the sentence that justifies it, what the detour costs, and why every candidate that lost lost. The route above is never swapped for it. |
| summary | Yes | One-line human-readable summary of the route. |
| avoidance | No | What `avoid`/`exclude` became, and the caveats that go with it (only when either list carried something). |
| landmarks | No | The landmark-annotation summary (only when `landmarks: true` was requested): how many manoeuvres gained a `landmark_instruction`, and a `note` when the per-route cap was hit or the deployment has no place index. A zero with no note means this route genuinely passes nothing recognisable. |
| maneuvers | Yes | Ordered turn-by-turn maneuvers across all legs. |
| rationale | No | Why the route goes this way (only when `rationale: true` was requested; computed for truck, auto, bicycle, pedestrian and motor_scooter costings). |
| distance_m | Yes | Total route distance in metres. |
| duration_s | Yes | Total estimated travel time in seconds. |
| applied_adr | No | The ADR costing merged into the request, or null when no truck profile was given. |
| geometry_polyline6 | Yes | Full route geometry as a Google encoded polyline with six digits of decimal precision (polyline6). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so exhaustively: gateway/auth requirements (GATEWAY_URL + GATEWAY_API_KEY), which flags incur extra metered route calls and their caps, the honest limits of `avoid` (Dartford Crossing example) vs `exclude`, ADR tunnel-flag caveats, and the distinction between 'no prettier way' and 'could not look'. This is unusually complete 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?
A single enormous prose block covering a dozen optional flags with no headers, bullets, or ordering by importance. Individual sentences are informative, but the structure forces the reader to parse a wall of text to find the core call, and much of the detail duplicates the schema.
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 14-parameter routing tool with a nested schema and an output schema, the description leaves nothing an agent would need uncovered: costing semantics, ADR honesty, zone pricing, scenic/rationale cost models, and engine-specific limitations (Valhalla vs GraphHopper). It is complete to the point of excess.
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 100%, and the schema's own $defs already document every parameter (TruckSpec, BicycleSpec, PreferredSideKind, etc.) in depth. The description largely restates that material, adding little semantic detail the schema lacks, so the baseline of 3 applies.
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+resource+scope: 'Compute a turn-by-turn route between origin and destination (optionally via waypoints).' An agent immediately knows this is the routing primitive, distinct from siblings like optimise_routes or reachable_area. It never names an alternative sibling explicitly, so it stops short of a 5.
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?
Rich conditional guidance: 'Use `exclude` when you mean a ban', 'scenic: true (auto costing only)', eligibility rules for avoid features, and repeated warnings about opt-in metered cost. However it gives no guidance on choosing this tool over routing-adjacent siblings (plan_ev_route, optimise_routes), so it lacks an explicit alternatives clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
route_observationsAInspect
What a journey PASSES, in sentences ready to be read aloud, each with its position along the route. The named rivers and canals it crosses, the road it runs on and for how far, the settlements it goes through, the protected landscapes it enters and how high the road climbs: the things a passenger who knew the area would say. NONE OF THIS IS IN A ROUTE: a route is a list of movements and a river crossing is not a movement, so do not try to read it out of route's answer. Give geometry_polyline6 straight from the route tool, plus optional units ("miles" default, or "kilometers"), min_gap_m and max_observations. Each observation carries at_m (WHERE it belongs (delivered anywhere else it is trivia, not an observation), a kind, a say sentence to relay verbatim, and a basis naming the map layer and tag the claim rests on. THE SILENCE BUDGET IS THE DESIGN: min_gap_m is a floor, not a target, and when a route yields more than max_observations the gap WIDENS on its own so the survivors stay spread over the whole journey rather than clustering where the map happened to be richest. Inside a window the rarer kind wins. So a short list on a long route is the budget working, not thin data. READ coverage BEFORE REPORTING AN EMPTY LIST: an empty observations with tiles_read of 0 means NO DATA WAS READ, which is not the same claim as quiet countryside, and uncovered_m says how much of the route could not be seen at all. Two things it will never say, deliberately: it never names a hill (a peak two kilometres away behind a ridge is named confidently and seen by nobody), and it never reads a junction number (an observation mistakable for an instruction is not safe to speak beside real guidance). A settlement is a labelled POINT, not a boundary, and offset_m publishes the distance behind the word "through". It is a query and it triggers nothing: no position is held and nothing is pushed. COSTS 10 UNITS a call, flat, whatever is asked for. Requires the MapMap gateway (GATEWAY_URL + GATEWAY_API_KEY), whose basemap archive and elevation model answer it; a deployment with no archive answers 501 and says so.
| Name | Required | Description | Default |
|---|---|---|---|
| units | No | Units for the spoken distances: `miles` (default) or `kilometers`. `kilometres` and `km` are accepted too. | |
| min_gap_m | No | Least distance along the route between two observations, metres (default 2000). A FLOOR, not a target: when the route holds more than `max_observations`, the gap widens past this on its own so the survivors stay spread over the whole journey. | |
| max_observations | No | Ceiling on how many observations come back, 1 to 200 (default 40). | |
| geometry_polyline6 | Yes | The route shape, precision-6 encoded: `geometry_polyline6` straight out of the `route` tool's answer. Nothing else is accepted: there is no origin/destination form, because this tool annotates a route somebody already chose rather than computing one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| caveat | Yes | The standing limits of the method, for relaying to users. |
| coverage | Yes | What the archive and the elevation model could and could not say: `tiles_read`, `tiles_missing`, `uncovered_m`, and the per-kind censuses. **Read it before reporting an empty list.** `tiles_read` of 0 means nothing was looked at, which is not the same claim as quiet countryside. |
| attribution | Yes | The licence notice for this answer. The obligation attaches to the product, not to each spoken sentence, so a visible or linked credit in the app satisfies it. |
| observations | Yes | The observations, in route order, already thinned to the silence budget. |
| route_length_m | Yes | The route's own length, metres, as walked. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and is exceptionally transparent. It discloses that the tool is a query and triggers nothing, costs 10 units flat, requires the MapMap gateway, and returns 501 without an archive. It also explains the silence-budget design, coverage semantics, deliberate exclusions like hills and junction numbers, and the meaning of `offset_m`.
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 almost every sentence adds operational value, from budget behavior to coverage caveats to error conditions. It is front-loaded with purpose and then structured into distinct behaviors. The rhetorical framing is slightly excessive but not redundant.
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 provenance, output observation fields, the meaning of empty results with `tiles_read` and `uncovered_m`, cost, authentication via gateway environment variables, and error behavior. For a tool with four parameters and no annotations, 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?
Schema coverage is 100%, so the baseline is 3. The description repeats the parameter names and emphasizes passing `geometry_polyline6` straight from the route tool, but it does not add meaning beyond what the schema already provides. It therefore meets the baseline but does not exceed it.
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 precisely what the tool produces: spoken-style observations of what a journey passes, including rivers, roads, settlements, landscapes, and elevation, each tagged with a position. It also distinguishes itself from `route` by warning that none of this information is present in a route's movement list.
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: this tool annotates an already-chosen route, and `geometry_polyline6` must come directly from the `route` tool. It also gives an explicit when-not by saying 'a route is a list of movements and a river crossing is not a movement, so do not try to read it out of route's answer.' However, it does not explicitly name or compare alternatives such as `search_along_route`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_along_routeAInspect
Find places (POIs) along a route with the REAL extra travel time of stopping at each — never a straight-line guess. Provide origin + destination (a route is computed) or an existing route's geometry_polyline6, plus a free-text query ("coffee", "EV charger", "truck stop") and max_detour_minutes (default 10). For a category intent ("fuel", "EV charger", "coffee") pass category instead of relying on words alone: it takes the same vocabulary as nearby_places (lowercased OSM tag values such as "fuel", "cafe", "charging_station", "parking", "pharmacy"), and common colloquial phrases are normalised server-side ("petrol station" and "gas station" to fuel, "coffee" to cafe, "EV charger" to charging_station). query alone also promotes a pure category phrase to the same browse, so "fuel" finds fuel stations rather than places whose NAME starts "Ful"; anything else stays free-text name matching. When a browse ran, the response echoes the tokens used in matched_categories. Candidates near the route corridor are priced through the routing engine with your costing: detour = (origin→place) + (place→destination) − (origin→destination). Costing "auto", "truck" (with a truck profile the detours respect dimensional/ADR restrictions), "bicycle", "pedestrian" or "motor_scooter". Returns results sorted by detour with detour_minutes, detour_km, along_route_position (0-1) and off_route_m; at most 25 candidates are priced per call (candidate_cap).
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Free-text POI query, e.g. "coffee", "EV charger", "truck stop". | |
| truck | No | Truck profile (dimensions + ADR declaration). Requires costing "truck"; the detours then respect dimensional/ADR restrictions. | |
| origin | No | Route origin (with `destination`, when no geometry is given). | |
| costing | No | Costing model for the route and detour matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
| category | No | Explicit place category ("fuel", "cafe", "charging_station" — same vocabulary as nearby_places). Colloquial phrases are normalised server-side; prefer this over query for category intents. | |
| destination | No | Route destination. | |
| max_results | No | Maximum results (default 5, at most 25). | |
| geometry_polyline6 | No | An existing route geometry as an encoded polyline6 (the `route` tool's `geometry_polyline6`). Provide either this or `origin` + `destination`, not both. | |
| max_detour_minutes | No | Largest acceptable detour in minutes (default 10, at most 120). |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | The query as interpreted. |
| costing | Yes | The costing the detours were priced with. |
| results | Yes | Places within the detour budget, cheapest detour first. |
| candidate_cap | Yes | The matrix fan-out cap in force. |
| route_length_m | Yes | Length of the route geometry in metres. |
| fuel_attribution | No | Attribution string for fuel-price data sources, present only when at least one returned result carries `fuel_prices` (gateway-preferred mode with `SN_FUEL_PRICES` configured; see [`AlongRouteHit`]). |
| route_distance_m | No | Direct origin→destination distance in metres. |
| route_duration_s | No | Direct origin→destination travel time in seconds (same estimator as the detour legs), when routable. |
| candidates_costed | Yes | Candidates actually priced through the engine (fan-out is capped at `candidate_cap` nearest-to-route). |
| matched_categories | No | The normalised category tokens the candidates were browsed by, present only when a category browse actually ran (an explicit `category`, or a query the server promoted to one). Absent means free-text name matching answered the call, so a caller can tell how its words were understood rather than inferring it from the results. |
| max_detour_minutes | Yes | The detour budget applied, minutes. |
| candidates_considered | Yes | Candidates found near the corridor before pricing. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the behavioral burden and does so thoroughly. It discloses the exact detour formula, server-side normalisation of colloquial phrases, the browse-vs-name-matching distinction, costing-specific behavior for truck profiles, sorting by detour, result cap at 25 candidates, and the fields returned. This is far more than a typical tool description and leaves little hidden 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 long, but every sentence carries operational value: input alternatives, query/category semantics, costing behavior, and output shape. It is front-loaded with the core value proposition and then logically layers usage details, with examples and parentheticals earning their place. No filler or tautology.
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 9 parameters, no annotations, and significant behavioral nuance, the description is remarkably complete. It covers route input modes, query semantics, costing and truck restrictions, defaults, output fields, sorting, and limits. The existence of an output schema means return-value documentation is covered elsewhere, and nothing needed for correct 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 100%, but the description adds substantial meaning beyond the schema: how `query` and `category` interact, what 'fuel' would otherwise match by name, how detour is computed, what costing options imply, and the candidate_cap pricing limit. It transforms the parameters from field definitions into a usable mental model of the tool's 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 description opens with a specific verb and resource: 'Find places (POIs) along a route' and immediately states the key differentiator: real extra travel time rather than straight-line distance. It clearly identifies what the tool computes, how route context is supplied, and what kind of results come back, making it easy to distinguish from nearby_places or route-only 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 gives explicit usage instructions: provide origin+destination OR geometry_polyline6, not both; prefer `category` over `query` for category intents; and explains the query-vs-category behavior with concrete examples. It even notes that category uses the same vocabulary as `nearby_places` and that pure category phrases in `query` are promoted to browse, giving clear decision guidance without needing to open the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_layer_paintAInspect
Set one MapLibre paint property on one skeleton layer of a hosted style (e.g. layer_id "road-major", property "line-width", value 4 or an expression array) and publish the result as a new immutable style version. Layer ids come from list_style_layers. Returns the new version and style URL.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | The paint value (any MapLibre-valid JSON: number, colour string or expression array). | |
| layer_id | Yes | Skeleton layer id, e.g. "road-major". Call `list_style_layers` for the accepted ids. | |
| property | Yes | MapLibre paint property name, e.g. "line-width" or "fill-color". | |
| style_id | Yes | Hosted style id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| version | Yes | The newly published version. |
| style_id | Yes | Hosted style id. |
| style_url | Yes | Immutable URL of the compiled style at this version. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the burden of behavioral transparency. It discloses that the operation is non-destructive in effect by publishing 'a new immutable style version', and it states the returned artifacts ('new version and style URL'). It does not mention permissions or failure modes, but the core side-effect is clearly communicated.
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 sentences deliver the verb, target, scope, example, prerequisite id source, and return value with no filler. The most important information is front-loaded, and every phrase 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 functionally complete: it states the operation, target, examples, where layer ids come from, and what is returned; an output schema handles return shape. It could explicitly mention set_palette as the multi-property alternative for full sibling differentiation, but the gap is minor.
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 already describes all four parameters in detail, including value types and examples. The description adds a concrete example ('road-major', 'line-width', '4') and reminds the agent that expressions are valid, but this largely mirrors the schema's existing documentation. With 100% schema coverage, the description's added semantic value is modest.
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 names a precise operation: 'Set one MapLibre paint property on one skeleton layer of a hosted style', immediately clarifying scope and context. It also explains the outcome ('publish the result as a new immutable style version') and explicitly contrasts this with related styling tools by using 'one property' and 'one skeleton layer'.
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 establishes when to use this tool: when you need to change a single paint property on a layer, and it tells the agent where to get valid layer ids ('Layer ids come from list_style_layers'). It does not explicitly contrast with set_palette or state when not to use it, but the single-layer/single-property framing is clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_paletteAInspect
Recolour one or more palette slots of a hosted style (e.g. {"water": "#0b2038", "roadMajor": "#8a6d3b"}) and publish the result as a new immutable style version. Slot names come from list_style_layers; colours are CSS (#rgb/#rrggbb/#rrggbbaa/rgb()/hsl()). Returns the new version and style URL.
| Name | Required | Description | Default |
|---|---|---|---|
| colours | Yes | Palette overrides: slot name → CSS colour (e.g. {"water": "#0b2038"}). Call `list_style_layers` for the slot names. | |
| style_id | Yes | Hosted style id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| version | Yes | The newly published version. |
| style_id | Yes | Hosted style id. |
| style_url | Yes | Immutable URL of the compiled style at this version. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals that this operation publishes a new immutable style version, which implies the existing style version is not mutated, and it states the return value. It could additionally mention side effects like publication visibility, but the core behavior is clear.
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 a single dense sentence that front-loads the action, includes a concrete example, covers input sources and colour syntax, and states the return value. There is no fluff or repetition of schema 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?
The description covers what the tool does, how to find slot names, allowed colour formats, and the return value. Since an output schema exists, detailed return documentation is unnecessary. A brief note drawing the boundary against set_layer_paint would make it fully complete, but 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?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by enumerating accepted CSS colour formats (#rgb, #rrggbb, #rrggbbaa, rgb(), hsl()) and providing a concrete example of the colours object. This helps the agent construct valid parameter values.
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 action ('Recolour one or more palette slots'), a specific resource ('hosted style'), and a distinctive outcome ('publish the result as a new immutable style version'). It clearly separates this from siblings like set_layer_paint by focusing on palette slots rather than layer paint properties.
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 operational context: it tells the agent to obtain slot names from list_style_layers and explains how colours should be formatted. It does not explicitly compare against siblings such as set_layer_paint or create_style, so exclusion guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_temporary_closureAInspect
OPERATOR WRITE, ADMIN ONLY. Asserts a short-lived closure (assert: {kind: closed}) or speed ({kind: speed_override, speed_kph}, 1 to 120) on named OSM way_ids (1 to 20) and direction (forward, backward or both, default both), for ttl_secs (60 to 86400), with a reason and an optional evidence_url. The record expires on its own, ranks below official closures and is logged with the reason. NEVER CALL THIS WITHOUT A PERSON'S EXPLICIT APPROVAL OF THIS EXACT CLOSURE IN THIS CONVERSATION: draft it, show it, stop, and call it only after a yes. Available only where the operator runs sn-mcp locally with SN_CAMERA_INCIDENTS_ENABLED=true and SN_ADMIN_TOKEN set; everywhere else it refuses and says why. Whether a live traffic writer applies it is reported in applied_by_live_writer; false means the record is stored but no road changes.
| Name | Required | Description | Default |
|---|---|---|---|
| assert | Yes | `closed` or a speed in km/h (1..=120). | |
| reason | Yes | Why, for the audit log and the incidents endpoint note. | |
| way_ids | Yes | OSM way ids to assert on; at most 20. | |
| ttl_secs | Yes | Lifetime, seconds, 60..=86400. | |
| direction | No | Carriageway, default `both`. | both |
| evidence_url | No | Evidence link, if any. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The override record id written. |
| end | Yes | Lifts at, RFC 3339. |
| source | Yes | Always `ops-admin`: the static admin token carries no key id. |
| applied_by_live_writer | Yes | Whether a live writer is armed to apply it on this deployment. A record written where no writer runs is honest about it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does: it discloses the record self-expires, ranks below official closures, is logged with the reason, is admin-only, has environment prerequisites, refuses with an explanation when unavailable, and reports via applied_by_live_writer whether a live writer actually applied it (false = stored but no road change).
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?
Dense but front-loaded with the highest-stakes information first (OPERATOR WRITE, ADMIN ONLY) followed by the never-call-without-approval warning. Every clause serves a purpose for a high-risk mutation tool, though the sentence is long and backtick-heavy.
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?
An output schema exists, so return values needn't be enumerated, yet the description still explains the key output field applied_by_live_writer. Prerequisites, refusal behavior, expiry semantics, and ranking are all covered, leaving nothing an agent needs in order to call 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 100%, so the baseline is 3. The description restates constraints already in the schema (1-20 way_ids, 60-86400 ttl, 1-120 speed, default direction both, optional evidence_url) and the reason's audit-log purpose is also already in the schema, so it adds little beyond what structured fields 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?
States a precise verb+resource: asserts a short-lived closure or speed override on named OSM way_ids, with the exact assertion kinds, ttl, and direction scope. No sibling tool in the list does temporary closures, so the agent can distinguish it immediately.
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?
Explicit when/when-not: it must never be called without a person's explicit approval of the exact closure in the conversation, with a prescribed draft-show-stop-confirm flow. It also states it is only available where sn-mcp runs locally with SN_CAMERA_INCIDENTS_ENABLED=true and SN_ADMIN_TOKEN set, and that it refuses elsewhere and says why.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_integration_retroAInspect
Send MapMap a structured integration retro (problems, gotchas, wins, docs gaps). Call at most once, after your MapMap integration works or you stop trying, and only if the developer has approved sending feedback to MapMap. Sends ONLY the structured fields in this schema to MapMap: there is no field for a transcript, a prompt, source code, file contents or coordinates. The free-text fields are short and capped, but they are still free text: do NOT paste code, credentials, customer names or personal data into them. Provide what_built (required), problems [{area: sdk|api|mcp|docs|billing|self-host|other, description, workaround_found}], gotchas, wins, docs_gaps, and optionally agent_name and sdk_version.
| Name | Required | Description | Default |
|---|---|---|---|
| wins | No | What went well (at most 20 entries × 500 bytes). | |
| gotchas | No | Surprises/traps worth documenting (at most 20 entries × 500 bytes). | |
| problems | No | Problems hit during the integration (at most 20). | |
| docs_gaps | No | Documentation gaps hit (at most 20 entries × 500 bytes). | |
| agent_name | No | The submitting agent's name, e.g. "Claude Code" (at most 100 bytes). | |
| what_built | Yes | What was built with MapMap, in one or two sentences (required, at most 500 bytes). | |
| sdk_version | No | MapMap SDK version integrated against, when known (at most 50 bytes). |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | `received` when the gateway stored it; `queued` when it was appended to the local review queue. |
| message | Yes | A short, honest sentence for the agent saying where the retro landed — sent to MapMap, or held in this server's local queue. |
| delivery | Yes | How it was delivered: `gateway` or `local-queue`. |
| retro_id | Yes | Id of the stored retro (gateway id, or the local queue id). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so: it discloses what is transmitted ('ONLY the structured fields in this schema... no field for a transcript, a prompt, source code, file contents or coordinates'), the 'at most once' call-limit behavior, the consent prerequisite, and the field-size caps. These are exactly the traits an agent cannot derive from structured fields.
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?
Purpose and the call-gating rule are front-loaded, and the privacy constraints follow in a logical order. The middle sentence is dense and repeats cap information already in the schema, and enumerating the field list at the end is partly redundant, costing it 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 mutation/feedback tool with no annotations but a full output schema, the description covers purpose, invocation limits, consent requirements, data-exclusion rules and a field inventory. Nothing an agent needs in order to invoke it safely and 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 description coverage is 100% and the schema already documents every parameter, including the problem 'area' enum and per-field byte caps, so the description's parameter summary is largely redundant. It correctly flags `what_built` as required, but adds no syntax or meaning beyond the schema, which is the baseline-3 case.
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 ('Send MapMap a structured integration retro') and enumerates the content it carries (problems, gotchas, wins, docs gaps), so the agent knows exactly what this tool does. It does not, however, differentiate itself from the semantically adjacent sibling report_map_issue, so a 4 rather than 5.
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?
Gives explicit timing and gating conditions: 'Call at most once, after your MapMap integration works or you stop trying, and only if the developer has approved sending feedback to MapMap.' This is a complete when/when-not rule with no inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_optimise_jobAInspect
Submit a problem too large to solve inside one request to the asynchronous lane, and get a job id back. Set kind to "optimise", "replan" or "matrix", and pass problem in EXACTLY the shape the matching synchronous tool takes — optimise_routes input, replan_routes input, or matrix input. Moving a working synchronous call onto this lane changes nothing but which tool you call it with. A field that tool's input does not have is REFUSED by name rather than dropped: the HTTP API accepts some the MCP tools have not surfaced yet, and a job queued without a constraint you asked for is worse than one that was never queued. The ceilings are far higher here because there is no request to hold open: 2,000 unique locations for an optimisation or re-plan against the synchronous 200, and 40,000 matrix elements against 10,000 (a deployment may set either lower, in which case its own refusal is the authority). A re-plan is counted on the REMAINING problem, after completed stops are removed, so a shift well through its day may fit where the morning's would not. This answers 202-and-a-job-id, NOT a plan: the job is queued and a worker picks it up. Poll get_job with the returned id until it says the status is terminal, then read the result. Polling is free — the gateway meters this submission, not the reads. Units are charged on submission and handed back in full if the job fails. The optional webhook_url (https only) posts a SIGNED notification when the job finishes and is for a human wiring infrastructure that must react without a process watching; it carries a pointer, never the result, and needs a webhook signing secret on the key. An agent that can poll should not use it. Requires the MapMap gateway.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Which problem this is. It selects both the body shape below and the ceiling the submission is judged against. | |
| problem | Yes | The problem itself, in exactly the shape the synchronous tool takes — `optimise_routes` input for `optimise`, `replan_routes` input for `replan`, `matrix` input for `matrix`. Moving a working synchronous call onto this lane changes nothing but the tool you call it with. | |
| webhook_url | No | Optional HTTPS URL to POST a signed `{job_id, kind, status, result_url}` notification to when the job finishes. The RESULT is never pushed — the notification says where to fetch it. Requires a webhook signing secret on the key; without one the submission is refused rather than delivered unsigned. An agent that can poll does not need this: polling with `get_job` is free. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | The job id. Pass it to `get_job` to poll. |
| kind | Yes | `optimise`, `replan` or `matrix`. |
| next | Yes | What to do next, in one sentence: poll `get_job`, and how often is reasonable. |
| status | Yes | Always `queued` — no worker has looked at it yet. |
| result_url | Yes | The HTTP URL this job (and its result) can be fetched from. The same URL a webhook carries. `get_job` is the tool that reads it. |
| units_charged | Yes | Quota units this submission drew. Charged now, handed back in full if the job fails. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the burden and does so richly. It discloses that the tool returns a 202-and-job-id, not a plan; that jobs are queued and processed asynchronously; that unknown fields are refused by name rather than dropped; that polling is free; that units are charged on submission and refunded on failure; and that webhook_url delivers a signed pointer, never the result. These are substantial behavioral traits beyond the schema.
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 conveys a distinct and necessary fact: purpose, parameter mapping, refusal behavior, ceilings, re-plan counting, response semantics, polling cost, billing, and webhook guidance. It is front-loaded with the core purpose and then structured to cover the tool's edge cases. 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?
For a complex asynchronous submission tool with no annotations, the description is remarkably complete. It covers purpose, alternatives, parameter semantics, error behavior, quotas, billing, result retrieval via get_job, and optional webhook usage. The output schema may handle return value structure, but the description provides all contextual and operational knowledge 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 100%, so the baseline is 3, but the description adds significant meaning. It explains the kind values map to specific synchronous input shapes, elaborates on the problem parameter with the exact-shape requirement and refusal behavior, and details webhook_url semantics including HTTPS-only, signed notifications, pointer-not-result, and the agent-should-poll caveat. This goes well beyond the schema descriptions.
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 a specific verb and resource: 'Submit a problem too large to solve inside one request to the asynchronous lane, and get a job id back.' It clearly differentiates this tool from synchronous siblings like optimise_routes and replan_routes, and from get_job which polls the result. The purpose is unambiguous and distinct.
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 states when to use the tool: for problems too large for a single synchronous request. It names the matching synchronous tools and says moving a working synchronous call changes nothing but the tool. It also gives a clear exclusion for webhook_url: 'An agent that can poll should not use it.' This is explicit when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_geodataAInspect
Check whether a dataset's DECLARED coordinate reference system actually describes its own coordinates, before you draw it on a map. Catches the failures that are otherwise silent: swapped lat/lon axes, degrees labelled as metres, and Web Mercator or another projection mislabelled with a UTM or national-grid code. Pass the declared CRS (e.g. "EPSG:4326") and a sample of the raw coordinates as {x, y} in the dataset's OWN units — deliberately not named lon/lat, because whether they are degrees is the question. Returns a verdict (consistent / suspect / impossible), what is wrong in plain language, and where the numbers actually point when read another way. This is a sanity check, not a reprojection: it never transforms coordinates. Local computation: no network call, no quota.
| Name | Required | Description | Default |
|---|---|---|---|
| coordinates | Yes | A sample of the dataset's coordinates. A few dozen is plenty; the check is about ranges and spans, not volume. | |
| declared_crs | Yes | The CRS the dataset claims, e.g. `"EPSG:4326"`, `"EPSG:32610"`, `"EPSG:3857"`, `"EPSG:27700"`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| extent | Yes | Observed extent of the sample, in the dataset's own units. |
| verdict | Yes | |
| problems | Yes | Plain-language findings, most important first. Empty when consistent. |
| suggestions | Yes | What the numbers look like, when they do not match the declaration. |
| interpreted_as | Yes | The CRS family the declaration was understood as. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the behavioral burden and does so thoroughly. It discloses the return shape (verdict, plain-language problem, alternative interpretation), states that no coordinate transformation occurs, and guarantees local computation with no network call or quota. This gives an agent a complete picture of side effects and non-effects.
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 earns its place: purpose, failure modes, input prescription, output summary, and capability boundary. The description is dense but not bloated, and the most decision-relevant information is 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?
For a 2-parameter validation tool with a full output schema present, the description covers what matters: what the tool checks, why it exists, what inputs to provide, what outputs to expect, and what it will not do. An agent has everything needed to select and invoke it correctly without additional context.
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 already covers 100% of parameters, so the baseline is 3; the description adds real value beyond that by explaining why parameters are named x/y rather than lon/lat, giving concrete EPSG examples, and advising that 'a few dozen is plenty'. This helps the agent construct sensible inputs without restating schema content.
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 gives a precise verb-check, a specific resource (a dataset's declared CRS against its own coordinates), and a concrete use moment ('before you draw it on a map'). It also names example failure modes (swapped axes, degrees labelled as metres), making the tool's job unmistakable and distinct from the many geo 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 it ('before you draw it on a map') and explicitly excludes a major misuse case ('a sanity check, not a reprojection: it never transforms coordinates'). It does not name an alternative tool for reprojection or other coordinate operations, so it stops just short of explicit alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_placesAInspect
Check whether places (and itineraries) an AI mentioned are real, findable and physically possible. Pass structured claims (reliable, and the only path that supports itinerary feasibility) or free text (best-effort quoted-phrase extraction). Each claim resolves to exactly one of three verdicts, never a boolean: "verified" (matched a real place, with its stable id and the source/date of the evidence), "contradicted" (a specific, dated, sourced fact rules it out — currently only an itinerary leg the routing engine proves cannot be driven in the stated time, with the computed travel time as evidence), or "unverified" (no evidence either way). This tool NEVER asserts that a named real business does not exist or has closed — that would be a defamation risk with no upside; a missing match is always "unverified". Claims sharing increasing sequence values and both carrying claimed_time (ISO 8601) form itinerary legs checked for feasibility via matrix, catching e.g. "breakfast in Bath, 10am meeting in Edinburgh". Max 20 claims per request. The response's summary field is a concise plain-text digest — also returned as this tool result's text content — so clients that drop structured/non-text content blocks still see the verdicts.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Free text to extract place claims from (best-effort heuristic: quoted phrases and Title Case runs after "at/in/near/to/from/ visiting" — not NLP or an LLM call, and it does not attempt itinerary feasibility since there are no explicit times to anchor legs to). Mutually exclusive with `claims`. Max 8,000 characters. | |
| claims | No | Structured claims — the reliable path, and the only path that supports itinerary feasibility. Mutually exclusive with `text`. Max 20 per request. | |
| costing | No | Costing for feasibility legs: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter". | auto |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes | |
| summary | Yes | Always present: a concise plain-text summary alongside the structured `results` — several MCP clients (notably ChatGPT connectors) drop non-text content blocks, so this must stand on its own. This same string is also returned as the tool call's text content block, not only inside the structured JSON. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and exceeds it: it explains the non-boolean verdicts, the defamation-avoidance rule, how sequence/claimed_time trigger routing-based contradiction checks, the 20-claim limit, and that `summary` is surfaced as text content. This is exemplary disclosure for a tool with this complexity.
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?
Though long, every sentence earns its place: purpose, mode selection, verdict semantics, a crucial behavioral caveat, itinerary feasibility, request limits, and output-format note. The structure front-loads the primary action and then layers necessary detail without fluff.
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 three parameters, no annotations, and real behavioral nuance, the description is complete: it covers input-mode tradeoffs, verdict semantics, constraints, edge-case behavior, and response-format quirks. The presence of an output schema means the description does not need to enumerate return fields, and nothing an agent needs 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 100%, so the baseline is 3. The description adds real semantic value beyond the schema by labeling `claims` as the reliable path, `text` as best-effort heuristic extraction, and explaining why `sequence` and `claimed_time` together enable feasibility checks. It does not merely repeat schema text.
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: checking whether places and itineraries an AI mentioned are real, findable, and physically possible. The three-verdict model (verified/contradicted/unverified) further sharpens what the tool does and clearly distinguishes it from geocoding or place-search siblings.
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 tells agents when to use structured `claims` versus free `text`, and notes that only `claims` supports itinerary feasibility. It does not explicitly name sibling alternatives like `geocode` or `nearby_places` as things to use instead, but the usage context is clear enough for a unique-purpose tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
- Added
camera_incidents - Added
set_temporary_closure
1 tool update
- Changed
route8 fields changed- added
Output schema / $defs / ManeuverOut / properties / countryAdded value: +{ + "description": "ISO 3166-1 alpha-2 country of the road the manoeuvre starts on, e.g.\n`\"GB\"`. This and the road fields below come from the MapMap gateway's\nroad walk: present when the route was computed through the gateway\n(GATEWAY_URL + GATEWAY_API_KEY) and the map knows the road, absent\notherwise. Never inferred.", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / driving_sideAdded value: +{ + "description": "The side of the road traffic keeps to there, `\"left\"` or `\"right\"`;\npresent only when the road's country is known.", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / refAdded value: +{ + "description": "Route numbers of that road (`\"; \"` separated, e.g. `\"A27\"` or\n`\"I 5; US 101\"`); absent when it carries none, never read from a\nstreet name.", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / road_classAdded value: +{ + "description": "Engine road class of that road (`motorway`, `trunk`, `primary`,\n`secondary`, `tertiary`, `unclassified`, `residential`,\n`service_other`).", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / speed_limit_postedAdded value: +{ + "description": "The posted limit as the sign shows it, in the road's own unit:\n`{\"type\":\"known\",\"value\":30,\"unit\":\"mph\"}` (plus `\"national\":true`\nfor a national limit), `{\"type\":\"unlimited\"}` or `{\"type\":\"unknown\"}`.\nRead from the road the manoeuvre mostly travels along." +} - added
Output schema / $defs / ManeuverOut / properties / speed_limit_signAdded value: +{ + "description": "The speed-limit sign family there: `\"vienna\"` (roundel) or\n`\"mutcd\"` (US and Canadian rectangle).", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / speed_limit_unitAdded value: +{ + "description": "The unit speed limits are posted in on that road, `\"mph\"` or\n`\"km/h\"`, from its country (never from the request's units).", + "type": [ + "string", + "null" + ] +} - added
Output schema / $defs / ManeuverOut / properties / subdivisionAdded value: +{ + "description": "ISO 3166-2 subdivision of that road where the map carries one, e.g.\n`\"GB-ENG\"` or `\"US-CA\"`.", + "type": [ + "string", + "null" + ] +}
28 tool updates
- Changed
cheapest_charging_along_route5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
cheapest_fuel_along_route5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
check_clearance_on_route5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
elevation5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_area5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_bbox5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_bearing5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_centroid10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_destination10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_distance5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_length5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_nearest_point_on_line10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_point_in_polygon5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geo_simplify10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
geocode5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
get_job1 field changed- changed
Output schema / properties / result / descriptionPrevious value: -"The answer, inline, once `status` is `succeeded` — exactly the body\nthe synchronous tool would have returned."New value: +"The answer, inline, once `status` is `succeeded` — exactly the body\nthe synchronous tool would have returned. A matrix job answers\n`durations_s` and `distances_m`, as the `matrix` tool does; it also\nstill carries the same numbers as `durations` and `distances`, which\nare DEPRECATED and will be removed in a future release."
- Changed
match_trace5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
matrix5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
optimise_routes10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
order_stops10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
plan_day10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
plan_errands5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
plan_ev_route5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
reachable_area5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
replan_routes10 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
report_map_issue5 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
route9 fields changed- added
Input schema / $defs / RouteLocation / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - removed
Input schema / $defs / RouteLocation / properties / latRemoved value: -{ - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" -} - removed
Input schema / $defs / RouteLocation / properties / lonRemoved value: -{ - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" -} - removed
Input schema / $defs / RouteLocation / requiredRemoved value: -[ - "lat", - "lon" -] - added
Output schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Output schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Output schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Output schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Output schema / $defs / LatLon / typeRemoved value: -"object"
- Changed
search_along_route6 fields changed- added
Input schema / $defs / LatLon / anyOfAdded value: +[ + { + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" + }, + { + "description": "GeoJSON position [lon, lat]: longitude FIRST.", + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + } +] - changed
Input schema / $defs / LatLon / descriptionPrevious value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server." - removed
Input schema / $defs / LatLon / propertiesRemoved value: -{ - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } -} - removed
Input schema / $defs / LatLon / requiredRemoved value: -[ - "lat", - "lon" -] - removed
Input schema / $defs / LatLon / typeRemoved value: -"object" - added
Input schema / additionalPropertiesAdded value: +false
3 tool updates
- Added
heritage_narration - Changed
route4 fields changed- added
Input schema / properties / scenicAdded value: +{ + "description": "Ask whether there is a prettier way (default false, `auto`\ncosting only). The route in `geometry_polyline6` is NEVER swapped:\nwhat comes back is a peer offer beside it, in `scenic`, carrying\nthe plain sentence that justifies it. No sentence, no offer: a\nroute that scores well but cannot support one is dropped rather\nthan dressed up, and `scenic.reason` is then null, which is an\nanswer. Every candidate that lost says why in\n`scenic.rejections[]` (`same_route`, `no_scenic_gain`,\n`not_scenic_enough`, `over_time_budget`, `nothing_to_say`), so\n\"no prettier way\" is always attributable. Opt-in because it\ncosts: at most two extra metered route computations, the same\nbilling shape as `rationale`. Needs the MapMap gateway, whose\nbasemap archive the scoring is measured against.", + "type": [ + "boolean", + "null" + ] +} - added
Output schema / $defs / ScenicOfferAdded value: +{ + "description": "The scenic assessment beside a route: a peer offer, never a\nsubstitution.\n\nThe fields here are the ones a client must actually read before\nsaying anything. `block` keeps the gateway's whole answer beside them\nso a figure can always be audited back to the source that produced\nit, rather than to this mapping.", + "properties": { + "alternative_geometry_polyline6": { + "description": "The scenic route's own geometry, polyline6, when there is one to\noffer. `geometry_polyline6` on the route itself is byte-for-byte\nwhat the same request returns without the flag.", + "type": [ + "string", + "null" + ] + }, + "available": { + "description": "Whether scenery could be assessed at all on this deployment. When\nfalse, `note` says why and nothing below was measured: that is\n\"we could not look\", never \"there is nothing there\".", + "type": "boolean" + }, + "block": { + "description": "The gateway's whole `scenic` block, verbatim: candidates, feature\nshares, tile coverage, metering and budget." + }, + "caveats": { + "description": "The standing limits of the method, for relaying to users.", + "type": "string" + }, + "chosen": { + "description": "Which route the assessment would offer: `\"fastest\"` (the quick way\nis already the pretty one, or nothing beat it) or `\"scenic\"`.", + "type": "string" + }, + "extra_time_s": { + "description": "How much longer the offered route takes than the fastest one,\nseconds, and the sentence for it. Absent when nothing was offered.", + "format": "double", + "type": [ + "number", + "null" + ] + }, + "note": { + "description": "Why no assessment ran (only when `available` is false).", + "type": [ + "string", + "null" + ] + }, + "reason": { + "description": "The plain, speakable sentence behind the offer. **Null is an\nanswer**: nothing on this corridor measured above the floor, so\nno claim is made rather than one being invented.", + "type": [ + "string", + "null" + ] + }, + "rejections": { + "description": "Why each candidate that lost lost. Empty when none did. Relay it:\nit is what makes \"no prettier way\" an attributable answer instead\nof a shrug.", + "items": { + "$ref": "#/$defs/ScenicRejection" + }, + "type": "array" + }, + "spoken": { + "description": "The trade phrased for speech, e.g. \"About seven minutes longer\nthan the quick way.\" Prefer reading this aloud over the seconds.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "available", + "chosen", + "caveats", + "block" + ], + "type": "object" +} - added
Output schema / $defs / ScenicRejectionAdded value: +{ + "description": "Why one candidate route was not offered.", + "properties": { + "code": { + "description": "The rejection code: `same_route`, `no_scenic_gain`,\n`not_scenic_enough`, `over_time_budget` or `nothing_to_say`.", + "type": "string" + }, + "detail": { + "description": "The code in words, including the minutes an `over_time_budget`\ncandidate would have cost, so raising the budget is an informed\nchoice rather than a guess.", + "type": "string" + }, + "source": { + "description": "Where the candidate came from: `\"fastest\"`, `\"engine_alternate\"`\nor `\"no_motorway\"`.", + "type": "string" + } + }, + "required": [ + "source", + "code", + "detail" + ], + "type": "object" +} - added
Output schema / properties / scenicAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/ScenicOffer" + }, + { + "type": "null" + } + ], + "description": "The scenic peer offer (only when `scenic: true` was requested):\nwhether there is a prettier way, the sentence that justifies it,\nwhat the detour costs, and why every candidate that lost lost.\nThe route above is never swapped for it." +}
- Added
route_observations
4 tool updates
- Changed
cheapest_charging_along_route2 fields changed- added
Output schema / properties / sayAdded value: +{ + "description": "**Always present.** The whole answer as one short spoken line,\ncomposed by the gateway. Coverage is inside the claim rather than\nappended to it: the line scopes its superlative to the operators\nthis deployment holds, and an empty result's line says the\nemptiness is about those operators, never about the road. Safe to\nread to a driver verbatim.", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "costing", - "route_length_m", - "candidates_considered", - "candidates_costed", - "candidate_cap", - "max_detour_minutes", - "results", - "coverage_note", - "sources", - "availability_live", - "availability_note" -]New value: +[ + "costing", + "route_length_m", + "candidates_considered", + "candidates_costed", + "candidate_cap", + "max_detour_minutes", + "results", + "coverage_note", + "sources", + "availability_live", + "availability_note", + "say" +]
- Changed
cheapest_fuel_along_route2 fields changed- added
Output schema / properties / sayAdded value: +{ + "description": "**Always present.** The whole answer as one short spoken line,\ncomposed by the gateway: the number, the detour, and the honest\nqualifier where one applies. Safe to read to a driver verbatim,\nand safe on an empty result, where it names the cause rather than\nimplying there is no fuel on the road. A stale price's line states\nthe figure and the day it was last seen and claims no saving.", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "fuel", - "costing", - "route_length_m", - "candidates_considered", - "candidates_costed", - "candidate_cap", - "max_detour_minutes", - "baseline", - "results" -]New value: +[ + "fuel", + "costing", + "route_length_m", + "candidates_considered", + "candidates_costed", + "candidate_cap", + "max_detour_minutes", + "baseline", + "results", + "say" +]
- Added
places_in_view - Added
plan_errands
2 tool updates
- Changed
create_style2 fields changed- added
Input schema / properties / baseAdded value: +{ + "description": "Optional named base to start from, e.g. \"streets\", \"midnight\",\n\"navigator-night\", \"fleet\". Call `list_style_layers` for the\ncatalogue, including which bases expect an overlay of their own. The\nbase's whole document is laid down first and `theme` is merged over\nit, so a base plus two palette entries is a complete style. Omitted,\nthe style starts from the default light theme as it always did.", + "type": [ + "string", + "null" + ] +} - changed
Input schema / properties / theme / descriptionPrevious value: -"Optional theme document (palette/layer overrides). Omitted, the\nstyle starts from the default theme carrying `name`."New value: +"Optional theme document (palette/layer overrides). Merged over\n`base` when one is given; on its own, it replaces the default theme\noutright."
- Changed
list_style_layers3 fields changed- added
Output schema / $defs / StyleBaseInfoAdded value: +{ + "description": "One entry in the named-base catalogue (`sn_style::list_bases`).", + "properties": { + "description": { + "description": "One line saying what the base is for. This is what to choose on.", + "type": "string" + }, + "group": { + "description": "\"base\" for the two stock slates (`light`, `dark`), \"designed\" for a\ndrawn style.", + "type": "string" + }, + "id": { + "description": "Base id: what `create_style`'s `base` and the static-map API's\n`style=` accept, e.g. \"navigator-night\".", + "type": "string" + }, + "label": { + "description": "Short display label, e.g. \"Navigator Night\".", + "type": "string" + }, + "restrictions": { + "description": "True when the base is drawn to sit under MapMap's\nvehicle-restriction overlay (only `fleet`). That overlay is a\nmapmap.ai runtime layer, not tile data and not part of any compiled\nstyle, so it draws in Studio and on /map and nowhere else. Asking\nfor this base anywhere else gets the palette alone; for a real\nrestriction answer use `check_clearance_on_route` or\n`check_adr_tunnel`, which answer for an actual vehicle.", + "type": "boolean" + } + }, + "required": [ + "id", + "label", + "description", + "group", + "restrictions" + ], + "type": "object" +} - added
Output schema / properties / basesAdded value: +{ + "description": "The first-party named bases a style can start from, in display\norder: pass one to `create_style`'s `base`, or to the static-map\nAPI's `style=`.", + "items": { + "$ref": "#/$defs/StyleBaseInfo" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "palette_slots", - "layer_ids", - "source_layers", - "attribution" -]New value: +[ + "bases", + "palette_slots", + "layer_ids", + "source_layers", + "attribution" +]
1 tool update
- Changed
cheapest_fuel_along_route3 fields changed- changed
Output schema / $defs / FuelBaseline / descriptionPrevious value: -"The cheapest effectively-on-route option in one currency — what the\ndriver pays by just pulling in without a detour; the reference the\nper-result savings are computed against."New value: +"The cheapest effectively-on-route option in one currency — what the\ndriver pays by just pulling in without a detour; the reference the\nper-result savings are computed against. Only a fresh price is\neligible, so this is `stale: false` by construction." - changed
Output schema / $defs / FuelPriceQuote / properties / stale / descriptionPrevious value: -"True when the price could not be verified fresher than 24 hours —\ntreat it as indicative, not bindable."New value: +"True when the price could not be verified fresher than 24 hours:\nunless BOTH the source's own `updated_at` and the snapshot's fetch\ntime fall inside that window, and always when either is missing.\nTreat it as indicative, not bindable — say \"last seen at X on\n<date>\", never quote it as today's price or as a saving." - changed
Output schema / $defs / FuelStationHit / properties / saving_per_litre / descriptionPrevious value: -"Per-litre saving against the cheapest effectively-on-route station\nin the same currency (negative = dearer than staying on route).\nAbsent when no station sits on the route itself in this currency."New value: +"Per-litre saving against the cheapest effectively-on-route station\nin the same currency (negative = dearer than staying on route).\nAbsent when no FRESH station sits on the route itself in this\ncurrency, and always absent on a stale result: an unverifiable\nprice may state a number but never claim a saving."
6 tool updates
- Added
cluster - Added
get_job - Changed
optimise_routes16 fields changed- added
Input schema / $defs / EmissionsFuelAdded value: +{ + "description": "What a vehicle burns, in clean-air-zone scheme terms.", + "oneOf": [ + { + "const": "petrol", + "description": "Petrol, including petrol hybrids (schemes rate a hybrid by its\ncombustion engine's approval).", + "type": "string" + }, + { + "const": "diesel", + "description": "Diesel, including diesel hybrids.", + "type": "string" + }, + { + "const": "electric", + "description": "Battery-electric.", + "type": "string" + }, + { + "const": "hydrogen", + "description": "Hydrogen fuel cell.", + "type": "string" + }, + { + "const": "gas", + "description": "LPG or CNG; rated as petrol by every scheme in the dataset.", + "type": "string" + } + ] +} - added
Input schema / $defs / EmissionsSpecAdded value: +{ + "description": "A vehicle's emission declaration, for clean-air / low-emission zone\nassessment.", + "properties": { + "euro_standard": { + "description": "Its Euro emission standard, 1–6. Heavy-duty approvals are written\nin Roman numerals (Euro VI); declare Euro VI as `6`. Required for\nany combustion fuel — without it no zone can be resolved, and a\nhalf-declared vehicle is indistinguishable from an undeclared one.\nOptional only for `electric` or `hydrogen`.", + "format": "uint8", + "maximum": 255, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "fuel": { + "$ref": "#/$defs/EmissionsFuel", + "description": "What it burns." + }, + "vehicle_category": { + "$ref": "#/$defs/EmissionsVehicleCategory", + "description": "What kind of vehicle this is, in scheme terms." + } + }, + "required": [ + "vehicle_category", + "fuel" + ], + "type": "object" +} - added
Input schema / $defs / EmissionsVehicleCategoryAdded value: +{ + "description": "What a vehicle is, in clean-air-zone scheme terms.\n\nDeclaring this turns \"charge depends on vehicle emissions\" into an\nanswer. Without it a zone can only be named, never priced.", + "oneOf": [ + { + "const": "car", + "description": "A private car.", + "type": "string" + }, + { + "const": "van", + "description": "A van or light goods vehicle up to 3.5 tonnes.", + "type": "string" + }, + { + "const": "minibus", + "description": "A minibus (typically 8+ passenger seats, up to 5 tonnes).", + "type": "string" + }, + { + "const": "hgv", + "description": "A heavy goods vehicle over 3.5 tonnes.", + "type": "string" + }, + { + "const": "bus", + "description": "A bus over 5 tonnes.", + "type": "string" + }, + { + "const": "coach", + "description": "A coach over 5 tonnes.", + "type": "string" + }, + { + "const": "taxi", + "description": "A licensed hackney carriage.", + "type": "string" + }, + { + "const": "phv", + "description": "A private hire vehicle.", + "type": "string" + }, + { + "const": "motorcycle", + "description": "A motorcycle, moped or tricycle.", + "type": "string" + }, + { + "const": "motorhome", + "description": "A motor caravan or campervan.", + "type": "string" + } + ] +} - added
Input schema / $defs / OptimiseVehicleSpec / properties / reloadsAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/ReloadsSpec" + }, + { + "type": "null" + } + ], + "description": "Let this vehicle return to a depot, reload and go out again — the\nwaste-collection tipping round, the van that comes back for a\nsecond wave of parcels." +} - added
Input schema / $defs / OptimiseVehicleSpec / properties / territory_idsAdded value: +{ + "description": "Ids of the request's `territories` this vehicle may work in.\nOmitted or empty, the vehicle is UNRESTRICTED and may serve any\ntask, inside a territory or outside every one of them. Listed, the\nvehicle may serve a task only if that task sits inside at least one\nof the named territories.", + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] +} - added
Input schema / $defs / RelaxSpecAdded value: +{ + "description": "What the caller is willing to give up if the first solve leaves work\nunassigned. At least one field is required.", + "properties": { + "allow_overtime_s": { + "description": "Extend every vehicle's shift END by this many seconds. Shift starts\nare never moved earlier — a driver cannot begin before they begin.", + "format": "int64", + "type": [ + "integer", + "null" + ] + }, + "time_windows_by_s": { + "description": "Widen every task time window by this many seconds at EACH end. A\n09:00–12:00 window with 1800 becomes 08:30–12:30.", + "format": "int64", + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +} - added
Input schema / $defs / ReloadsSpecAdded value: +{ + "description": "A vehicle's multi-trip reload plan.", + "properties": { + "depot": { + "anyOf": [ + { + "$ref": "#/$defs/LatLon" + }, + { + "type": "null" + } + ], + "description": "Where the vehicle reloads. Omitted, its own `start` is used (or its\n`end` if it declared only that)." + }, + "max_trips": { + "description": "How many trips this vehicle may run in its shift, 2–5. A BUDGET,\nnot a prediction: the shift is cut into that many fixed windows\nbefore the solve, so asking for five trips on a shift that supports\nthree shrinks every window to a fifth and can make the whole day\nworse. Ask for the number of trips you actually expect to run.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "reload_time_s": { + "description": "Seconds at the depot between trips — tipping, reloading, the\nweighbridge. Held out of the shift before it is partitioned, so it\nis never accidentally spent driving.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "max_trips" + ], + "type": "object" +} - added
Input schema / $defs / TerritorySpecAdded value: +{ + "description": "One named territory: a polygon that bounds which vehicle may serve\nwhich stop.", + "properties": { + "id": { + "description": "Caller-chosen id, echoed back and referenced by\n`vehicles[].territory_ids`. Must be unique within the request.", + "type": "string" + }, + "polygon": { + "description": "The outer ring as GeoJSON `[lon, lat]` positions — longitude\nFIRST. Closed or open; an unclosed ring is closed for you.", + "items": { + "items": { + "format": "double", + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "id", + "polygon" + ], + "type": "object" +} - added
Input schema / properties / avoid_zonesAdded value: +{ + "description": "Keep the optimisation's travel-time matrix out of every zone the\ndeclared vehicle would be charged or banned in. Requires\n`emissions`.", + "type": [ + "boolean", + "null" + ] +} - added
Input schema / properties / emissionsAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/EmissionsSpec" + }, + { + "type": "null" + } + ], + "description": "The fleet's emission declaration, for UK clean-air / low-emission\nzone assessment. On its own it annotates: the response's `zones`\nblock names every zone containing one of the problem's own\nlocations and what this vehicle would pay there. With\n`avoid_zones` it also steers the internal travel-time matrix away\nfrom those zones, so the plan itself changes." +} - added
Input schema / properties / relax_if_unassignedAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/RelaxSpec" + }, + { + "type": "null" + } + ], + "description": "Re-solve ONCE with these relaxations if the first solve leaves work\nunassigned, and say honestly which plan came back. At most one\nsecond solve, never beyond the caps you state, and the relaxed plan\nis returned only if it assigns MORE work than the first — giving\naway constraints for nothing is strictly worse than not giving them\naway. Breaks are never widened, nor are capacities, skills,\nterritories or task caps: only time windows move, and only by the\nstated amounts. Bills as two solves when the second one runs." +} - added
Input schema / properties / territoriesAdded value: +{ + "description": "Fleet territories: named polygons that bound which vehicle may\nserve which stop, referenced by `vehicles[].territory_ids`. These\nare request data — caller-drawn rounds, validated per call and\nnever stored. Nothing to do with clean-air zones or with the\noffline map packages of the same word.", + "items": { + "$ref": "#/$defs/TerritorySpec" + }, + "type": [ + "array", + "null" + ] +} - added
Output schema / properties / relaxationAdded value: +{ + "description": "The relaxation report: the caps requested, whether a second solve\nran, whether ITS plan is the one returned, what was widened, and\nwhat is still unassigned. Present only when `relax_if_unassigned`\nwas declared.\n\nAlways read `second_solve` and `relaxed_plan_used` before telling\nanyone the day fits. A plan produced under relaxation has had\npromises moved, and the block is what says so." +} - added
Output schema / properties / reloadsAdded value: +{ + "description": "The multi-trip split: each vehicle's trips, their windows, the\ndepot each returns to, and the stated approximation. Present only\nwhen a vehicle declared `reloads`.\n\nRead the `basis` inside it before quoting arrival times. The trip\nwindows are fixed BEFORE the solve, so a lorry that tips early\ncannot lend the spare time to its next trip: stops can come back\nunassigned that a truly sequential model would have served. The\nplan is feasible, never optimistic — it cannot put a vehicle in two\nplaces at once — but it is not optimal. Re-plan after each tip\nthrough `replan_routes` for the tighter answer." +} - added
Output schema / properties / territoriesAdded value: +{ + "description": "How the territories bound the plan: which vehicle was eligible for\nwhat, and any task no eligible vehicle existed for. Present only\nwhen `territories` was declared." +} - added
Output schema / properties / zonesAdded value: +{ + "description": "Clean-air / low-emission zones touching the problem's own\nlocations, and what the declared vehicle pays in each. Present only\nwhen `emissions` was declared." +}
- Added
replan_routes - Changed
route17 fields changed- added
Input schema / $defs / AvoidFeatureAdded value: +{ + "description": "A road feature to avoid as a PREFERENCE, not a ban. \"tolls\" and \"highways\" apply to motorised costings only (auto, truck, bus, motor_scooter, motorcycle); \"ferries\" applies to every costing. Asking for one on a costing whose engine table has no field for it is refused rather than silently ignored.", + "enum": [ + "tolls", + "highways", + "ferries" + ], + "type": "string" +} - added
Input schema / $defs / EmissionsFuelAdded value: +{ + "description": "What a vehicle burns, in clean-air-zone scheme terms.", + "oneOf": [ + { + "const": "petrol", + "description": "Petrol, including petrol hybrids (schemes rate a hybrid by its\ncombustion engine's approval).", + "type": "string" + }, + { + "const": "diesel", + "description": "Diesel, including diesel hybrids.", + "type": "string" + }, + { + "const": "electric", + "description": "Battery-electric.", + "type": "string" + }, + { + "const": "hydrogen", + "description": "Hydrogen fuel cell.", + "type": "string" + }, + { + "const": "gas", + "description": "LPG or CNG; rated as petrol by every scheme in the dataset.", + "type": "string" + } + ] +} - added
Input schema / $defs / EmissionsSpecAdded value: +{ + "description": "A vehicle's emission declaration, for clean-air / low-emission zone\nassessment.", + "properties": { + "euro_standard": { + "description": "Its Euro emission standard, 1–6. Heavy-duty approvals are written\nin Roman numerals (Euro VI); declare Euro VI as `6`. Required for\nany combustion fuel — without it no zone can be resolved, and a\nhalf-declared vehicle is indistinguishable from an undeclared one.\nOptional only for `electric` or `hydrogen`.", + "format": "uint8", + "maximum": 255, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "fuel": { + "$ref": "#/$defs/EmissionsFuel", + "description": "What it burns." + }, + "vehicle_category": { + "$ref": "#/$defs/EmissionsVehicleCategory", + "description": "What kind of vehicle this is, in scheme terms." + } + }, + "required": [ + "vehicle_category", + "fuel" + ], + "type": "object" +} - added
Input schema / $defs / EmissionsVehicleCategoryAdded value: +{ + "description": "What a vehicle is, in clean-air-zone scheme terms.\n\nDeclaring this turns \"charge depends on vehicle emissions\" into an\nanswer. Without it a zone can only be named, never priced.", + "oneOf": [ + { + "const": "car", + "description": "A private car.", + "type": "string" + }, + { + "const": "van", + "description": "A van or light goods vehicle up to 3.5 tonnes.", + "type": "string" + }, + { + "const": "minibus", + "description": "A minibus (typically 8+ passenger seats, up to 5 tonnes).", + "type": "string" + }, + { + "const": "hgv", + "description": "A heavy goods vehicle over 3.5 tonnes.", + "type": "string" + }, + { + "const": "bus", + "description": "A bus over 5 tonnes.", + "type": "string" + }, + { + "const": "coach", + "description": "A coach over 5 tonnes.", + "type": "string" + }, + { + "const": "taxi", + "description": "A licensed hackney carriage.", + "type": "string" + }, + { + "const": "phv", + "description": "A private hire vehicle.", + "type": "string" + }, + { + "const": "motorcycle", + "description": "A motorcycle, moped or tricycle.", + "type": "string" + }, + { + "const": "motorhome", + "description": "A motor caravan or campervan.", + "type": "string" + } + ] +} - added
Input schema / $defs / ExcludeFeatureAdded value: +{ + "description": "A road feature to exclude outright. A hard exclusion can leave a request with no path at all — that is the honest answer, not a failure — and it depends on the routing engine's own hard-exclusion setting, which nothing here can read.", + "enum": [ + "tolls", + "highways", + "ferries", + "bridges", + "tunnels" + ], + "type": "string" +} - removed
Input schema / $defs / LatLonRemoved value: -{ - "description": "A WGS84 coordinate pair in decimal degrees.", - "properties": { - "lat": { - "description": "Latitude in decimal degrees (−90 to 90).", - "format": "double", - "type": "number" - }, - "lon": { - "description": "Longitude in decimal degrees (−180 to 180).", - "format": "double", - "type": "number" - } - }, - "required": [ - "lat", - "lon" - ], - "type": "object" -} - added
Input schema / $defs / PreferredSideKindAdded value: +{ + "description": "Side-of-street preference for arriving at or departing from a location.\n\nCarries both vocabularies: MapMap's own `same`/`opposite`/`either` and\nthe OSRM/Mapbox `approaches` words `curb`/`unrestricted`, which are\naliases for `same` and `either`. Both spell the same request, on this\nsurface and on the HTTP API.", + "oneOf": [ + { + "const": "same", + "description": "The side the location itself projects to — the kerb, resolved\nagainst the locale's driving side (the left kerb in the UK, the\nright in Germany).", + "type": "string" + }, + { + "const": "opposite", + "description": "The far side of the road from the location.", + "type": "string" + }, + { + "const": "either", + "description": "No side preference.", + "type": "string" + }, + { + "const": "curb", + "description": "Alias for `same`, from the OSRM/Mapbox `approaches` vocabulary.", + "type": "string" + }, + { + "const": "unrestricted", + "description": "Alias for `either`, from the OSRM/Mapbox `approaches` vocabulary.", + "type": "string" + } + ] +} - added
Input schema / $defs / RouteLocationAdded value: +{ + "description": "One location of a `route` request: a coordinate, plus the optional\nkerbside approach for arriving at it.\n\nA bare `{lat, lon}` is still a complete location — every kerbside field\nis optional and omitting all of them is exactly the request that was\nmade before they existed.", + "properties": { + "lat": { + "description": "Latitude in decimal degrees (−90 to 90).", + "format": "double", + "type": "number" + }, + "lon": { + "description": "Longitude in decimal degrees (−180 to 180).", + "format": "double", + "type": "number" + }, + "preferred_side": { + "anyOf": [ + { + "$ref": "#/$defs/PreferredSideKind" + }, + { + "type": "null" + } + ], + "description": "Which side of the street to arrive on (or depart from). `same` (or\n`curb`) puts the vehicle on the door's side of the road, resolved\nagainst the locale's driving side. Two honest limits: this is a\n**snapping preference**, not a manoeuvre guarantee — the engine\nprefers an edge on that side, it does not promise the driver never\ncrosses — and it needs a coordinate genuinely offset from the road\ncentreline, because a point on the centreline has no side." + }, + "street_side_max_distance_m": { + "description": "Metres: further than this from the road centreline, the side of\nstreet is treated as `none` and `preferred_side` does nothing.\nEngine default 1000 m. Together with `street_side_tolerance_m` this\nis a WINDOW: a pair that leaves no window (tolerance at or above\nmax distance) is refused here rather than answered with a route on\nwhich the kerbside preference was silently inert.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "street_side_tolerance_m": { + "description": "Metres: nearer than this to the road centreline, the side of street\nis treated as `none` and `preferred_side` does nothing. Engine\ndefault 5 m.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "lat", + "lon" + ], + "type": "object" +} - added
Input schema / properties / avoidAdded value: +{ + "description": "Road features to avoid as a PREFERENCE. Rendered as the costing's\nwillingness factor set to zero — a thumb on the scale, not a ban.\nThe engine's own reference is explicit that a value of zero is not\nguaranteed to avoid the feature entirely, and it does not: asking\nto avoid tolls across the Dartford Crossing returns the same tolled\nroute, because the untolled alternative is fifty kilometres\nfurther. Use `exclude` when you mean a ban.", + "items": { + "$ref": "#/$defs/AvoidFeature" + }, + "type": [ + "array", + "null" + ] +} - changed
Input schema / properties / destination / $refPrevious value: -"#/$defs/LatLon"New value: +"#/$defs/RouteLocation" - added
Input schema / properties / emissionsAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/EmissionsSpec" + }, + { + "type": "null" + } + ], + "description": "The vehicle's emission declaration, for UK clean-air / low-emission\nzone assessment. Given, the response's `zones` block names every\nzone the route enters and what THIS vehicle pays there, with the\npublishing authority cited. Without it a zone can only be named,\nnever priced. Needs the MapMap gateway, which holds the curated\nzone dataset; the full dataset is readable at `GET /v1/zones`." +} - added
Input schema / properties / excludeAdded value: +{ + "description": "Road features to exclude outright, rendered as the costing's hard\nexclusion flag. Two things follow from that and both matter: a hard\nexclusion can return NO ROUTE rather than a detour (excluding\ntunnels on a Rotherhithe crossing has no answer), and the flags\ndepend on the routing engine's `allow_hard_exclusions` setting,\nwhich the engine does not expose and nothing here can read — so\nthis is never promised, only requested.", + "items": { + "$ref": "#/$defs/ExcludeFeature" + }, + "type": [ + "array", + "null" + ] +} - changed
Input schema / properties / origin / $refPrevious value: -"#/$defs/LatLon"New value: +"#/$defs/RouteLocation" - changed
Input schema / properties / waypoints / items / $refPrevious value: -"#/$defs/LatLon"New value: +"#/$defs/RouteLocation" - added
Output schema / $defs / AppliedAvoidanceAdded value: +{ + "description": "What the avoidance lists actually did, reported back so a 200 is never\nreadable as a certificate.", + "properties": { + "avoid": { + "description": "The `avoid` values that were applied, echoed back.", + "items": { + "type": "string" + }, + "type": "array" + }, + "caveats": { + "description": "The caveats that apply to this request, in words fit to repeat to a\nuser. Always present when anything was applied.", + "items": { + "type": "string" + }, + "type": "array" + }, + "costing_option_fields": { + "description": "The engine costing-option fields these words became, e.g.\n`{\"use_tolls\": 0.0, \"exclude_ferries\": true}`. This is the whole of\nwhat was sent — there is no hidden second mechanism." + }, + "exclude": { + "description": "The `exclude` values that were applied, echoed back.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "costing_option_fields", + "caveats" + ], + "type": "object" +} - added
Output schema / properties / avoidanceAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/AppliedAvoidance" + }, + { + "type": "null" + } + ], + "description": "What `avoid`/`exclude` became, and the caveats that go with it\n(only when either list carried something)." +} - added
Output schema / properties / zonesAdded value: +{ + "description": "Clean-air / low-emission zones this route enters and what the\ndeclared vehicle pays in each, with the publishing authority cited\n(only when `emissions` was declared). Passed through verbatim from\nthe gateway's curated dataset — the same figures `GET /v1/zones`\npublishes, so a charge can always be audited back to its source." +}
- Added
submit_optimise_job
8 tool updates
- Added
cheapest_charging_along_route - Changed
geocode11 fields changed- added
Input schema / properties / cityAdded value: +{ + "description": "Structured component: town or city, e.g. \"London\". Matches the\ncontaining city as well as the immediate locality, so a suburb name\nworks here too.", + "type": [ + "string", + "null" + ] +} - added
Input schema / properties / countryAdded value: +{ + "description": "Structured component: ISO 3166-1 alpha-2 code or country name —\n\"GB\", \"gb\", \"United Kingdom\" and \"UK\" all mean the same country.\nA value naming no country is refused rather than quietly applied as\na filter that matches nothing.", + "type": [ + "string", + "null" + ] +} - added
Input schema / properties / housenumberAdded value: +{ + "description": "Structured component: house number, e.g. \"10\" or \"221B\". Only\nmeaningful alongside `street` — a house number on its own excludes\nnearly everything and identifies nothing.", + "type": [ + "string", + "null" + ] +} - added
Input schema / properties / postcodeAdded value: +{ + "description": "Structured component: postcode in any spacing or case — \"SW1A 2AA\"\nand \"sw1a2aa\" are one query. A bare UK outward code (\"SW1A\")\nselects the whole district.", + "type": [ + "string", + "null" + ] +} - changed
Input schema / properties / query / descriptionPrevious value: -"Free-text place query, e.g. \"Dover ferry terminal\"."New value: +"Free-text place query, e.g. \"Dover ferry terminal\". Required unless\nat least one structured component is supplied." - changed
Input schema / properties / query / typePrevious value: -"string"New value: +[ + "string", + "null" +] - added
Input schema / properties / streetAdded value: +{ + "description": "Structured component: street name, e.g. \"Downing Street\". Matches\nthe street of addresses and POIs (transliterated street names\nincluded) as well as the street itself.", + "type": [ + "string", + "null" + ] +} - removed
Input schema / requiredRemoved value: -[ - "query" -] - added
Output schema / $defs / GeocodeHit / properties / matchAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/GeocodeMatch" + }, + { + "type": "null" + } + ], + "description": "How far this hit can be trusted to be the place that was asked\nfor — see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on." +} - added
Output schema / $defs / GeocodeMatchAdded value: +{ + "description": "How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n answer does not carry the address that was asked for — an `unmatched`\n postcode means the result has no postcode at all, `inferred` means it\n has a different one. Neither is a match. Say so rather than presenting\n the hit as the address, and reach for `verify_places` when the address\n came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n and the runner-up, which is exactly when to show the alternatives\n instead of picking one for the user.", + "properties": { + "components": { + "$ref": "#/$defs/GeocodeMatchComponents", + "description": "Per-component verdict on this hit: one entry for each structured\ncomponent supplied, and empty when the query was free text only." + }, + "score_gap": { + "description": "The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score — so a `0` is \"no signal\", not\n\"a tie\".", + "format": "double", + "type": "number" + }, + "source": { + "description": "Which backend answered: \"mapmap-index\" (the first-party index) or\n\"photon\".", + "type": "string" + } + }, + "required": [ + "components", + "score_gap", + "source" + ], + "type": "object" +} - added
Output schema / $defs / GeocodeMatchComponentsAdded value: +{ + "description": "Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\" — the result's own field carries the value asked for (case-\n and accent-insensitive, and by containment, so `city: \"London\"`\n matches \"City of London\").\n* \"inferred\" — the result carries a value for that component, but not\n the one asked for. It reached the page through ranking, as when a\n street is found by its transliterated name and displayed under its\n canonical one.\n* \"unmatched\" — the result carries no value for that component at all.", + "properties": { + "city": { + "description": "Verdict on the supplied `city`.", + "type": [ + "string", + "null" + ] + }, + "country": { + "description": "Verdict on the supplied `country`.", + "type": [ + "string", + "null" + ] + }, + "housenumber": { + "description": "Verdict on the supplied `housenumber`.", + "type": [ + "string", + "null" + ] + }, + "postcode": { + "description": "Verdict on the supplied `postcode`.", + "type": [ + "string", + "null" + ] + }, + "street": { + "description": "Verdict on the supplied `street`.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Added
get_usage - Added
list_place_categories - Added
match_trace - Changed
plan_day3 fields changed- added
Output schema / $defs / GeocodeHit / properties / matchAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/GeocodeMatch" + }, + { + "type": "null" + } + ], + "description": "How far this hit can be trusted to be the place that was asked\nfor — see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on." +} - added
Output schema / $defs / GeocodeMatchAdded value: +{ + "description": "How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n answer does not carry the address that was asked for — an `unmatched`\n postcode means the result has no postcode at all, `inferred` means it\n has a different one. Neither is a match. Say so rather than presenting\n the hit as the address, and reach for `verify_places` when the address\n came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n and the runner-up, which is exactly when to show the alternatives\n instead of picking one for the user.", + "properties": { + "components": { + "$ref": "#/$defs/GeocodeMatchComponents", + "description": "Per-component verdict on this hit: one entry for each structured\ncomponent supplied, and empty when the query was free text only." + }, + "score_gap": { + "description": "The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score — so a `0` is \"no signal\", not\n\"a tie\".", + "format": "double", + "type": "number" + }, + "source": { + "description": "Which backend answered: \"mapmap-index\" (the first-party index) or\n\"photon\".", + "type": "string" + } + }, + "required": [ + "components", + "score_gap", + "source" + ], + "type": "object" +} - added
Output schema / $defs / GeocodeMatchComponentsAdded value: +{ + "description": "Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\" — the result's own field carries the value asked for (case-\n and accent-insensitive, and by containment, so `city: \"London\"`\n matches \"City of London\").\n* \"inferred\" — the result carries a value for that component, but not\n the one asked for. It reached the page through ranking, as when a\n street is found by its transliterated name and displayed under its\n canonical one.\n* \"unmatched\" — the result carries no value for that component at all.", + "properties": { + "city": { + "description": "Verdict on the supplied `city`.", + "type": [ + "string", + "null" + ] + }, + "country": { + "description": "Verdict on the supplied `country`.", + "type": [ + "string", + "null" + ] + }, + "housenumber": { + "description": "Verdict on the supplied `housenumber`.", + "type": [ + "string", + "null" + ] + }, + "postcode": { + "description": "Verdict on the supplied `postcode`.", + "type": [ + "string", + "null" + ] + }, + "street": { + "description": "Verdict on the supplied `street`.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Added
plan_ev_route - Changed
search_along_route3 fields changed- added
Output schema / $defs / GeocodeHit / properties / matchAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/GeocodeMatch" + }, + { + "type": "null" + } + ], + "description": "How far this hit can be trusted to be the place that was asked\nfor — see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on." +} - added
Output schema / $defs / GeocodeMatchAdded value: +{ + "description": "How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n answer does not carry the address that was asked for — an `unmatched`\n postcode means the result has no postcode at all, `inferred` means it\n has a different one. Neither is a match. Say so rather than presenting\n the hit as the address, and reach for `verify_places` when the address\n came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n and the runner-up, which is exactly when to show the alternatives\n instead of picking one for the user.", + "properties": { + "components": { + "$ref": "#/$defs/GeocodeMatchComponents", + "description": "Per-component verdict on this hit: one entry for each structured\ncomponent supplied, and empty when the query was free text only." + }, + "score_gap": { + "description": "The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score — so a `0` is \"no signal\", not\n\"a tie\".", + "format": "double", + "type": "number" + }, + "source": { + "description": "Which backend answered: \"mapmap-index\" (the first-party index) or\n\"photon\".", + "type": "string" + } + }, + "required": [ + "components", + "score_gap", + "source" + ], + "type": "object" +} - added
Output schema / $defs / GeocodeMatchComponentsAdded value: +{ + "description": "Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\" — the result's own field carries the value asked for (case-\n and accent-insensitive, and by containment, so `city: \"London\"`\n matches \"City of London\").\n* \"inferred\" — the result carries a value for that component, but not\n the one asked for. It reached the page through ranking, as when a\n street is found by its transliterated name and displayed under its\n canonical one.\n* \"unmatched\" — the result carries no value for that component at all.", + "properties": { + "city": { + "description": "Verdict on the supplied `city`.", + "type": [ + "string", + "null" + ] + }, + "country": { + "description": "Verdict on the supplied `country`.", + "type": [ + "string", + "null" + ] + }, + "housenumber": { + "description": "Verdict on the supplied `housenumber`.", + "type": [ + "string", + "null" + ] + }, + "postcode": { + "description": "Verdict on the supplied `postcode`.", + "type": [ + "string", + "null" + ] + }, + "street": { + "description": "Verdict on the supplied `street`.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
34 tool updates
- First observed
cheapest_fuel_along_route - First observed
check_adr_tunnel - First observed
check_clearance_on_route - First observed
check_style_contrast - First observed
create_style - First observed
elevation - First observed
geo_area - First observed
geo_bbox - First observed
geo_bearing - First observed
geo_centroid - First observed
geo_destination - First observed
geo_distance - First observed
geo_length - First observed
geo_nearest_point_on_line - First observed
geo_point_in_polygon - First observed
geo_simplify - First observed
geocode - First observed
get_style - First observed
list_style_layers - First observed
matrix - First observed
nearby_places - First observed
optimise_routes - First observed
order_stops - First observed
plan_day - First observed
reachable_area - First observed
report_map_issue - First observed
reverse_geocode - First observed
route - First observed
search_along_route - First observed
set_layer_paint - First observed
set_palette - First observed
submit_integration_retro - First observed
validate_geodata - First observed
verify_places
Related MCP Connectors
- geoOAuthco.thinair
Geocoding, routing, isochrones, traffic, weather, and place search for AI agents. 19 MCP tools.
Hosted MCP for live place search, geocoding & turn-by-turn routes. No Maps API key to manage.
Agentic-AI route optimization for delivery fleets, capacity- and time-window-safe.
- RijwindOAuthcom.rijwind
European maps, geocoding and routing: places, routes, travel times, reachable areas and maps.
1
Related MCP Servers
- AlicenseAqualityDmaintenanceGeospatial API tools for AI agents — geocoding, reverse geocoding, routing, isochrone, distance matrix, static maps, H3 hexagons, elevation, GPS map-matching, point-in-polygon, address normalisation, timezone lookup, and batch geocoding. Built on OpenStreetMap infrastructure. Cost-effective alternative to Google Maps API.1824 npmMIT

ThinAir Geoofficial
AlicenseAqualityBmaintenanceLocation & routing intelligence for AI agents — geocoding, truck routing, traffic, weather, and place search.619212 npm1MIT
Magic Lane MCP Serverofficial
AlicenseBqualityBmaintenanceEnables AI agents to become geospatially intelligent assistants with tools for location search, smart routing, round trip planning, reverse geocoding, isochrone analysis, route visualization, geofence management, and interactive map display.818 npm7Apache 2.0- AlicenseAqualityCmaintenanceEnables AI agents to compute optimized routes, geocode locations, generate distance matrices, cluster points, check boundaries, and manipulate GeoJSON through MCP tools.6MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.