MapMap
Server Details
Maps for agents: truck/ADR routing, geocoding, places, matrices, isochrones, EV and fleet planning.
- Status
- Healthy
- Uptime
- 99.9% over 62 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 55 tools
Most tools target a clearly distinct capability (geometry helpers, routing, weather, transit, style management), and the descriptions do heavy lifting by explicitly telling the agent when to prefer one over a sibling. However, several overlapping families remain: order_stops / plan_day / plan_errands / optimise_routes / cluster all order stops, and nearby_places / places_in_view / reverse_geocode / search_along_route / geocode all resolve places, so misselection is plausible without careful reading.
Everything is snake_case, which is consistent, and common verb prefixes (check_, create_, get_, list_, set_, plan_, submit_, search_, near/b/-vy) recur predictably. The style is not strictly verb_noun throughout (camera_incidents, weather_frames, space_weather_now, elevation, matrix are noun-first, and the geo_ namespace excludes geocode/reverse_geocode), but it stays readable and predictable.
55 tools is well past the point where an agent can hold the surface in mind, and the rubric treats 25+ as too many. The breadth of the geospatial platform partially justifies it, but the overlapping ordering and place-finding families show the surface could be consolidated, so this is heavy rather than well-scoped.
Coverage is exceptional: routing across five costings, matrices, reachability, synchronous and asynchronous optimization plus re-planning and clustering, forward/reverse geocoding, POI discovery, fuel and EV planning, weather, incidents, transit, elevation, geometry utilities, style lifecycle and reporting/usage tools. Nearly every domain it touches has a near-complete create/read/update/act surface with no obvious dead ends.
Available Tools
55 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 carries the full burden and does so unusually well: it discloses coverage limitations (no national registry, per-deployment operator scope, always show coverage_note), the meaning of an empty results set, availability staleness semantics (live only when availability_live is true), the refusal behaviour of available_only, gateway/dataset prerequisites, and how ranking and costing work. These are exactly the operational traits an agent cannot derive from 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 core purpose and input modes are front-loaded in the first sentence, and the density is high with little filler apart from the aphorism about kilowatts. It is on the long side for a tool description and mixes result-field enumeration with invocation guidance, but almost every sentence conveys actionable 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 10 parameters, no required fields, a rich schema, an output schema, and no annotations, the description covers everything an agent needs: input-mode selection, filtering semantics, coverage and staleness caveats, error conditions, the `say` field contract, and attribution requirements. Return fields are listed even though an output schema exists, which is mildly redundant but not a gap.
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 already 100%, so the schema does the heavy lifting and a 3 would be the baseline. The description adds real meaning on top: it enumerates the connector tokens inline, explains min_kw's intent (e.g. 50 for rapid only), gives max_detour_minutes' default and cap context, and clarifies that a truck profile makes detours respect dimensional/ADR restrictions and requires costing "truck".
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 precise verb and resource — find EV charge points along a route — and adds the distinguishing scope that detours are costed through the routing engine rather than estimated as straight lines, which is genuinely differentiating. However, it never names or contrasts against the obvious siblings that could be confused with it, notably plan_ev_route and cheapest_fuel_along_route, so an agent must infer the boundary itself.
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 clearly states the input modes (origin+destination, or an existing route's geometry_polyline6, explicitly not both) and gives concrete filter conditions such as available_only requiring a live feed and being refused otherwise. It also tells the agent to prefer the returned `say` verbatim and to display charging_attribution. What is missing is any explicit when-not or alternative-tool routing against siblings like plan_ev_route or search_along_route.
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, the description carries the full burden and does so richly: it defines the ranking rule (freshest-priced first, cheapest within), the exact meaning of `stale` including the missing-timestamp case, the rule that a stale price is never the baseline and carries no saving, the attribution requirement, and the always-present `say` line. 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?
The purpose and the key differentiator are front-loaded, and the dense single paragraph mostly earns its length by covering stale semantics and the `say` contract. It is a long, information-dense block, and some clauses (fuel lists, attribution details) could be trimmed, but little is truly wasteful.
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 spelled out, yet the description still orients the agent on the important result fields (price, detour, saving, stale) and the `say` field's role. Combined with the routing, ranking, and dataset-prerequisite context, an agent has everything needed to call it correctly and interpret the answer.
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 goes beyond it by explaining that `truck` requires costing 'truck' and how it affects detours, that `geometry_polyline6` is the `route` tool's field and is mutually exclusive with origin/destination, the fuel default and aliases, and the effect of `fill_litres`. It adds real semantic relationships rather than restating types.
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 ('Find the cheapest fuel along a route') and immediately qualifies it with a distinguishing trait ('REAL extra travel time of stopping at each station, never a straight-line guess'). This clearly separates it from the sibling cheapest_charging_along_route and the generic route 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?
Gives explicit input alternatives ('Provide origin + destination ... or an existing route's geometry_polyline6'), states defaults for fuel and max_detour_minutes, and notes the gateway/dataset prerequisite with its error behavior. It does not explicitly name when to prefer a sibling (e.g. cheapest_charging_along_route for EVs), so it stops short of full routing guidance.
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, the description carries the behavioral burden and does so well: it discloses the conservative worst-case reading (over-restrict, never under-restrict), that no network access is needed, and that it answers instantly. It omits only peripheral details like negation semantics of a blocked vs permitted result.
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 tight sentences, front-loaded with the purpose, then inputs, then behavioral caveats. No wasted filler; slightly dense but appropriately sized.
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 need not be explained, and the description covers inputs, edge cases (unknown code), and behavioral semantics thoroughly enough for a stateless, no-annotation check tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds genuine value beyond the schema by giving example tunnel codes ("B", "C5000D", "B/D", "none") and the conservative default for an unknown code, clarifying real input expectations.
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 (check) and resource (tunnel passage) with the ADR category range, and the hazmat/ADR framing clearly separates it from geometric siblings like check_clearance_on_route. An agent can identify the operation 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 input guidance (provide hazmat, and the tunnel code when known), which implies usage, but never states when to reach for this tool versus alternatives such as check_clearance_on_route or route. Usage context is implied rather than spelled out.
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 delivers: it discloses that distances ignore the road network, that the answer carries a `basis` sentence that should be shown to the user, deterministic seeding across deployments, a MapMap gateway requirement, and that a load ceiling is a bin-packing problem that may have no solution. This is unusually rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded, then the critical straight-line caveat, then the input contract and return shape. It is long and occasionally repetitive (the straight-line limitation is restated), but nearly every sentence carries decision-relevant 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 6-parameter tool with an output schema, the description covers the sequencing recipe, the clustering limitation, the constraint modes, determinism, and the gateway requirement. An agent has everything needed 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 coverage is already 100%, so the baseline is 3, but the description adds cross-parameter meaning: the exactly-one-of constraint across `clusters`/`max_cluster_locations`/`max_cluster_load`, how `territories` isolates clustering, and how `seed` guarantees reproducibility. It goes beyond per-field 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?
States a specific verb and resource ('Group stops into balanced geographic clusters') and immediately scopes it as straight-line clustering. It explicitly distinguishes itself from `optimise_routes` and from order-deciding tools, so an agent can place it against siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('front half of the recipe for a thousand-stop day'), the alternative and sequencing ('then call `optimise_routes` per cluster'), and an explicit when-not ('wrong one for deciding what ORDER to visit them in'). Nothing is left to inference.
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?
With no annotations, the description carries full disclosure and does it well: it describes merge precedence (base laid down first, theme merged over), the no-argument default theme, and the worldview side effect on label naming. It does not cover persistence/ownership or any auth requirements for a 'hosted' write, leaving a small gap.
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-loads the purpose in the first sentence and then packs merge semantics, defaults, worldview, and return values into one dense paragraph. It is on the long side and could be split, but nearly every clause carries information an agent needs.
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 a write tool with no annotations and an output schema present, the description supplies everything needed to invoke it correctly: required vs optional inputs, composition/merge rules, default behavior, worldview options, and the returned style_id/URL chain to sibling tools.
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 genuine meaning: it enumerates the concrete base names (light, dark, streets, midnight, navigator-day, fleet, outdoor, dataviz, backdrop, print), spells out the theme document shape (base/palette/layers with slot: colour semantics), and gives the accepted worldview codes with their effect on labels.
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 ('Create a hosted map style') and immediately distinguishes itself from siblings like get_style, set_palette, set_layer_paint by describing creation plus what it returns. An agent can tell this is the style-creation entry point without reading further.
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?
Explains the composing cases clearly: base alone, theme alone, base+theme combined ('streets with darker water is one call'), and neither (default theme). It also points to list_style_layers for the catalogue and names set_palette/set_layer_paint as the follow-up tools. It stops short of stating explicit exclusions such as when to modify an existing style instead of creating one.
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, the description carries full behavioral burden and does so well: it discloses ordering of results, that elevation_m is null rather than guessed where DEM coverage is absent, and that the polyline form returns resampled lat/lon plus cumulative range_km. It omits auth/rate-limit or failure-mode info, keeping it short of a 5.
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 dense sentences, front-loaded with the core action, then mode selection, then return semantics. No filler or redundancy with the title.
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 3-param read tool with an output schema and full schema coverage, the description supplies the one genuinely agent-relevant behavior not captured elsewhere: how missing coverage is represented (null, never a guess) and result ordering. Nothing needed to call 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 description coverage is 100% and the schema already states the mutual exclusivity and that resampling is ignored for points. The description reinforces this ('a bare list of coordinates') but adds little semantic detail beyond the structured fields, 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 ('Sample terrain elevation') and immediately names the two distinct sampling modes it supports. An agent can distinguish it from route/weather siblings 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?
Explicitly states the mutually exclusive usage condition ('Provide points ... or encoded_polyline ... not both') and what resample_distance_m applies to. It does not name alternative tools for related needs, but within this tool 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.
events_in_areaAInspect
Earthquakes, volcano alerts and satellite fire detections in a bounding box, for display. Pass bbox [west, south, east, north] (WGS84), optional types (quake, volcano, fire; default all), min_magnitude (quakes, default 2.5) and limit (1 to 500, default 100). Earthquakes are USGS, magnitude 2.5 and above, past 24 hours, as reported (magnitudes and locations may be revised). Volcano alerts are USGS-monitored volcanoes ONLY: an absent alert says nothing about volcanoes elsewhere. Fire cells are NASA FIRMS VIIRS detections thinned to 0.5 degree cells: satellite-detected heat, NOT confirmed fires. Each feed carries status (ok, stale, unknown): pass a stale or unknown status on, never present old data as current. This is reported data for display, not a warning service and not safety-critical; keep that qualifier when you pass it on. Requires the MapMap gateway. Display the returned attribution, and for fire data the FIRMS acknowledgment and disclaimer.
| Name | Required | Description | Default |
|---|---|---|---|
| bbox | Yes | Bounding box `[west, south, east, north]`, WGS84 degrees. West must be less than east and south less than north; a box crossing the antimeridian is not supported (query two boxes). | |
| limit | No | Most events to return, 1 to 500 (default 100). Newest quakes first, then volcano alerts, then the busiest fire cells. | |
| types | No | Which feeds to include: any of `quake`, `volcano`, `fire`. Default: all three. | |
| min_magnitude | No | Smallest earthquake magnitude, 2.5 to 9.0 (default 2.5). Quakes only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | Events returned. |
| feeds | Yes | Freshness of each requested feed, keyed `quake`, `volcano`, `fire`. |
| label | Yes | Reported events for display; not a warning service. Pass it on. |
| events | Yes | The events: newest quakes, then volcano alerts, then fire cells. |
| summary | Yes | One sentence built from the counts. Pass it on with its qualifier. |
| coverage | Yes | What each feed does and does not cover. Pass it on. |
| truncated | Yes | True when the limit cut the list short. |
| disclaimer | Yes | NASA FIRMS "as is" disclaimer. Display it with fire data. |
| attribution | Yes | Source credits, keyed by feed. Display them. |
| endorsement | Yes | No endorsement by or affiliation with USGS, NOAA or NASA is implied. |
| acknowledgment | Yes | NASA FIRMS acknowledgment. Display it with fire data. |
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 and does so thoroughly: gateway dependency, data provenance (USGS, NASA FIRMS), freshness windows, the volcano-only monitoring limitation, fire cells being unconfirmed heat rather than confirmed fires, and revision warnings. These are exactly the behavioral traits an agent needs and which annotations would otherwise cover.
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 bbox format are front-loaded and the dense caveats stay on-topic; nothing reads as filler. It is long and heavily packed, but each clause (attribution, acknowledgment, disclaimer requirements) 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?
With an output schema present, return-value detail is unnecessary, and the description instead supplies the non-schema essentials: gateway requirement, caveats about data reliability, status propagation, and required attribution text. Nothing an agent needs to call or responsibly relay this tool 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 bbox format, defaults, ranges and ordering; the description mostly restates these (bbox WGS84, defaults, quakes-only min_magnitude). It adds little semantics beyond the schema, so the baseline of 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?
Names a specific resource (earthquake/volcano/fire events) with an explicit spatial scope (bounding box) and a stated intent (for display). An agent can distinguish it from geo_bbox or space_weather_now without opening any 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?
Gives clear usage context and exclusions: 'for display, not a warning service and not safety-critical', and instructs that stale/unknown status must be passed on rather than presented as current. It does not name an alternative sibling to use instead, so it falls short of an explicit routing rule.
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?
No annotations, but the description carries the full burden well: it explains that components are hard requirements rather than ranking hints, that an invalid country is refused not silently ignored, that a bare city name lists airports/stations first, and that match/score_gap must be read before acting on an address. These are precisely the non-obvious behavioral traits an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb and resource, then builds through input modes and output interpretation. Dense but every sentence earns its place; slightly long, but the compression is intentional and mostly readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 params and output schema present, the description covers input semantics, result interpretation (match, score_gap, backend), and language behavior. It does not detail every output field, but the output schema covers that. 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 baseline is 3, but the description adds real semantic value beyond the schema: it explains the two input modes combine, that components are REQUIREMENTS not hints, the country format, and that bare city names surface airports/stations. The match/score_gap guidance is output-level, but limit/x default behavior is confirmed too.
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?
Specific verb+resource: 'Turn a place (address, POI, town) into coordinates.' Explicitly distinguishes itself from reverse_geocode (opposite direction) and points the agent at verify_places for checking addresses. No ambiguity against 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?
Gives concrete when-to-use: pass components when the address already arrives in parts (form, CRM row, manifest); use verify_places instead when the address came from a model or user and needs verification. Also explains when to prefer query over components based on whether the input is free text or already structured.
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?
No annotations are provided, so the description carries the full burden, and it delivers the two facts an agent most needs: the computation is local with no network call and no quota, and the result is geodesic rather than routed. It does not discuss precision, edge cases (antipodal points), or units of the return value, but the output schema covers the return shape.
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 short sentences, front-loaded with the core definition, then the disambiguation, then the operational caveat. Every sentence carries distinct information and none is 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 two-parameter pure-computation tool with a full output schema, the description covers purpose, unit, semantics, sibling routing, and cost profile. 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 description coverage is 100% and the nested LatLon definition thoroughly documents the coordinate formats, including the longitude-first GeoJSON array ordering. The description only says 'two coordinates' and adds no semantics beyond what the schema already provides, so 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?
States a specific resource (distance in metres between two coordinates) and immediately scopes it as geodesic straight-line distance on WGS84. It explicitly names the sibling tools that do something different (`route`, `matrix`), so an agent can distinguish it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both sides of the routing decision: use this for as-the-crow-flies distance, use `route` or `matrix` for travel distance and time. The condition that selects this tool versus the alternatives is stated directly rather than implied.
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?
With no annotations provided, the description carries the behavioral load and does well by disclosing that this is a local, quota-free computation and that the result is summed geodesically rather than routed. It could say more about edge cases such as antimeridian handling or minimum-point validation, 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?
Three short sentences, front-loaded with the core computation and followed immediately by the key routing distinction and execution context. There is no filler, and everything needed is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter geometry tool with an output schema and rich nested schema definitions, the description supplies everything an agent needs: what is measured, how it differs from `route`, units, and that there is no network or quota impact.
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 `points` structure, coordinate formats, and coordinate order are already fully documented in the schema. The description adds useful semantic context by specifying that a polyline requires 2+ coordinates and that measurements are geodesic, going beyond the schema’s brief 'The coordinates to consider.'
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 computed quantity: total polyline length in metres, summed geodesically, for a supplied set of 2+ coordinates. It also explicitly distinguishes this from a driven route by naming `route` as the correct alternative, which is the main sibling confusion.
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 when-not rule: use `route` for driven routes, while this tool measures the line you supply. It also states a key usage condition: local computation with no network call and no quota.
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?
With no annotations, the description carries the full burden and delivers: reads are unmetered while the submission is charged, `units_charged`/`refunded` semantics on failure, and strict ownership rules where another key's id returns NOT FOUND rather than forbidden to avoid disclosing existence. These are non-obvious gateway behaviors an agent could not infer from 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?
Purpose is front-loaded and almost every clause adds operational value, but the justification of the free-polling design ('a poll that costs quota is a poll a caller rations...') runs two clauses longer than the guidance it supports. Dense and useful, slightly discursive.
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, yet the description still explains the state machine (`queued`/`running`/`succeeded`/`failed`), the `terminal` polling signal, and the charge/refund fields in a way an agent can act on. Nothing needed to call 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% with a single required `id`, and the schema already says it comes from `submit_optimise_job`. The description adds no format, validation, or expiry detail about the id beyond that, so this is the standard baseline when the schema does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Read an asynchronous job submitted with `submit_optimise_job`') and names the sibling that creates such jobs. It goes further by specifying exactly what is returned (status, then result inline identical to the synchronous tool), so the agent knows the contract 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?
Explicit when and how: poll while `terminal` is false, check every few seconds rather than guessing a duration, and it names the alternative (webhooks) while excluding it for agents in a loop. This is a textbook when/when-not/alternative routing statement.
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 full behavioral burden. "Fetch" implies a read-only operation and it clarifies that the theme document is the editable source while the MapLibre style is a compiled artifact, but there is no explicit statement about side effects, permissions, or rate limits.
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 tight sentences with zero filler, front-loading what is returned before the usage hint. Every 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?
With one fully documented parameter and an output schema covering return values, the description is essentially complete for an agent to call it correctly. It omits error/not-found behavior and any sibling routing, which are minor gaps for a simple fetch.
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 single style_id parameter is already documented with a concrete example, so the schema does the heavy lifting. The description adds no syntax, format, or default details beyond what the schema provides, making the baseline 3 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?
States a specific verb (Fetch) and a precisely scoped resource (a hosted style's latest theme document plus the URL of its latest compiled MapLibre style). This cleanly separates it from siblings like create_style, set_palette, list_style_layers, and check_style_contrast 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?
"Use the theme to inspect current palette and layer overrides before editing" gives a clear read-before-write workflow context. It does not name alternative tools (e.g. list_style_layers) or state when not to use it, so it stops short of full when/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_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, the description carries the full behavioral burden and does so richly: reading is free and consumes no quota, the authenticating key is the only key reported, pooled quota (identity_pooled) may include other keys, and it requires the MapMap gateway env vars. It also clarifies that units are weighted, not call counts, which is a critical behavioral caveat.
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 dense and front-loaded, leading with the purpose and cost profile before parameters and return semantics. The sentences are long but each carries distinct, non-redundant information, though the return-field enumeration partly duplicates the 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?
For a read-only reporting tool, it covers purpose, cost model, range constraints, quota semantics, and auth requirements. Since an output schema exists, its description of return fields is supplementary rather than required, and nothing an agent needs to call 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 description coverage is 100%, so the schema already documents both optional params including the YYYY-MM-DD UTC format and 92-day cap. The description restates these rather than adding new syntax or format meaning, 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?
The description names a specific verb+resource ('Check what your own API key has spent') and immediately frames the scope (self-usage only, no other caller's usage). No sibling tool covers this domain, so there is nothing to confuse it with, and the 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?
It states the motivating context clearly ('so you can decide mid-task whether to keep going') and highlights the free/non-quota nature that would drive selection. It stops short of naming an explicit alternative or when-not-to-use condition, but for a self-contained diagnostics tool that context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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: it discloses the silent-failure mode (an off-list token matches nothing and returns an empty result rather than an error), the cost profile (local lookup, no network, no quota), and determinism (sorted by category, identical on every call). It also pre-describes the shape of each returned entry (token, aliases, description).
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?
Five sentences, each load-bearing: purpose and consumers first, then return shape, then the failure warning, then the exclusion rule, then cost/determinism. No repetition of the title or filler, and the most important warning 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?
An output schema exists so return values need not be re-explained, yet the description still summarises the entry structure helpfully. For a zero-parameter, offline enumeration tool, nothing an agent needs in order to call 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 takes zero input parameters, so the baseline is 4. The description usefully explains the semantics of the values the tool *returns* and that they must be passed verbatim as `category` elsewhere, but there is no input schema to enrich.
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 (list the canonical place categories) and immediately names the sibling tools that consume the output (`nearby_places`, `search_along_route`, `geocode`), so an agent can place it in the tool graph without opening any schema. It also distinguishes itself from free-text search by excluding cuisines, brands and names.
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 'read this before guessing a category' directive with the consequence spelled out, plus a clear when-not rule (cuisines, brands and names are NOT categories, search those as free text). The alternative behaviour and the condition selecting it are both stated, not implied.
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, the OpenMapTiles source-layers extra layers may reference, the insertion slots (bottom, middle, top) an extra layer may name, and the rules for a theme's own sources (your data by https URL). 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=`. |
| slots | No | The insertion slots an extra layer may name (`"slot"`), bottom of the stack first, with the layer each sits directly below. A layer without a slot goes in `middle`. |
| sources | No | The rules for a theme's own `sources` (customer data by URL). |
| 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; an extra layer on the `territory` source must reference one of these. |
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 real behavioral facts: local lookup, no network, always works, and the non-obvious invariant that attribution is enforced on every compiled style and cannot be themed away. Return shape is not described, but an output schema exists, so that omission is acceptable.
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 scope statement is front-loaded and each enumerated clause carries a distinct, useful vocabulary item rather than filler. It is a dense run-on sentence, but the density is information rather than padding.
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 discovery tool with a full output schema and no annotations, the description covers what it enumerates, how to consume the results, and its operational guarantees. Nothing an agent needs before calling 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 takes zero parameters, so the baseline is 4. The description nonetheless adds meaning to other tools' parameters by naming `base`, `style=`, insertion slots (bottom/middle/top), and set_layer_paint's accepted layer ids, which helps the agent chain calls correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a concrete verb and resource ("List everything a MapMap style theme can style") and enumerates the exact vocabularies returned — bases, palette slots, skeleton layer ids, source-layers, insertion slots, sources rules. It implicitly distinguishes itself from get_style/set_layer_paint by naming those tools as consumers of the values, though it never states what those siblings do differently.
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 what to do with the results (pass a base to create_style's `base` or the static-map API's `style=`; use skeleton layer ids with set_layer_paint), which is clear usage context. It stops short of an explicit when-to-use-this-vs-get_style statement or any exclusion.
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?
With no annotations, the description carries the full burden and does so well: it discloses the exact input alternatives and mutual exclusion, the return shape, the honesty caveat that roll-ups may not sum to `distance_m`, how unattributed segments are handled, and the hard dependency on the MapMap gateway with no fallback.
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 front-loaded, with the core action in the first sentence and parameters, returns, caveats and prerequisites following in order. It is long, but nearly every sentence carries usable information, so only mild trimming is possible.
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 three-parameter matching tool with an output schema and no annotations, the description is complete: inputs, costing semantics, return fields, data-quality caveats and the gateway prerequisite are all covered, leaving no gap an agent would need to fill.
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 meaning beyond the schema: the 'provide this or that (not both)' mutual exclusion (not enforced at the top level of the schema), the 2-2000 point range, and an example of how costing changes physical matching (a walk matched as auto snaps to the carriageway).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: snap a recorded GPS trace to the road network and report what was travelled. It clearly separates itself from routing siblings like `route` and `route_observations` by emphasizing matching an already-recorded trace rather than computing a path.
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 context ('turn a dashcam or telematics log into a report') and explains the costing choice that governs matching. It does not explicitly name alternatives or when-not-to-use (e.g. vs `route` or `route_observations`), 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.
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?
With no annotations at all, the description carries the full burden and does so: it documents the return shape (durations_s in seconds, distances_m in metres, null for unreachable pairs), a hard limit of 10,000 cells per call, and engine-specific behaviour (exclude_polygons honoured on Valhalla, silently ignored on GraphHopper). Those are exactly the operational facts an agent needs before calling.
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 verb and matrix orientation, then costing, output contract, limits, and the optional scenario parameter. Dense but every sentence contributes; the only redundancy is the exclude_polygons explanation largely duplicating the schema's own description, including its wording and the engine caveat.
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, yet the description still supplies what the schema alone cannot convey: null-cell meaning, the cell-count ceiling, and engine-dependent support for `exclude_polygons`. Combined with the 100%-covered input schema, an agent has everything needed 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 genuine meaning beyond the schema: it repeats the longitude-first requirement for polygons, explains that exclusion is applied to every cell's pathfinding (intersecting roads), and links the `truck` profile semantics back to `route`. It does not, however, clarify units or defaults for the truck dimensions.
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 (compute travel time/distance matrix) and defines the row/column semantics of origins and destinations, which immediately distinguishes it from row-per-route siblings like `route` and `optimise_routes`.
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 one clear use case (before/after scenario analysis with `exclude_polygons`) and a compatibility caveat, but never states when to prefer this over `route`, `optimise_routes`, or `reachable_area`. Usage is implied by the many-to-many shape rather than explicitly contrasted with alternatives.
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 does so: it discloses the MapMap gateway auth requirement (GATEWAY_URL + GATEWAY_API_KEY), that unknown categories/names return an empty list rather than an error, default/max values, the direction-vs-cardinal fallback, and the meaning of out_of_view. The note about preferring to read `direction` aloud and reporting out_of_view rather than "nothing nearby" is behavioral guidance an agent could not infer elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the geocode contrast, then required inputs, then optional params and return shape; each sentence is informative. It is, however, a dense wall of prose with some duplication of the schema (fov_deg, category normalisation), which costs it the top mark.
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 8-parameter tool with no annotations, the description covers auth, required inputs, defaults, ordering, units, edge-case error behavior and viewpoint-dependent phrasing. An output schema exists, yet the description still orients the agent on how to use results, so nothing needed to call 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 description coverage is 100%, so the schema already documents every parameter including colloquial category normalisation and fov_deg width semantics. The description adds some cross-parameter meaning (combining category+name to disambiguate a brand), but largely restates schema content, so 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?
Opens with a specific verb+resource+ordering+units: "Find places near a point, nearest first with distance in metres, by category ... by name ... or both." It explicitly contrasts itself with the sibling geocode, so an agent can distinguish the two without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the exact condition for choosing this tool over geocode ("whenever the question is about what is NEAR a location") and explains the failure mode geocode has (returns a branch in another city over the one 100 m away). It also states the input precondition: provide lat, lon and at least one of category or name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nearby_stopsAInspect
England bus and coach stops near a point, nearest first. Pass lat and lon (WGS84), optional radius_m (1 to 2,000, default 500) and limit (1 to 50, default 10). Each stop carries its NaPTAN ATCO code id (pass it to next_departures), name, indicator (e.g. "Stop S"), locality, position, distance_m and bearing_deg from the point, and lines, the line names the Bus Open Data timetables have calling there. Bus and coach only: rail, tram, metro and ferry stops are not included, and coverage is England (plus stops just across a border that an England service calls at). Display data, never a journey plan: pass on the returned label and coverage. Requires the MapMap gateway; a deployment without the stops index answers a clear error. Display the returned attribution (NaPTAN and BODS, Open Government Licence v3.0).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude of the point, WGS84 degrees. | |
| lon | Yes | Longitude of the point, WGS84 degrees. | |
| limit | No | Most stops to return, 1 to 50 (default 10), nearest first. | |
| radius_m | No | Search radius in metres, 1 to 2,000 (default 500). |
Output Schema
| Name | Required | Description |
|---|---|---|
| label | Yes | What the answer is and is not: display data, never a journey plan or an arrival prediction. Pass it on with the stops. |
| stops | Yes | Stops inside the radius, nearest first. |
| coverage | Yes | What the data covers (England bus and coach stops; no rail, tram or ferry). Pass it on with the stops. |
| attribution | Yes | NaPTAN and BODS attribution (Open Government Licence v3.0): display it with the stops. |
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 and does so well: it discloses coverage (England plus border stops), the gateway dependency and the exact failure behavior ('a deployment without the stops index answers a clear error'), and the attribution/licence obligation. That is richer than a typical read-only tool description.
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 required inputs are front-loaded in the first two sentences, and each sentence carries real information. It is dense to the point of enumerating every returned field even though an output schema exists, which is the one place words could be spared.
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 4-parameter lookup with an output schema, the description covers everything an agent needs: input contract, mode and geographic coverage, error posture, downstream chaining, and display obligations. Nothing material is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already spells out WGS84, the 1-to-50 limit and default 10, and the radius default 500, so the description's parameter text is largely a restatement. It adds the tighter '1 to 50' bound for limit versus the schema's declared maximum of 255, which is informative but also a minor inconsistency.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('bus and coach stops near a point, nearest first') plus geography and mode scope, which cleanly separates it from nearby_places and next_departures in the sibling list. An agent can tell what it 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?
Gives the invocation condition (pass lat/lon), the exclusions (rail, tram, metro, ferry not included) and a chaining instruction (pass the returned id to next_departures). It never names a sibling as the alternative for the excluded modes, so it stops just short of full when/when-not/alternatives guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
next_departuresAInspect
Timetabled bus departures at one stop, from the Bus Open Data (BODS) timetables. Pass stop (the NaPTAN ATCO code nearby_stops returns), optional at (RFC 3339, default now; the index holds three service days from today), window_minutes (1 to 180, default 60) and limit (1 to 30, default 8). Each departure carries line, destination, operator, scheduled_at (local time) and trip, plus live when a vehicle on that line was seen in the live positions within 3 km and heading towards the stop (vehicle, distance_m, age_s). These are TIMETABLE times: basis is always "timetable", and a live entry is an observation, never an arrival time or a delay. MapMap does not predict arrivals: never present scheduled_at or live as one, and pass on the returned label and coverage verbatim. Requires the MapMap gateway; a deployment without the departures index answers a clear error. Display the returned attribution (NaPTAN and BODS, Open Government Licence v3.0).
| Name | Required | Description | Default |
|---|---|---|---|
| at | No | Start of the window, RFC 3339 (e.g. "2026-10-12T08:00:00+01:00"); default now. The index holds three service days from today. | |
| stop | Yes | The stop's NaPTAN ATCO code, as `nearby_stops` returns it. | |
| limit | No | Most departures to return, 1 to 30 (default 8). | |
| window_minutes | No | Window length, 1 to 180 minutes (default 60). |
Output Schema
| Name | Required | Description |
|---|---|---|
| stop | Yes | The stop. |
| basis | Yes | Always "timetable". |
| label | Yes | The honesty line, verbatim: timetable times, what a live entry is, and that MapMap does not predict arrival times. Pass it on with the departures. |
| coverage | Yes | What the data covers. Pass it on with the departures. |
| departures | Yes | Departures in timetable order. |
| attribution | Yes | NaPTAN and BODS attribution (Open Government Licence v3.0). |
| generated_at | No | When the answer was assembled, RFC 3339. |
| timetable_date | No | The service date the requested time falls on, YYYY-MM-DD. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full load and does so well: `basis` is always 'timetable', a `live` entry is an observation (within 3 km and heading towards the stop) never an arrival time or delay, the tool never predicts arrivals, the index spans three service days, and the gateway error behavior is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then params, then the critical 'do not present as arrival times' caveat. It is a dense single paragraph and slightly long, but nearly every sentence earns its place (semantics, limitation, attribution requirement).
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 an output schema existing, the description supplements it with usage-critical semantics (what `live`/`basis` mean) and obligations (attribution display, verbatim label/coverage). Nothing an agent needs to call and interpret this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters including defaults and ranges. The description largely repeats these (stop code source, three-day index, 1-180/default 60, 1-30/default 8) without adding format or syntax beyond the schema, so 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?
States a specific verb+resource ('Timetabled bus departures at one stop') and names its data source (BODS timetables). This clearly distinguishes it from nearby_stops (stop lookup) and route_observations (live positions), so an agent can pick it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It chains to a sibling ('the NaPTAN ATCO code nearby_stops returns'), states the gateway prerequisite, and warns that a deployment without the index errors out. It does not explicitly contrast when to prefer this over other departure/route tools, but the usage context is clearly conveyed.
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. Returns view_url, a mapmap.ai link that draws the answer on a map (no key needed); the link carries the stop coordinates and names.
| 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. |
| view_url | No | A mapmap.ai link that draws this fleet plan, one route per vehicle, on a map: open it or pass it on as the last line of the answer. Nothing is stored server-side and opening it needs no key; the link itself carries the stop coordinates and stop names (plus any arrival clocks, dwell times and totals) and nothing else, so anyone holding it can read those stops. Absent when the plan cannot be linked (see `view_url_note`) or the server runs with links turned off (`SN_MCP_SITE_URL` empty). |
| 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. |
| view_url_note | No | Why there is no `view_url` (too many vehicles or stops for one link, or over the 6,000 character cap), or what the link left out to fit under the cap (arrival times, dwell times, then stop names). Relay it with the link. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden and does so unusually well: it discloses billing ('bills as two solves when the second one runs'), the fact that the tool refuses rather than silently ignoring gateway features, that the reload split is fixed before the solve and therefore conservative, that max_trips is a budget not a prediction, and that relaxation is capped at one extra solve and only returned if it assigns more work. Auth/permission requirements and any rate limits beyond 'fair use' are not stated, which keeps it short of a 5.
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 critical facts are front-loaded (what it is, then inputs, then limits), but the body is a dense wall of text with conversational asides ('cargo-bike and courier fleets welcome', 'the tipping round', 'it cannot put a lorry in two places at once') that cost scanning time. Much of the reloads/relaxation material is also duplicated in the schema field descriptions, so the length is not fully earned.
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 VRP tool with nested specs, an output schema, and no annotations, the description covers every capability surface an agent needs: input shapes, the truck/ADR legality consequence, territories, reloads, relaxation, emissions zones, the gateway precondition, billing, and the returned view_url. Nothing material to a 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 baseline is 3; the description climbs above it by explaining cross-parameter semantics the schema cannot state per-field — how territory_ids interacts with territories (unrestricted when empty), how emissions+avoid_zones changes the matrix rather than merely annotating, and how relax_if_unassigned interacts with the first solve. This is interpretive value on top of documented 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?
Opens with a specific verb+resource and scope: 'Optimise multi-vehicle, multi-stop delivery plans (VRP)', then enumerates the input shapes (vehicles/jobs/shipments). It explicitly distinguishes itself from three siblings by name — cluster for splitting oversized problems, submit_optimise_job for the async lane, and replan_routes for post-tip tightening — so an agent can route to the right tool without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use and when-not guidance: the 200-location / matrix-span fair-use ceiling and the fallback ('cluster the stops … or submit the whole problem to the asynchronous lane'), plus the requirement to re-plan with replan_routes after each reload. It also states the precondition that territories/reloads/relaxation/zones need a configured MapMap gateway.
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 full burden. It discloses the output shape (visit order, arrival offsets in seconds, total duration/distance) and the end-vs-round_trip relationship, but says nothing about permissions, rate limits, cost of computation, or solver behavior on infeasible 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?
Front-loaded with the core action, then inputs, then return values, in a compact block with no filler. Slightly dense but every clause carries purpose or usage 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?
An output schema exists and the rich input schema is fully described, so the description's remaining need is minimal. It covers inputs and outputs adequately, though it omits failure modes and invocation prerequisites.
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 six parameters thoroughly. The description restates the costing values and stop structure rather than adding new semantics beyond what the schema provides, so it sits at 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 gives a clear verb+resource ('Put a single run's stops in the best visiting order') and scopes it to a single vehicle run. However, it never distinguishes itself from plausible siblings like plan_errands, optimise_routes, or matrix, so an agent must infer the boundary.
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 context is implied via 'single run's stops' and the reference to passing `truck` as in `route`, but there is no explicit when-to-use guidance, no exclusion of the multi-route siblings, and no note on inputs that make it fail (e.g. >100 stops).
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. Returns view_url, a mapmap.ai link that draws the answer on a map (no key needed); the link carries the stop coordinates and names.
| 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. |
| view_url | No | A mapmap.ai link that draws this day plan on a map: open it or pass it on as the last line of the answer. Nothing is stored server-side and opening it needs no key; the link itself carries the stop coordinates and stop names (plus any arrival clocks, dwell times and totals) and nothing else, so anyone holding it can read those stops. Absent when the plan cannot be linked (see `view_url_note`) or the server runs with links turned off (`SN_MCP_SITE_URL` empty). |
| 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. |
| view_url_note | No | Why there is no `view_url` (too many vehicles or stops for one link, or over the 6,000 character cap), or what the link left out to fit under the cap (arrival times, dwell times, then stop names). Relay it with the link. |
| 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 and does reasonably well: it discloses that `optimise` depends on the VROOM solver ("requires the optimisation sidecar"), that geocoded names return a `resolution` and should be re-run with explicit coordinates when `ambiguous`, and that `view_url` encodes stop coordinates/names with no key required. It does not mention rate limits, quota, or error behavior, keeping it short of a 5.
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 purpose, then walks through inputs and return shape in a logical order, and every clause carries information. It is dense and somewhat long, with some redundancy against the schema (re-listing costing values and truck restrictions), which keeps it from 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 7-parameter planning tool with an output schema, the description is comprehensive: inputs, ordering behavior, geocoding ambiguity handling and the map link are all covered, and return values are explained (though the output schema already covers them). With no annotations, a brief note on permissions/cost or failure modes would be the only remaining gap.
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 same parameter facts already documented in the schema (costing list, truck profile, optimise/VROOM, depart_at semantics) rather than adding new syntax or default guidance, so it earns no more than 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?
Opens with a specific verb+resource+scope: "Turn an itinerary into one navigable multi-stop route," which is immediately distinguishable from siblings like `route` (single route), `order_stops`/`optimise_routes` (pure ordering) and `plan_errands`. The description also enumerates the distinguishing capabilities (dwell time, ETAs, optimise via VROOM) so an agent can tell what makes this tool different without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the feature set (multi-stop itinerary, dwell_minutes, depart_at, return_to_start) makes the intended scenario inferable, but there is no explicit "use this when / use X instead when" routing against close siblings such as `plan_errands`, `order_stops`, or `route`. No exclusions or prerequisites are given.
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, the description carries the full burden and does so: it discloses that infeasible outcomes are answers (`feasible: false`, `reason`, furthest reachable point) not retryable errors, warns about `gradient_data` = absent, mandates surfacing `coverage_note` and `charging_attribution`, and notes `availability_live` for status currency plus the MapMap gateway dependency and no-dataset error. This is exactly the operational context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and required inputs, then tiers down into modelling detail and output caveats. It is long and occasionally dense, but nearly every sentence carries distinct behavioural information rather than padding.
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 an 11-parameter schema and a nested vehicle object, the description covers what the agent must know that structured fields cannot express: infeasibility semantics, coverage limitations, elevation caveat, and the required display of attribution. With an output schema present, it rightly avoids explaining return values and focuses on 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 genuine meaning beyond it: it clarifies that `reserve_soc` is the mid-route floor distinct from arrival SOC, that `connectors` only narrows the vehicle's own set, and that `profile` acts as a base overridden by inline figures. The numeric defaults it repeats are already in the schema, so it does not reach the top band.
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 ("Plan a whole electric-vehicle journey, charge stops included") and the follow-up distinguishes it from plain routing by emphasizing charge-stop insertion and physics-based energy modelling. An agent can tell this apart from `route`, `optimise_routes` and `cheapest_charging_along_route` without opening any 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 gives clear context for invocation (give origin/destination plus a vehicle, defaults for the SOC knobs) and strong when-not guidance around infeasible results. It stops short of explicitly naming sibling alternatives such as `cheapest_charging_along_route` or `route`, so the routing is implied through scenario rather than stated.
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 to 4 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. The origin is first moved onto the nearest road the travel mode can use (ferries excluded, at most 5 km away) and the rings are drawn from there: snapped_origin {lat, lon, distance_m} on the collection and on every feature's properties says where. An origin with no road within 5 km (open sea, desert, an unmapped area) is refused with "no roads near this point" rather than answered with a speck, and that refusal is not billed; move it onto land near a road. 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 to 4 values (the routing engine's limit), 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, drawn from the origin snapped onto the nearest usable road: the collection's `snapped_origin` `{lat, lon, distance_m}` (repeated on every feature's properties) says where that was. |
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: origin snapping to the nearest usable road (ferries excluded, 5 km cap), snapped_origin reporting on collection and features, the refusal case 'no roads near this point' with the notable detail that it is not billed, and engine applicability (Valhalla-only, ignored on GraphHopper). These are exactly the behaviors an agent cannot infer from 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?
Purpose and primary parameters are front-loaded, and most sentences earn their place by adding behavioral detail. It is dense and long for a single paragraph, and the exclude_polygons engine caveat is echoed twice, which slightly dilutes the structure.
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 spatial tool with 5 parameters, required fields, and an output schema already covering return values, the description still supplies all the preconditions an agent needs: snapping, refusal semantics, engine support, and output feature granularity (one feature per contour). 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 description coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: the before/after scenario rationale for exclude_polygons ('close this bridge and recompute'), the longitude-first ring convention, and the polygons true/false render-layer distinction. It goes past restating the schema rather than just duplicating 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 opens with a precise verb+resource: 'Compute the area reachable from an origin within one or more travel-time budgets.' It further grounds this with concrete framing (walkability/cyclability rings, isochrone-style output) that separates it from geometric siblings like geo_area, geo_bbox or geo_length.
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 strong contextual guidance via concrete questions ('how far can I walk in 15 minutes?', delivery coverage) and explains what each costing selects. However, it names no alternative sibling tool or an explicit when-not-to-use condition (e.g. single-point routing should use route instead), so it stops short of full routing guidance.
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. |
| view_url | No | A mapmap.ai link that draws this fleet plan, one route per vehicle, on a map: open it or pass it on as the last line of the answer. Nothing is stored server-side and opening it needs no key; the link itself carries the stop coordinates and stop names (plus any arrival clocks, dwell times and totals) and nothing else, so anyone holding it can read those stops. Absent when the plan cannot be linked (see `view_url_note`) or the server runs with links turned off (`SN_MCP_SITE_URL` empty). |
| 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. |
| view_url_note | No | Why there is no `view_url` (too many vehicles or stops for one link, or over the 6,000 character cap), or what the link left out to fit under the cap (arrival times, dwell times, then stop names). Relay it with the link. |
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 and discharges it: statelessness ('nothing is stored', no dispatch state/plan/position/log), the reason for the round-trip cost (stale/leaking server-side plan), reproducibility guarantees, the locked-prefix invariant, the required MapMap gateway, and the billing model ('Billed on the remaining problem'). This is unusually complete behavioral disclosure for an unannotated mutation 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 correctly — purpose in sentence one, mechanics after — but it is roughly twice as long as needed, with rhetorical filler ('rather than left for a dispatcher to notice at four in the afternoon', 'a guarantee the solver cannot break, rather than a hint it is free to ignore') that a dispatcher-facing agent does not need to select or call 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?
For an 11-parameter, stateful-ish tool with no annotations, the description covers selection, prerequisites, refusals, billing, and even previews the non-standard `replan` output block (prefix, releases, forced-unassigned, unresolved ids). An output schema exists, so return values need not be fully specified, yet the description still gives the agent enough to interpret the response.
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 structured baseline is 3, but the description adds framing the schema does not: that the ORIGINAL problem must be passed in full (not a delta), and how progress/changes interact with the gating rule. It restates some schema-documented field semantics (ordered completed_stop_ids), so it edges just above baseline rather than fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Re-plan a fleet part-way through its shift,' immediately distinguishing it from the sibling optimise_routes by framing it as a mid-shift variant. An agent can select this tool from the name-plus-first-sentence 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?
Explicitly states the preconditions ('you pass the ORIGINAL optimise_routes problem in full, plus progress and/or changes'), the gating rule ('At least one progress entry or one change is required'), and an exclusion ('Multi-trip vehicles cannot be re-planned... refused with what to send instead'). It names the alternative tool and the conditions that select this one over it.
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, the description carries the full burden and does so well: it declares the report is QUEUED for human/agent review, NEVER changes routing immediately, and NEVER edits any map, and it names the return value (queued report_id). These are exactly the behavioral facts an agent needs before calling a write-looking 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 purpose, then the safety semantics, then the parameter summary — a sensible order. The enumeration of all seven category values duplicates the schema's const definitions and is the one clearly redundant passage.
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 are covered elsewhere, and the description supplies the missing behavioral context (queued, non-mutating, first-party observation) plus required vs optional parameters. Nothing an agent needs to call this correctly is absent.
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 location, category, way_id, description, and evidence_url in detail. The description largely restates the parameter list (including the category values already defined as schema consts), adding only optionality framing, so 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?
States a specific verb (report) and resource (a live-world/map mismatch), and enumerates concrete mismatch kinds that pin down the scope. It is clearly distinguishable from edit-style siblings like set_temporary_closure or validate_geodata.
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 says when to use it ('when you observe the mismatch mid-task') and carefully states the effect is queued and does not change routing, which implicitly contrasts with closure- or edit-type tools. However, it never names an alternative tool or an explicit when-not-to-use condition, which matters given set_temporary_closure and validate_geodata in the sibling set.
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, the description carries the full burden and does well: it discloses ordering (nearest first), default/max limits, that fov filtering silently drops results counted in 'out_of_view', and the fallback from heading-relative to cardinal phrasing. It does not mention auth, quota or error behavior, but this is a read-only lookup with no side effects implied.
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 is front-loaded and the rest is information-dense rather than padded, but the long multi-clause sentences with nested parentheticals are heavy going, and the heading/fov mechanics are repeated verbatim in 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?
Output schema exists, so return values need not be spelled out, yet the description enumerates the payload (name, label, type, address parts, distance_m, bearing_deg, direction, details tags). Combined with the filtering and fallback rules, an agent has everything needed to call it correctly; only cross-tool routing is thin.
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's heading_deg and fov_deg explanations largely restate the schema text; the only added value is the presentation hint to read 'direction' aloud instead of coordinates, which does not change invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('turn coordinates into the nearest places: addresses, POIs and localities with distance in metres') and immediately positions it against the sibling geocode ('The inverse of geocode'). An agent can distinguish it from nearby_places, geo_nearest_point_on_line and other point-query tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: supply lat/lon, results come nearest-first, and the heading/fov knobs are optional so 'this works with or without a compass'. It does not, however, say when to prefer this over alternatives such as nearby_places or geocode, so there are no explicit exclusions.
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, use_hills 0-1, max_grade_pct 1-90, surface_quality "avoid"|"ignore"} for lit-street walking, wheelchair routing and trail limits. A wheelchair route through the MapMap gateway returns a grade block (maximum grade, ascent and descent sampled from a 30 m elevation model, the use_hills preference sent, and cap.enforced for a max_grade_pct, which the engine accepts but does not enforce yet: say so) and, where the deployment has a surface graph, a surface_quality block: applied: true means ways rated smoothness bad or worse in OpenStreetMap were avoided in the named region, a preference from ratings where they exist that says nothing about kerbs, widths, steps or inclines; applied: false gives the reason. Relay both caveats and never describe such a route as suitable for every user; 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. Returns view_url, a mapmap.ai link that draws the answer on a map (no key needed); the link carries the stop coordinates and names.
| 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 |
|---|---|---|
| grade | No | The hill report on a pedestrian route (only through the MapMap gateway): maximum grade, total ascent and descent sampled along the route from the elevation model, the hill preference sent, and whether a requested grade cap was enforced. Relay `cap.enforced` and the caveat as given. |
| 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. |
| view_url | No | A mapmap.ai link that draws this route on a map: open it or pass it on as the last line of the answer. Nothing is stored server-side and opening it needs no key; the link itself carries the stop coordinates and stop names (plus any arrival clocks, dwell times and totals) and nothing else, so anyone holding it can read those stops. Absent when the plan cannot be linked (see `view_url_note`) or the server runs with links turned off (`SN_MCP_SITE_URL` empty). |
| 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. |
| view_url_note | No | Why there is no `view_url` (too many vehicles or stops for one link, or over the 6,000 character cap), or what the link left out to fit under the cap (arrival times, dwell times, then stop names). Relay it with the link. |
| surface_quality | No | Surface quality on a wheelchair route (only through the MapMap gateway): `applied` true with the region, the exact rule, the data timestamp and a caveat when the route was computed on the surface graph; `applied` false with a `reason` otherwise. Relay the caveat: it is a preference from OpenStreetMap ratings where they exist, and says nothing about kerbs, widths, steps or inclines. |
| 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 behavioral burden and does so thoroughly: it distinguishes preference (`avoid`) from hard exclusion (`exclude`) including the Dartford Crossing and Rotherhithe examples, discloses that `max_grade_pct` is accepted but not enforced, that exclusion depends on an unreadable `allow_hard_exclusions` flag, that gateway credentials are required for several features, and the metered cost of `rationale` and `scenic`. Refusal behaviors (no window, unsupported avoid features) and no-route outcomes are also disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, but the body is an extremely long, densely parenthetical wall of text that frequently duplicates content already present in the 100%-covered schema and the output schema (e.g. the kerbside window, ADR honesty, scenic rejection codes are all restated). For a 14-parameter call the agent must wade through far more prose than the decision requires, so size and redundancy drag this down.
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 multi-costing routing tool with no annotations, the description covers everything an agent needs: engine/gateway dependencies, engine-specific limitations, cost of opt-in flags, honesty caveats, and what several response blocks mean. With an output schema present it need not explain return values, yet 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, but the description adds genuine meaning beyond the schema: it explains why `avoid` and `exclude` differ behaviourally, what the kerbside preference actually resolves against, that `exclude_polygons` is ignored on GraphHopper, and what `emissions` unlocks. These are semantic distinctions the schema fields alone do not 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?
The opening sentence gives a specific verb and resource: "Compute a turn-by-turn route between origin and destination (optionally via waypoints)." It tells the agent exactly what comes back and the origin/destination/waypoint shape. It does not, however, differentiate itself from routing-adjacent siblings like optimise_routes, matrix, replan_routes or reachable_area, so the agent must infer when this tool rather than another is correct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is extensive conditional guidance for the optional features: "Use `exclude` when you mean a ban", avoid applies only to motorised costings, scenic is auto-only, exclude_polygons is Valhalla-only, emissions is needed to price rather than merely name a zone. That is strong when-to-use guidance at the parameter level. It gives no guidance on selecting this tool over sibling routing tools, which is the one gap.
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?
No annotations, so the description carries the full burden. It discloses the detour formula, the candidate_cap of 25 priced per call, the matched_categories echo, costings supported, and server-side normalisation of colloquial phrases. It omits auth/permission needs and rate limits, but for a read-only search this is strong 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?
Front-loaded with purpose, but it is one very dense block that packs normalisation rules, costing notes, and return fields together. Every claim is relevant, yet the structure makes it hard to skim for the parameter guidance an agent needs.
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 need not be spelled out, yet the description still summarises detour_minutes, detour_km, along_route_position and off_route_m. Combined with the routing/costing context, this is complete enough to call the tool correctly 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 value beyond the schema: the origin+destination / geometry_polyline6 mutual exclusion, category normalisation rules, and the query-promotes-to-category behaviour are behaviour the schema does not express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (find POIs along a route) with a differentiating angle: real detour time rather than straight-line distance. An agent can distinguish it from nearby_places (area search) and from cheapest_fuel_along_route / cheapest_charging_along_route (cost-optimised searches).
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 conditions for choosing origin+destination vs geometry_polyline6, and for category vs query ("For a category intent ... pass category instead of relying on words alone"). It names nearby_places as the vocabulary source but never states when a sibling like nearby_places would be the better tool, so it stops short of full alternative routing.
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.
space_weather_nowAInspect
The planetary Kp index and the NOAA SWPC OVATION aurora forecast right now. No input. Returns kp (0 to 9) with its time, the forecast's valid time, the peak aurora probability and aurora_png_url (a 360 by 181 probability grid, percent per pixel, column 0 at 180 W, row 0 at 90 N) when the forecast is under an hour old; status is unavailable when it is older and nothing should be drawn. A FORECAST about 30 to 90 minutes ahead, not an observation; never present it as a sighting or a guarantee. Requires the MapMap gateway. Display the returned attribution; no endorsement by NOAA is implied.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| kp | No | Planetary Kp index, 0 to 9. |
| age_s | No | Seconds since the forecast time when the answer was assembled. |
| label | Yes | "Forecast, not an observation". Pass it on. |
| status | Yes | `ok`, `unavailable` (the forecast is over an hour old: draw nothing) or `unknown` (no data). |
| kp_time | No | When the Kp value applies (RFC 3339 UTC). |
| summary | Yes | One sentence for the answer. Pass it on with its qualifier. |
| attribution | Yes | NOAA SWPC credit. Display it. |
| endorsement | Yes | No endorsement by or affiliation with NOAA is implied. |
| threshold_s | Yes | The age in seconds after which the forecast is unavailable. |
| forecast_time | No | The time the aurora forecast is valid for (RFC 3339 UTC). |
| aurora_png_url | No | URL of the 360 by 181 probability grid (percent per pixel, column 0 at 180 W, row 0 at 90 N); present only while the forecast is fresh. Needs the caller's own MapMap key. |
| max_probability | No | Peak aurora probability anywhere on the grid, percent. |
| observation_time | No | The observation the forecast was made from (RFC 3339 UTC). |
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 substantial work: it discloses that `status` becomes `unavailable` when the forecast is over an hour old, that the data is a forecast rather than an observation, and that the MapMap gateway is required. It omits rate limits, caching, or failure modes beyond staleness, keeping it short of a 5.
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 resource identity, then layers return fields, caveats, and obligations. Every sentence carries information, though the mid-section mixing return-field documentation with caveats makes it slightly denser than ideal.
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, yet the description still adds useful value by explaining the aurora grid geometry (360x181 percent-per-pixel, column 0 at 180 W, row 0 at 90 N) and the staleness branch. Combined with the no-input declaration, attribution requirement, and forecast-not-observation warning, nothing an agent needs to call and interpret this tool 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 takes zero parameters, so per the rubric the baseline is 4. The description correctly states 'No input' rather than leaving the agent to infer it, and there are no parameter semantics left to clarify.
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 specific resources (the planetary Kp index and the NOAA SWPC OVATION aurora forecast) and a specific temporal scope ('right now'), making it immediately distinguishable from terrestrial-weather siblings like weather_along_route and weather_frames. An agent knows exactly what domain this serves 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 clear situational context ('right now', a forecast 30-90 minutes ahead, not an observation) and instructs the agent on how to present results ('never present it as a sighting or a guarantee', 'Display the returned attribution'). It stops short of explicitly naming when to prefer a sibling tool or stating hard exclusions, so it is clear but not fully routing-aware.
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 zero annotations, the description carries the full behavioral burden and does so: it discloses exactly what data leaves the client ('ONLY the structured fields in this schema'), enumerates what is NOT transmitted (transcript, prompt, source code, file contents, coordinates), and warns that free-text caps do not make pasting code/credentials/customer names/PII safe. This is precisely the disclosure a no-annotation tool needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded: the call-condition and data-boundary constraints come before any field listing. The final sentence restates the schema's field list with 100% coverage and is the one semi-redundant part; everything earlier 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?
An output schema exists, so return values need not be explained. Given that, the description covers the trigger condition, the once-only cap, the consent prerequisite, the data-exfiltration boundary, and the payload shape — nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description goes slightly further by flagging which field is required, showing the shape of the nested problem object (area/description/workaround_found) and its enum values, and noting the optional fields. It largely mirrors the schema rather than adding new semantics like format or examples, so it stays just above 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 first sentence states a specific verb (Send), recipient (MapMap), and resource (structured integration retro) plus the exact content categories (problems, gotchas, wins, docs gaps). No sibling tool covers the same ground, and the retro semantics are unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to call ('after your MapMap integration works or you stop trying'), the frequency cap ('at most once'), and a hard prerequisite ('only if the developer has approved sending feedback to MapMap'). There is no competing alternative tool for this task, so no routing guidance is owed.
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 carries the full burden and does so: it discloses the 202-and-job-id return semantics (not a plan), the polling loop via get_job until terminal status, that polling is free while submission is metered, that units are refunded in full on failure, that unknown fields are refused by name, the exact ceilings (2,000 locations / 40,000 matrix elements) versus synchronous caps, and that webhook delivery requires a signing secret. This is unusually complete behavioral context for a mutation/queueing 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 front-loaded with purpose and return semantics, and most sentences carry distinct information (ceilings, refunds, refusal-by-name, webhook guidance). There is minor redundancy, e.g. the 'moving a synchronous call changes nothing' point appears both in the description and again in the problem schema field.
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 need not be explained, yet the description still clarifies that the immediate answer is a job id rather than a plan and describes the polling path to the result. For a 3-parameter async submission tool with real consequences (metering, refunds, queuing), nothing an agent needs to call 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 description coverage is 100%, so kind, problem, and webhook_url are already fully documented in the schema, and the description largely restates that content (kind selects body shape, problem mirrors the synchronous input, webhook is https-only and signed). It adds little parameter detail the schema does not already carry, so 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 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') and explicitly contrasts itself with the synchronous siblings optimise_routes, replan_routes, and matrix. An agent can distinguish this tool from those without opening any 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 explicit when-to-use criteria (problem too large for a single request), names the three synchronous alternatives and the exact shape each maps to, and states the migration rule ('changes nothing but which tool you call it with'). It also gives a when-not-to-use for webhook_url ('An agent that can poll should not use it').
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 carries the full burden and meets it: it discloses the return shape (verdict consistent/suspect/impossible plus plain-language explanation), the local no-network/no-quota execution model, and the absolute guarantee that coordinates are never transformed. Nothing about the tool's behavior is left implicit.
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 longer than average but front-loaded with purpose and every clause adds information — failure modes, the not-a-reprojection boundary, return values, and compute profile. Slightly dense, but no sentence is 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 two-parameter, deterministic check with an output schema, the description covers purpose, boundary conditions, input semantics, and execution model. An agent has everything needed to decide and 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 baseline is 3, but the description adds genuine meaning beyond the schema: that coordinates must be supplied in the dataset's OWN units, the rationale for x/y naming ('whether they are degrees is the question'), and the sampling sufficiency ('a few dozen is plenty').
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 and resource — checking whether a declared CRS actually describes a dataset's coordinates — and names the specific failure classes it catches (swapped axes, degrees-as-metres, mislabelled projections). It also explicitly distinguishes itself from reprojection tools, so no sibling is confusable.
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 a clear trigger ('before you draw it on a map') and a strong when-not ('This is a sanity check, not a reprojection: it never transforms coordinates'). It does not name a specific sibling alternative, but no sibling performs CRS validation, so the guidance is sufficient.
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. A claim takes only id, name, locality, sequence and claimed_time; any other field (e.g. near) is refused naming the accepted ones, so put disambiguating context such as a town in locality. 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, the description carries the full burden and does so: it enumerates the three verdicts, forbids boolean returns, discloses the defamation-driven rule that a missing match is always 'unverified' (never 'does not exist'), names the only contradiction case, describes the sequence+claimed_time leg mechanics, and warns that unknown fields are refused with the accepted list.
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, then the two input paths, then verdict semantics, then constraints and the summary fallback – a sensible front-loaded order. It runs long and repeats the leg-feasibility rule that the schema also states, which keeps it short of maximally tight.
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 non-trivial verification tool with an output schema, the description supplies everything the schema cannot: verdict semantics, the never-assert-nonexistence policy, the one contradiction path, the 20-claim and 8,000-char limits, and the text-content `summary` fallback for clients that drop structured blocks.
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 interpretation: it restates the accepted claim fields, explains that `near` is refused and disambiguating context belongs in `locality`, and ties `sequence`/`claimed_time` to leg building. Much of this overlaps with the schema's own field descriptions, so the marginal gain is real but not large.
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+scope: 'Check whether places (and itineraries) an AI mentioned are real, findable and physically possible.' The three-verdict model and the itinerary-feasibility angle clearly separate it from siblings like nearby_places, geocode and matrix, which it references as an internal component rather than a peer.
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 frames the two entry paths and when each applies: structured `claims` is 'reliable, and the only path that supports itinerary feasibility', while free `text` is 'best-effort quoted-phrase extraction'. It also states the mutual exclusion and the 20-claim limit, so selection between the modes is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
weather_along_routeAInspect
Forecast weather along a route, each sample read for the hour you actually reach it rather than the weather right now. Pass the route's shape (an encoded polyline6, the route tool's geometry_polyline6), optional depart_at (RFC 3339, default now), the route's duration_s (from route; omitted, an 80 km/h average is assumed and duration_source says so) and optional sample_interval_m (default 25,000, 5,000 to 100,000, at most 40 samples). Each sample carries its ETA, temperature, rain, snowfall, precipitation type and probability, wind and gust speed, visibility, the WMO weather code and severe (thunderstorm and heavy precipitation codes only). It is a FORECAST, not an observation: read on a 0.05 degree grid (about 5.5 km) at the nearest hour, up to 16 days ahead, and samples past that horizon or without data come back available: false with a reason, never painted dry. summary is one sentence (where rain or snow starts and for how far, the strongest gust, samples without data) and always ends by saying it is advisory, never a routing guarantee: keep that qualifier when you pass it on. Requires the MapMap gateway; a deployment without a weather source answers a clear error. Display the returned attribution with the forecast, linked to attribution_url, with licence_url (CC BY 4.0) linked; derived_fields names the sample fields MapMap derives rather than Open-Meteo supplies.
| Name | Required | Description | Default |
|---|---|---|---|
| shape | Yes | The route shape as an encoded polyline6 (the `route` tool's `geometry_polyline6`). | |
| depart_at | No | Departure time, RFC 3339 (e.g. "2026-10-12T14:00:00Z"); defaults to now. Forecasts reach about 16 days ahead; samples past that answer unavailable. | |
| duration_s | No | The route's duration in seconds, used to work out when you reach each sample. Pass the `route` tool's duration; omitted, a generic 80 km/h average is assumed and `duration_source` says so. | |
| sample_interval_m | No | Distance between samples in metres (default 25,000, clamped to 5,000 to 100,000; at most 40 samples per route). |
Output Schema
| Name | Required | Description |
|---|---|---|
| samples | Yes | Route samples, start to end. |
| summary | Yes | One honest sentence describing the samples: where rain or snow starts and for how far, the strongest gust, how many samples had no data. Always ends by saying it is an advisory forecast, never a routing guarantee. |
| depart_at | Yes | The departure time actually used, RFC 3339 UTC. |
| duration_s | Yes | The route duration actually used, seconds. |
| attribution | Yes | Data attribution (CC BY 4.0): display it with the forecast, verbatim. |
| licence_url | Yes | The data licence to link with the credit (CC BY 4.0). |
| severe_ahead | Yes | True when any available sample carries a severe WMO code. |
| derived_fields | Yes | The sample fields MapMap derives rather than reads from Open-Meteo ("precipitation_type", "severe"), so a display can indicate the changes the licence asks to be indicated. |
| attribution_url | Yes | The link the credit carries ("https://open-meteo.com/"): Open-Meteo's licence asks for it next to any place its data is displayed. |
| duration_source | Yes | "provided" or "estimated_default_speed" (an 80 km/h guess: treat the ETAs as approximate). |
| sample_interval_m | Yes | The sample spacing actually used, metres (may be coarser than asked on a long route). |
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: forecast-not-observation semantics, 0.05 degree grid (~5.5 km) at nearest hour, 16-day horizon, samples returned `available: false` with a reason (never painted dry), a mandatory advisory qualifier, gateway dependency with a clear error when no weather source exists, and attribution/licence display obligations. This is exactly the behavioral context an agent needs 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?
Purpose and the key 'hour you reach it' distinction are front-loaded, and every sentence carries novel information with little waste. It is dense and long, with several clauses chained per sentence, but 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?
Despite high tool complexity, the description covers inputs, output fields, failure modes, licensing and safety qualifiers. Since an output schema exists, the description is not obligated to enumerate returns, yet it still gives enough for correct invocation and downstream handling.
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 all four parameters including defaults, clamping and the duration fallback. The description restates the same details (80 km/h assumption, interval range, 40-sample cap) rather than adding new meaning, so 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?
States a specific verb and resource ('Forecast weather along a route') and immediately distinguishes the semantics: each sample is read for the hour you reach it, not current conditions. An agent can differentiate it from siblings like route_observations and search_along_route without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It makes the pipeline explicit by requiring the `route` tool's geometry_polyline6 and duration_s as inputs, and contrasts forecast vs observation. However, it never names an alternative tool or states when this should be chosen over one, leaving that to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
weather_framesAInspect
The NOAA GFS forecast frames MapMap publishes for drawing weather on a map: 17 frames (0 to 48 hours every 3 hours) of the newest run, each with URLs for the global rain, temperature, cloud, gust and sea-level pressure PNG fields (1440 by 721, value-encoded; decode with encodings), the wind field (PNG plus JSON ranges) and XYZ tile templates for rain, temperature and isobars. Optional run (YYYYMMDDHH) and fields. The URLs need the caller's own MapMap key. A FORECAST, not an observation, processed by MapMap from NOAA GFS 0.25 degree data (regridded and quantised): never describe it as original NOAA data or imply NOAA endorsement. status says whether the newest run is fresh. Requires the MapMap gateway. Display the returned attribution.
| Name | Required | Description | Default |
|---|---|---|---|
| run | No | A forecast run as YYYYMMDDHH (UTC), e.g. "2026101700". Default: the newest run. | |
| fields | No | Which fields to return URLs for, any of `rain`, `temp`, `cloud`, `gust`, `mslp`, `wind`, `isobars`. Default: all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| run | Yes | The run time (RFC 3339 UTC). |
| note | Yes | Derived from NOAA GFS and modified by MapMap; no NOAA endorsement is implied. Pass it on. |
| age_s | No | Seconds since `generated_at` when the answer was assembled. |
| label | Yes | "Forecast, not an observation". Pass it on. |
| model | Yes | The forecast model. |
| frames | Yes | The frames, in hour order. |
| run_id | Yes | The run as YYYYMMDDHH. |
| status | Yes | `ok`, `stale` (the newest run is older than the threshold) or `unknown` (no frames). Pass a stale or unknown status on. |
| summary | Yes | One sentence for the answer. Pass it on with its qualifier. |
| encodings | Yes | How to decode each PNG field (unit, scale, offset), verbatim from the manifest. |
| attribution | Yes | NOAA GFS credit. Display it. |
| threshold_s | Yes | The age in seconds after which the frames count as stale. |
| generated_at | Yes | When MapMap published the manifest (RFC 3339 UTC). |
| processed_by | Yes | "MapMap": the data is processed by MapMap. |
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 well: it discloses that callers need their own MapMap key, that the MapMap gateway is required, that values are quantised/regridded, that the `status` field signals run freshness, and that `attribution` must be displayed. That is meaningful behavioral context beyond the schema. It stops short of failure modes, caching, or rate limits, keeping it at a strong 4 rather than 5.
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?
Effectively one dense paragraph that front-loads what the tool returns before the licensing/attribution caveats. Most sentences earn their place (field list, decoding hint, key requirement), though the legal caution ('never describe it as original NOAA data...') is asserted twice and adds bulk.
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, return values need not be explained here, and the description still supplies the operational essentials: auth key, gateway dependency, encoding/decoding, and attribution. It is close to complete for a data-fetch tool, with only edge-case behavior (invalid run, empty fields) left unaddressed.
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 `run` (YYYYMMDDHH, default newest) and `fields` (default all). The description restates the format and defaults but adds no syntax or constraint detail beyond what the schema provides, so the 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 precise verb+resource framing: the NOAA GFS forecast frames MapMap publishes, and enumerates exactly what is returned (17 frames, 0–48h at 3h steps, PNG fields, wind JSON ranges, XYZ tile templates). An agent can immediately distinguish this bulk frame/URL product from point-based siblings like weather_along_route or space_weather_now.
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 disambiguates the data type ('A FORECAST, not an observation') and notes the optional `run`/`fields` defaults, which implies the intended use (fetching map-drawable forecast frames). However, it never names an alternative sibling or states when NOT to use this tool versus weather_along_route, leaving selection largely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
- Changed
reachable_area1 field changed- changed
Output schema / properties / geojson / descriptionPrevious value: -"GeoJSON FeatureCollection of the reachability contours, one\nfeature per requested minute value (each feature's `contour`\nproperty is its minutes), as returned by the routing engine."New value: +"GeoJSON FeatureCollection of the reachability contours, one\nfeature per requested minute value (each feature's `contour`\nproperty is its minutes), as returned by the routing engine, drawn\nfrom the origin snapped onto the nearest usable road: the\ncollection's `snapped_origin` `{lat, lon, distance_m}` (repeated on\nevery feature's properties) says where that was."
2 tool updates
- Changed
reachable_area1 field changed- changed
Input schema / properties / contours_minutes / descriptionPrevious value: -"Contour boundaries in minutes of travel time, e.g. [5, 10, 15]\nfor 5/10/15-minute rings. 1–10 values, each between 0 and 120\nminutes."New value: +"Contour boundaries in minutes of travel time, e.g. [5, 10, 15]\nfor 5/10/15-minute rings. 1 to 4 values (the routing engine's\nlimit), each between 0 and 120 minutes."
- Changed
verify_places3 fields changed- added
Input schema / $defs / VerifyClaimInput / additionalPropertiesAdded value: +false - changed
Input schema / $defs / VerifyClaimInput / descriptionPrevious value: -"One place claim for the `verify_places` tool: a place an AI mentioned,\nto be checked for existence and (as part of an itinerary) feasibility."New value: +"One place claim for the `verify_places` tool: a place an AI mentioned,\nto be checked for existence and (as part of an itinerary) feasibility.\n\nUnknown fields are refused, naming the accepted ones. A dev-lane run\n(19 Oct 2026) passed `near` instead of `locality`; it was silently\ndropped, \"Roman Baths\" matched Ankara, and the itinerary leg became\nuncomputable with nothing telling the caller why." - added
Input schema / additionalPropertiesAdded value: +false
27 tool updates
- Changed
cheapest_charging_along_route5 fields changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Output schema / $defs / ChargerHit / properties / available_now / descriptionPrevious value: -"Whether a bay is free right now. Present only where a live\navailability feed backs the claim — absent means unknown, never\n\"occupied\"."New value: +"Whether a bay is free right now. Present only where a live\navailability feed backs the claim, absent means unknown, never\n\"occupied\"." - changed
Output schema / properties / charging_attribution / descriptionPrevious value: -"Attribution string for the charge-point operators actually\nreturned — display it with the results (a licence obligation)."New value: +"Attribution string for the charge-point operators actually\nreturned, display it with the results (a licence obligation)." - changed
Output schema / properties / coverage_note / descriptionPrevious value: -"**Always present.** What this deployment's charge-point dataset\ndoes and does not cover. An empty `results` means \"none from these\noperators within the budget\" — never \"there are no chargers here\".\nShow this to the user alongside the results."New value: +"**Always present.** What this deployment's charge-point dataset\ndoes and does not cover. An empty `results` means \"none from these\noperators within the budget\", never \"there are no chargers here\".\nShow this to the user alongside the results." - changed
Output schema / properties / note / descriptionPrevious value: -"Why `results` is empty, when it is — the cause, not a bare list."New value: +"Why `results` is empty, when it is, the cause, not a bare list."
- Changed
cheapest_fuel_along_route5 fields changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - 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. Only a fresh price is\neligible, so this is `stale: false` by construction."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:\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."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 / detour_minutes / descriptionPrevious value: -"Extra travel time of refuelling here, in minutes (rounded to 0.1):\n(origin→station) + (station→destination) − (origin→destination),\nall computed by the routing engine — never a straight-line guess."New value: +"Extra travel time of refuelling here, in minutes (rounded to 0.1):\n(origin→station) + (station→destination) − (origin→destination),\nall computed by the routing engine, never a straight-line guess." - changed
Output schema / properties / fuel_attribution / descriptionPrevious value: -"Attribution string for the fuel-price data sources actually\nreturned — display it with the prices (a licence obligation)."New value: +"Attribution string for the fuel-price data sources actually\nreturned, display it with the prices (a licence obligation)."
- Changed
check_adr_tunnel1 field changed- changed
Input schema / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\". Leave unset for a hazmat load of unknown\ncode (conservatively treated as code B)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\". Leave unset for a hazmat load of unknown\ncode (conservatively treated as code B)."
- Changed
cluster4 fields changed- changed
Input schema / $defs / ClusterLocationSpec / properties / load / descriptionPrevious value: -"Optional weight — parcels, kilograms, litres, minutes of service.\nSummed per cluster and reported; constrains the clustering only\nunder `max_cluster_load`."New value: +"Optional weight, parcels, kilograms, litres, minutes of service.\nSummed per cluster and reported; constrains the clustering only\nunder `max_cluster_load`." - changed
Input schema / $defs / TerritorySpec / properties / polygon / descriptionPrevious value: -"The outer ring as GeoJSON `[lon, lat]` positions — longitude\nFIRST. Closed or open; an unclosed ring is closed for you."New value: +"The outer ring as GeoJSON `[lon, lat]` positions, longitude\nFIRST. Closed or open; an unclosed ring is closed for you." - changed
Input schema / properties / max_cluster_load / descriptionPrevious value: -"At most this much summed `load` per cluster; the cluster count is\nderived from it. A load ceiling with lumpy loads is a bin-packing\nproblem and may have no solution at the derived count — the\nresponse says so rather than pretending."New value: +"At most this much summed `load` per cluster; the cluster count is\nderived from it. A load ceiling with lumpy loads is a bin-packing\nproblem and may have no solution at the derived count, the\nresponse says so rather than pretending." - changed
Output schema / properties / basis / descriptionPrevious value: -"The method statement: this is STRAIGHT-LINE clustering. Distances\nare between coordinates, not along roads — two stops either side of\nan estuary look adjacent. Show it. It is the sentence that stops a\ncentroid being read as a plan."New value: +"The method statement: this is STRAIGHT-LINE clustering. Distances\nare between coordinates, not along roads, two stops either side of\nan estuary look adjacent. Show it. It is the sentence that stops a\ncentroid being read as a plan."
- Changed
create_style1 field changed- changed
Output schema / properties / style_id / descriptionPrevious value: -"The generated style id — pass it to `set_palette`,\n`set_layer_paint` and `get_style`."New value: +"The generated style id, pass it to `set_palette`,\n`set_layer_paint` and `get_style`."
- Changed
elevation1 field changed- changed
Output schema / $defs / ElevationSample / properties / elevation_m / descriptionPrevious value: -"Elevation in metres, or `null` when the engine has no DEM tile\ncoverage at this point — Valhalla's own honest value, never a\nguess."New value: +"Elevation in metres, or `null` when the engine has no DEM tile\ncoverage at this point, Valhalla's own honest value, never a\nguess."
- Changed
geocode7 fields changed- changed
Input schema / properties / country / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / housenumber / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / postcode / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeHit / properties / match / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / properties / score_gap / descriptionPrevious value: -"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\"."New value: +"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\"." - changed
Output schema / $defs / GeocodeMatchComponents / descriptionPrevious value: -"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."New value: +"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."
- 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. 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."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
get_style1 field changed- changed
Output schema / properties / theme / descriptionPrevious value: -"The latest theme document — the editable source the next version\nis published from."New value: +"The latest theme document, the editable source the next version\nis published from."
- Changed
get_usage1 field changed- changed
Output schema / properties / month_used_units / descriptionPrevious value: -"Units counted against the monthly quota right now: the very number\nthe quota check enforces on, independent of `from`/`to`. Quota is\nmonthly, so this — not `total_units` — is what to compare with\n`monthly_quota_units`. It includes units recorded but not yet\nwritten to the daily counters, so over a whole-month range it can\nexceed `total_units`; that is not a discrepancy."New value: +"Units counted against the monthly quota right now: the very number\nthe quota check enforces on, independent of `from`/`to`. Quota is\nmonthly, so this (not `total_units`) is what to compare with\n`monthly_quota_units`. It includes units recorded but not yet\nwritten to the daily counters, so over a whole-month range it can\nexceed `total_units`; that is not a discrepancy."
- Changed
match_trace2 fields changed- changed
Input schema / properties / encoded_polyline / descriptionPrevious value: -"The trace as a Google encoded polyline with six digits of decimal\nprecision (polyline6) — the geometry `route` and `match_trace`\nthemselves return. Provide this or `shape`."New value: +"The trace as a Google encoded polyline with six digits of decimal\nprecision (polyline6), the geometry `route` and `match_trace`\nthemselves return. Provide this or `shape`." - changed
Output schema / properties / by_admin / descriptionPrevious value: -"Distance and time by administrative area, longest first. An entry\nwhose codes are all null covers segments the graph could not place\nin any admin area — counted honestly rather than guessed at."New value: +"Distance and time by administrative area, longest first. An entry\nwhose codes are all null covers segments the graph could not place\nin any admin area, counted honestly rather than guessed at."
- Changed
matrix2 fields changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Input schema / properties / exclude_polygons / descriptionPrevious value: -"Areas to avoid — scenario analysis (\"close this bridge and\nrecompute the matrix\"): an array of polygons, each an array of\n`[lon, lat]` pairs forming one exterior ring (GeoJSON-style,\nlongitude FIRST). Roads intersecting any ring are excluded from\nevery cell's path finding. Applies to the Valhalla engine;\nunsupported on the GraphHopper engine, where it is ignored."New value: +"Areas to avoid, scenario analysis (\"close this bridge and\nrecompute the matrix\"): an array of polygons, each an array of\n`[lon, lat]` pairs forming one exterior ring (GeoJSON-style,\nlongitude FIRST). Roads intersecting any ring are excluded from\nevery cell's path finding. Applies to the Valhalla engine;\nunsupported on the GraphHopper engine, where it is ignored."
- Changed
nearby_places6 fields changed- changed
Input schema / properties / category / descriptionPrevious value: -"The kind of place to find. The gateway matches it against the\nindex's lowercased OSM tag values (the value of the POI's\n`amenity`/`shop`/`tourism`/`railway`/… tag) — e.g. \"cafe\", \"fuel\",\n\"charging_station\", \"parking\", \"pharmacy\", \"supermarket\", \"hotel\",\n\"restaurant\", \"fast_food\", \"atm\", \"bakery\", \"hospital\", \"station\" —\nand normalises common colloquial names first (\"coffee\" → cafe;\n\"ev_charging\", \"ev charging\" → charging_station; \"petrol\" → fuel;\n\"chemist\" → pharmacy). A category the index does not carry matches\nnothing: the result is an empty list, not an error. Optional when\n`name` is given; at least one of the two is required."New value: +"The kind of place to find. The gateway matches it against the\nindex's lowercased OSM tag values (the value of the POI's\n`amenity`/`shop`/`tourism`/`railway`/… tag), e.g. \"cafe\", \"fuel\",\n\"charging_station\", \"parking\", \"pharmacy\", \"supermarket\", \"hotel\",\n\"restaurant\", \"fast_food\", \"atm\", \"bakery\", \"hospital\", \"station\",\nand normalises common colloquial names first (\"coffee\" → cafe;\n\"ev_charging\", \"ev charging\" → charging_station; \"petrol\" → fuel;\n\"chemist\" → pharmacy). A category the index does not carry matches\nnothing: the result is an empty list, not an error. Optional when\n`name` is given; at least one of the two is required." - changed
Input schema / properties / fov_deg / descriptionPrevious value: -"Field of view: the full width in degrees of a cone centred on\n`heading_deg`, outside which results are dropped — it is the\nFULL width, so 90 keeps only what lies within 45 degrees either\nside of dead ahead. Needs\n`heading_deg` — a cone has to point somewhere. The count of\nresults removed is reported as `out_of_view`."New value: +"Field of view: the full width in degrees of a cone centred on\n`heading_deg`, outside which results are dropped, it is the\nFULL width, so 90 keeps only what lies within 45 degrees either\nside of dead ahead. Needs\n`heading_deg`, a cone has to point somewhere. The count of\nresults removed is reported as `out_of_view`." - changed
Input schema / properties / name / descriptionPrevious value: -"The name or brand of the place to find — \"Lloyds\", \"Lloyds Bank\",\n\"Sainsbury's\" — for \"where is the nearest X\" questions. Every word\nmust appear in the place's name or one of its alternative names,\ncase- and accent-insensitively, with the last word also matching as\na prefix (\"Sains\" finds Sainsbury's). Combine with `category` to\ndisambiguate a brand used by more than one kind of place (\"Lloyds\"\nplus \"bank\" excludes Lloyds Pharmacy). Optional when `category` is\ngiven; at least one of the two is required."New value: +"The name or brand of the place to find, \"Lloyds\", \"Lloyds Bank\",\n\"Sainsbury's\", for \"where is the nearest X\" questions. Every word\nmust appear in the place's name or one of its alternative names,\ncase- and accent-insensitively, with the last word also matching as\na prefix (\"Sains\" finds Sainsbury's). Combine with `category` to\ndisambiguate a brand used by more than one kind of place (\"Lloyds\"\nplus \"bank\" excludes Lloyds Pharmacy). Optional when `category` is\ngiven; at least one of the two is required." - changed
Output schema / $defs / NearbyPlace / properties / direction / descriptionPrevious value: -"The direction phrased for speech — \"ahead and slightly to your\nright, about 80 metres\" with a heading, \"to the north-east, about\n80 metres\" without one. Deliver this verbatim rather than reading\nout coordinates."New value: +"The direction phrased for speech, \"ahead and slightly to your\nright, about 80 metres\" with a heading, \"to the north-east, about\n80 metres\" without one. Deliver this verbatim rather than reading\nout coordinates." - changed
Output schema / $defs / NearbyPlace / properties / type / descriptionPrevious value: -"Feature type — \"poi\" for category-browse hits."New value: +"Feature type, \"poi\" for category-browse hits." - changed
Output schema / properties / out_of_view / descriptionPrevious value: -"How many otherwise-matching places were dropped for falling\noutside `fov_deg`. Non-zero means there are matching places near\nthe user that are simply not in front of them — say so rather\nthan reporting nothing nearby. Always 0 when no field of view was\nset."New value: +"How many otherwise-matching places were dropped for falling\noutside `fov_deg`. Non-zero means there are matching places near\nthe user that are simply not in front of them, say so rather\nthan reporting nothing nearby. Always 0 when no field of view was\nset."
- Changed
optimise_routes9 fields changed- changed
Input schema / $defs / EmissionsSpec / properties / euro_standard / descriptionPrevious value: -"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`."New value: +"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`." - changed
Input schema / $defs / OptimiseVehicleSpec / properties / reloads / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / RelaxSpec / properties / allow_overtime_s / descriptionPrevious value: -"Extend every vehicle's shift END by this many seconds. Shift starts\nare never moved earlier — a driver cannot begin before they begin."New value: +"Extend every vehicle's shift END by this many seconds. Shift starts\nare never moved earlier, a driver cannot begin before they begin." - changed
Input schema / $defs / ReloadsSpec / properties / reload_time_s / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / TerritorySpec / properties / polygon / descriptionPrevious value: -"The outer ring as GeoJSON `[lon, lat]` positions — longitude\nFIRST. Closed or open; an unclosed ring is closed for you."New value: +"The outer ring as GeoJSON `[lon, lat]` positions, longitude\nFIRST. Closed or open; an unclosed ring is closed for you." - changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Input schema / properties / relax_if_unassigned / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / territories / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / properties / reloads / descriptionPrevious value: -"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."New value: +"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."
- Changed
order_stops1 field changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."
- Changed
plan_day7 fields changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Output schema / $defs / GeocodeHit / properties / match / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / properties / score_gap / descriptionPrevious value: -"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\"."New value: +"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\"." - changed
Output schema / $defs / GeocodeMatchComponents / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / StopResolution / properties / ambiguous / descriptionPrevious value: -"True when other plausible matches exist somewhere else — check\n`alternatives` and re-run with an explicit `location` if the\nchosen one is wrong."New value: +"True when other plausible matches exist somewhere else, check\n`alternatives` and re-run with an explicit `location` if the\nchosen one is wrong." - changed
Output schema / properties / geometry_polyline6 / descriptionPrevious value: -"Full multi-stop route geometry (polyline6) — hand it to the map SDK\nor the `route` tool consumers directly."New value: +"Full multi-stop route geometry (polyline6), hand it to the map SDK\nor the `route` tool consumers directly."
- Changed
plan_ev_route8 fields changed- changed
Input schema / $defs / EvVehicleSpec / properties / aux_kw / descriptionPrevious value: -"Auxiliary load in kW — lights, electronics, cabin conditioning.\nWinter heating is several times the mild-weather default."New value: +"Auxiliary load in kW, lights, electronics, cabin conditioning.\nWinter heating is several times the mild-weather default." - changed
Output schema / $defs / EvPlanStop / properties / available_now / descriptionPrevious value: -"Whether a bay is free right now. Present only where a live\navailability feed backs the claim — absent means unknown, never\n\"occupied\"."New value: +"Whether a bay is free right now. Present only where a live\navailability feed backs the claim, absent means unknown, never\n\"occupied\"." - changed
Output schema / $defs / EvPlanStop / properties / charge_s / descriptionPrevious value: -"Time plugged in, seconds — integrated over the vehicle's charging\ncurve capped by the charge point, not energy ÷ peak power."New value: +"Time plugged in, seconds, integrated over the vehicle's charging\ncurve capped by the charge point, not energy ÷ peak power." - changed
Output schema / $defs / EvPlanStop / properties / charger_kw / descriptionPrevious value: -"That connector's rated power, kW — what the charge time was\ncomputed against."New value: +"That connector's rated power, kW, what the charge time was\ncomputed against." - changed
Output schema / $defs / EvPlanSummary / properties / stops / descriptionPrevious value: -"How many charge stops the plan contains. Zero on a journey the car\nmakes on its own — and zero on an infeasible one."New value: +"How many charge stops the plan contains. Zero on a journey the car\nmakes on its own, and zero on an infeasible one." - changed
Output schema / $defs / EvPlanSummary / properties / total_duration_s / descriptionPrevious value: -"Driving plus charging, seconds — the number a user cares about."New value: +"Driving plus charging, seconds, the number a user cares about." - changed
Output schema / properties / charging_attribution / descriptionPrevious value: -"Attribution string for the charge-point operators actually used —\ndisplay it with the plan (a licence obligation)."New value: +"Attribution string for the charge-point operators actually used,\ndisplay it with the plan (a licence obligation)." - changed
Output schema / properties / feasible / descriptionPrevious value: -"**Whether the journey is possible at all.** False means no plan\nexists — a charger desert, a connector mismatch, or a gap wider than\nthe car's range. Report the `reason` and the furthest reachable\npoint; never describe an infeasible answer as a plan."New value: +"**Whether the journey is possible at all.** False means no plan\nexists, a charger desert, a connector mismatch, or a gap wider than\nthe car's range. Report the `reason` and the furthest reachable\npoint; never describe an infeasible answer as a plan."
- Changed
reachable_area1 field changed- changed
Input schema / properties / exclude_polygons / descriptionPrevious value: -"Areas to avoid — scenario analysis (\"close this bridge and\nrecompute reachability\"): an array of polygons, each an array of\n`[lon, lat]` pairs forming one exterior ring (GeoJSON-style,\nlongitude FIRST). Roads intersecting any ring are excluded from\nthe reachability search. Applies to the Valhalla engine;\nunsupported on the GraphHopper engine, where it is ignored."New value: +"Areas to avoid, scenario analysis (\"close this bridge and\nrecompute reachability\"): an array of polygons, each an array of\n`[lon, lat]` pairs forming one exterior ring (GeoJSON-style,\nlongitude FIRST). Roads intersecting any ring are excluded from\nthe reachability search. Applies to the Valhalla engine;\nunsupported on the GraphHopper engine, where it is ignored."
- Changed
replan_routes12 fields changed- changed
Input schema / $defs / EmissionsSpec / properties / euro_standard / descriptionPrevious value: -"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`."New value: +"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`." - changed
Input schema / $defs / OptimiseVehicleSpec / properties / reloads / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / RelaxSpec / properties / allow_overtime_s / descriptionPrevious value: -"Extend every vehicle's shift END by this many seconds. Shift starts\nare never moved earlier — a driver cannot begin before they begin."New value: +"Extend every vehicle's shift END by this many seconds. Shift starts\nare never moved earlier, a driver cannot begin before they begin." - changed
Input schema / $defs / ReloadsSpec / properties / reload_time_s / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / ReplanProgressSpec / properties / unavailable / descriptionPrevious value: -"The vehicle has dropped out of the shift — breakdown, illness, end\nof hours. It leaves the fleet for the re-plan; what it already\ncompleted stays completed."New value: +"The vehicle has dropped out of the shift, breakdown, illness, end\nof hours. It leaves the fleet for the re-plan; what it already\ncompleted stays completed." - changed
Input schema / $defs / ReplanProgressSpec / properties / vehicle / descriptionPrevious value: -"The vehicle this progress belongs to — an `id` from `vehicles`."New value: +"The vehicle this progress belongs to, an `id` from `vehicles`." - changed
Input schema / $defs / TerritorySpec / properties / polygon / descriptionPrevious value: -"The outer ring as GeoJSON `[lon, lat]` positions — longitude\nFIRST. Closed or open; an unclosed ring is closed for you."New value: +"The outer ring as GeoJSON `[lon, lat]` positions, longitude\nFIRST. Closed or open; an unclosed ring is closed for you." - changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Input schema / properties / progress / descriptionPrevious value: -"Per-vehicle progress. Optional, but at least one progress entry or\none change is required — a re-plan that reports nothing new is the\noriginal problem."New value: +"Per-vehicle progress. Optional, but at least one progress entry or\none change is required, a re-plan that reports nothing new is the\noriginal problem." - changed
Input schema / properties / relax_if_unassigned / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / territories / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / properties / reloads / descriptionPrevious value: -"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."New value: +"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."
- Changed
report_map_issue1 field changed- changed
Input schema / properties / way_id / descriptionPrevious value: -"The OSM way id the observation concerns, when the caller knows it.\nOptional — the report stands on its own as a first-party\nobservation and is never tied to OSM data beyond this hint."New value: +"The OSM way id the observation concerns, when the caller knows it.\nOptional, the report stands on its own as a first-party\nobservation and is never tied to OSM data beyond this hint."
- Changed
reverse_geocode3 fields changed- changed
Input schema / properties / fov_deg / descriptionPrevious value: -"Field of view: the full width in degrees of a cone centred on\n`heading_deg`, outside which results are dropped — it is the\nFULL width, so 90 keeps only what lies within 45 degrees either\nside of dead ahead. Needs\n`heading_deg` — a cone has to point somewhere. The count of\nresults removed is reported as `out_of_view`."New value: +"Field of view: the full width in degrees of a cone centred on\n`heading_deg`, outside which results are dropped, it is the\nFULL width, so 90 keeps only what lies within 45 degrees either\nside of dead ahead. Needs\n`heading_deg`, a cone has to point somewhere. The count of\nresults removed is reported as `out_of_view`." - changed
Output schema / $defs / ReverseGeocodeHit / properties / direction / descriptionPrevious value: -"The direction phrased for speech — \"ahead and slightly to your\nright, about 80 metres\" with a heading, \"to the north-east, about\n80 metres\" without one. Deliver this verbatim rather than reading\nout coordinates."New value: +"The direction phrased for speech, \"ahead and slightly to your\nright, about 80 metres\" with a heading, \"to the north-east, about\n80 metres\" without one. Deliver this verbatim rather than reading\nout coordinates." - changed
Output schema / properties / out_of_view / descriptionPrevious value: -"How many otherwise-matching places were dropped for falling\noutside `fov_deg`. Non-zero means there are places near the user\nthat are simply not in front of them — say so rather than\nreporting nothing nearby. Always 0 when no field of view was set."New value: +"How many otherwise-matching places were dropped for falling\noutside `fov_deg`. Non-zero means there are places near the user\nthat are simply not in front of them, say so rather than\nreporting nothing nearby. Always 0 when no field of view was set."
- Changed
route22 fields changed- changed
Input schema / $defs / BicycleSpec / properties / use_roads / descriptionPrevious value: -"Willingness to ride roads alongside motor traffic, 0.0–1.0\n(0.0 = prefer cycleways and quiet streets — the quiet-ride slider)."New value: +"Willingness to ride roads alongside motor traffic, 0.0–1.0\n(0.0 = prefer cycleways and quiet streets, the quiet-ride slider)." - changed
Input schema / $defs / EmissionsSpec / properties / euro_standard / descriptionPrevious value: -"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`."New value: +"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`." - changed
Input schema / $defs / ExcludeFeature / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / PedestrianSpec / properties / use_lit / descriptionPrevious value: -"Preference for lit streets, 0.0–1.0 (1.0 = prefer lit paths as\nstrongly as possible — the \"walk me home on lit streets\" option).\nUnlit ways are still used when no lit alternative exists."New value: +"Preference for lit streets, 0.0–1.0 (1.0 = prefer lit paths as\nstrongly as possible, the \"walk me home on lit streets\" option).\nUnlit ways are still used when no lit alternative exists." - changed
Input schema / $defs / PreferredSideKind / oneOfPrevious value: -[ - { - "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" - } -]New value: +[ + { + "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" + } +] - changed
Input schema / $defs / RouteLocation / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / RouteLocation / properties / preferred_side / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Input schema / properties / avoid / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / exclude / descriptionPrevious value: -"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."New value: +"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." - changed
Input schema / properties / exclude_polygons / descriptionPrevious value: -"Areas to avoid — scenario analysis (\"close this bridge and\nre-route\"): an array of polygons, each an array of `[lon, lat]`\npairs forming one exterior ring (GeoJSON-style, longitude FIRST).\nRoads intersecting any ring are excluded from the search. Applies\nto the Valhalla engine; unsupported on the GraphHopper engine,\nwhere it is ignored."New value: +"Areas to avoid, scenario analysis (\"close this bridge and\nre-route\"): an array of polygons, each an array of `[lon, lat]`\npairs forming one exterior ring (GeoJSON-style, longitude FIRST).\nRoads intersecting any ring are excluded from the search. Applies\nto the Valhalla engine; unsupported on the GraphHopper engine,\nwhere it is ignored." - changed
Input schema / properties / landmarks / descriptionPrevious value: -"Name landmarks in the turn instructions (default false): each\nmanoeuvre that passes a recognisable place — a petrol station, a\nsupermarket, a household-name chain — gains a\n`landmark_instruction` like \"Turn right just after the Shell\ngarage\" beside the engine's own street-name instruction, which is\nnever replaced. Nothing is named unless it is recognisable from the\nroad, within 40 m of the junction and not tagged as closed, so many\nroutes come back with none: a wrong landmark is worse than no\nlandmark. Needs the MapMap gateway, whose place index does the\nlookup."New value: +"Name landmarks in the turn instructions (default false): each\nmanoeuvre that passes a recognisable place, a petrol station, a\nsupermarket, a household-name chain, gains a\n`landmark_instruction` like \"Turn right just after the Shell\ngarage\" beside the engine's own street-name instruction, which is\nnever replaced. Nothing is named unless it is recognisable from the\nroad, within 40 m of the junction and not tagged as closed, so many\nroutes come back with none: a wrong landmark is worse than no\nlandmark. Needs the MapMap gateway, whose place index does the\nlookup." - changed
Input schema / properties / rationale / descriptionPrevious value: -"Explain the route (default false): re-routes with each declared\ntruck constraint (truck costing) or avoidance-side routing\npreference (auto, bicycle, pedestrian, motor_scooter) relaxed and\nreports the ones that actually changed the route as\n`rationale.avoided[]`. Opt-in — it costs up to 1 + N extra routing\ncalls, one per declared field plus one combined probe, and it is\nbilled for the ones it actually makes: at most 8 in total,\ntypically fewer, and 1 when there is nothing to probe. Against the\nhosted gateway each probe is its own metered route call, which is\nexactly what `POST /route` with `rationale: true` charges for its\nown fan-out, so the two surfaces price the same explanation the\nsame way."New value: +"Explain the route (default false): re-routes with each declared\ntruck constraint (truck costing) or avoidance-side routing\npreference (auto, bicycle, pedestrian, motor_scooter) relaxed and\nreports the ones that actually changed the route as\n`rationale.avoided[]`. Opt-in, it costs up to 1 + N extra routing\ncalls, one per declared field plus one combined probe, and it is\nbilled for the ones it actually makes: at most 8 in total,\ntypically fewer, and 1 when there is nothing to probe. Against the\nhosted gateway each probe is its own metered route call, which is\nexactly what `POST /route` with `rationale: true` charges for its\nown fan-out, so the two surfaces price the same explanation the\nsame way." - changed
Output schema / $defs / AppliedAdr / descriptionPrevious value: -"The ADR costing that was merged into a truck route request.\n\nEvery field here describes the **request**: the declared load and the\ncosting options built from it. Nothing here is an assertion about the\nreturned geometry — see [`TunnelEnforcement`]."New value: +"The ADR costing that was merged into a truck route request.\n\nEvery field here describes the **request**: the declared load and the\ncosting options built from it. Nothing here is an assertion about the\nreturned geometry, see [`TunnelEnforcement`]." - changed
Output schema / $defs / AppliedAdr / properties / forbidden_tunnel_categories / descriptionPrevious value: -"ADR tunnel categories **the vehicle** is forbidden from under the\nworst-case reading of ADR 8.6.4 (conditional clauses assumed to\napply). Empty when unrestricted. This is not a claim that the\nreturned route contains no tunnel of these categories — read\n[`AppliedAdr::tunnel_enforcement`] for what was actually applied."New value: +"ADR tunnel categories **the vehicle** is forbidden from under the\nworst-case reading of ADR 8.6.4 (conditional clauses assumed to\napply). Empty when unrestricted. This is not a claim that the\nreturned route contains no tunnel of these categories, read\n[`AppliedAdr::tunnel_enforcement`] for what was actually applied." - changed
Output schema / $defs / AppliedAdr / properties / tunnel_code / descriptionPrevious value: -"Canonical ADR tunnel restriction code applied (\"B/D\", \"(—)\", …),\nor null when no code was declared."New value: +"Canonical ADR tunnel restriction code applied (\"B/D\", \"(-)\", …),\nor null when no code was declared." - changed
Output schema / $defs / AppliedAvoidance / properties / costing_option_fields / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / AvoidedConstraint / properties / value / descriptionPrevious value: -"The declared value for the field (null for \"combined\"). NOTE: for\ntruck this is the vehicle's dimension, not the infrastructure\nlimit — the physical restriction is not identified."New value: +"The declared value for the field (null for \"combined\"). NOTE: for\ntruck this is the vehicle's dimension, not the infrastructure\nlimit, the physical restriction is not identified." - changed
Output schema / $defs / ManeuverOut / properties / landmark_instruction / descriptionPrevious value: -"The same manoeuvre anchored to a recognisable place, e.g. \"Turn\nright just after the Shell garage\" — present only when the request\nset `landmarks: true` and a place near the junction cleared the\nsalience bar. Prefer reading this aloud when it is there: it is how\na passenger would give the direction. `instruction` is always the\nengine's own and is never replaced."New value: +"The same manoeuvre anchored to a recognisable place, e.g. \"Turn\nright just after the Shell garage\", present only when the request\nset `landmarks: true` and a place near the junction cleared the\nsalience bar. Prefer reading this aloud when it is there: it is how\na passenger would give the direction. `instruction` is always the\nengine's own and is never replaced." - changed
Output schema / $defs / RouteRationale / descriptionPrevious value: -"Why the route goes the way it does — the `route` tool's opt-in\nrationale block, computed for truck, auto, bicycle, pedestrian and\nmotor_scooter costings. **Method honesty:** the routing engine exposes\nno exclusion set, so entries are derived by re-routing with each\ndeclared constraint or preference relaxed\n(`basis: \"route_divergence\"`); this proves a field was binding and\nwhere, but never names the physical restriction or feature (the\nspecific signed bridge, hill or unlit street). No live traffic or\nincident data enters the comparison and no delay is ever estimated\nfrom one — the engine has no live speed field."New value: +"Why the route goes the way it does, the `route` tool's opt-in\nrationale block, computed for truck, auto, bicycle, pedestrian and\nmotor_scooter costings. **Method honesty:** the routing engine exposes\nno exclusion set, so entries are derived by re-routing with each\ndeclared constraint or preference relaxed\n(`basis: \"route_divergence\"`); this proves a field was binding and\nwhere, but never names the physical restriction or feature (the\nspecific signed bridge, hill or unlit street). No live traffic or\nincident data enters the comparison and no delay is ever estimated\nfrom one, the engine has no live speed field." - changed
Output schema / $defs / TunnelEnforcement / descriptionPrevious value: -"How the declared ADR tunnel code reaches the routing engine, and what a\nreturned route therefore does — and does not — prove.\n\nThis block exists because [`AppliedAdr::forbidden_tunnel_categories`] is\na statement about the **load** (ADR 8.6.4 applied to the declared code),\nand on its own it reads like a statement about the **route**. It is not\none. The engine excludes a road only where the routing graph records an\nADR tunnel category for it, and that category is derived from OSM\n`hazmat:*` tagging. Coverage is therefore uneven: a corridor with no\nsuch tagging is not excluded and looks, in the response, exactly like a\ncorridor that was checked and cleared.\n\nThe field is emitted on every `applied_adr`, so a caller can never\nreceive the categories without the boundary that qualifies them."New value: +"How the declared ADR tunnel code reaches the routing engine, and what a\nreturned route therefore does (and does not) prove.\n\nThis block exists because [`AppliedAdr::forbidden_tunnel_categories`] is\na statement about the **load** (ADR 8.6.4 applied to the declared code),\nand on its own it reads like a statement about the **route**. It is not\none. The engine excludes a road only where the routing graph records an\nADR tunnel category for it, and that category is derived from OSM\n`hazmat:*` tagging. Coverage is therefore uneven: a corridor with no\nsuch tagging is not excluded and looks, in the response, exactly like a\ncorridor that was checked and cleared.\n\nThe field is emitted on every `applied_adr`, so a caller can never\nreceive the categories without the boundary that qualifies them." - changed
Output schema / properties / zones / descriptionPrevious value: -"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."New value: +"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."
- Changed
search_along_route7 fields changed- changed
Input schema / $defs / TruckSpec / properties / tunnel_code / descriptionPrevious value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)." - changed
Input schema / properties / category / descriptionPrevious value: -"Explicit place category (\"fuel\", \"cafe\", \"charging_station\" — same\nvocabulary as nearby_places). Colloquial phrases are normalised\nserver-side; prefer this over query for category intents."New value: +"Explicit place category (\"fuel\", \"cafe\", \"charging_station\", same\nvocabulary as nearby_places). Colloquial phrases are normalised\nserver-side; prefer this over query for category intents." - changed
Output schema / $defs / AlongRouteHit / properties / fuel_prices / descriptionPrevious value: -"Live pump prices for this fuel/petrol station, keyed by fuel code\n(e.g. \"diesel\", \"petrol_95\"), each `{value, currency, updated_at}`.\nOnly ever present when the server is gateway-preferred AND the\ndeployment configured `SN_FUEL_PRICES` AND this result matched a\nstation within range — never fabricated. Direct-backend fallback\nnever sets this (see the gap this closes in the PR description)."New value: +"Live pump prices for this fuel/petrol station, keyed by fuel code\n(e.g. \"diesel\", \"petrol_95\"), each `{value, currency, updated_at}`.\nOnly ever present when the server is gateway-preferred AND the\ndeployment configured `SN_FUEL_PRICES` AND this result matched a\nstation within range, never fabricated. Direct-backend fallback\nnever sets this (see the gap this closes in the PR description)." - changed
Output schema / $defs / GeocodeHit / properties / match / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / descriptionPrevious value: -"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."New value: +"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." - changed
Output schema / $defs / GeocodeMatch / properties / score_gap / descriptionPrevious value: -"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\"."New value: +"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\"." - changed
Output schema / $defs / GeocodeMatchComponents / descriptionPrevious value: -"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."New value: +"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."
- Changed
submit_integration_retro1 field changed- changed
Output schema / properties / message / descriptionPrevious value: -"A short, honest sentence for the agent saying where the retro\nlanded — sent to MapMap, or held in this server's local queue."New value: +"A short, honest sentence for the agent saying where the retro\nlanded, sent to MapMap, or held in this server's local queue."
- Changed
submit_optimise_job4 fields changed- changed
Input schema / $defs / JobKind / oneOfPrevious value: -[ - { - "const": "optimise", - "description": "A fleet optimisation — the `optimise_routes` problem, at ten times\nthe synchronous location cap.", - "type": "string" - }, - { - "const": "replan", - "description": "A mid-shift re-plan — the `replan_routes` problem, counted on the\nremaining work.", - "type": "string" - }, - { - "const": "matrix", - "description": "A many-to-many time/distance matrix — the `matrix` problem, at four\ntimes the synchronous element cap.", - "type": "string" - } -]New value: +[ + { + "const": "optimise", + "description": "A fleet optimisation, the `optimise_routes` problem, at ten times\nthe synchronous location cap.", + "type": "string" + }, + { + "const": "replan", + "description": "A mid-shift re-plan, the `replan_routes` problem, counted on the\nremaining work.", + "type": "string" + }, + { + "const": "matrix", + "description": "A many-to-many time/distance matrix, the `matrix` problem, at four\ntimes the synchronous element cap.", + "type": "string" + } +] - changed
Input schema / properties / problem / descriptionPrevious value: -"The problem itself, in exactly the shape the synchronous tool takes\n— `optimise_routes` input for `optimise`, `replan_routes` input for\n`replan`, `matrix` input for `matrix`. Moving a working synchronous\ncall onto this lane changes nothing but the tool you call it with."New value: +"The problem itself, in exactly the shape the synchronous tool takes\n, `optimise_routes` input for `optimise`, `replan_routes` input for\n`replan`, `matrix` input for `matrix`. Moving a working synchronous\ncall onto this lane changes nothing but the tool you call it with." - changed
Input schema / properties / webhook_url / descriptionPrevious value: -"Optional HTTPS URL to POST a signed `{job_id, kind, status,\nresult_url}` notification to when the job finishes. The RESULT is\nnever pushed — the notification says where to fetch it. Requires a\nwebhook signing secret on the key; without one the submission is\nrefused rather than delivered unsigned. An agent that can poll does\nnot need this: polling with `get_job` is free."New value: +"Optional HTTPS URL to POST a signed `{job_id, kind, status,\nresult_url}` notification to when the job finishes. The RESULT is\nnever pushed, the notification says where to fetch it. Requires a\nwebhook signing secret on the key; without one the submission is\nrefused rather than delivered unsigned. An agent that can poll does\nnot need this: polling with `get_job` is free." - changed
Output schema / properties / status / descriptionPrevious value: -"Always `queued` — no worker has looked at it yet."New value: +"Always `queued`, no worker has looked at it yet."
- Changed
validate_geodata1 field changed- changed
Input schema / $defs / XY / descriptionPrevious value: -"One coordinate from the dataset, in the dataset's own units — NOT\nnecessarily degrees. Named `x`/`y` rather than `lon`/`lat` precisely\nbecause whether they are degrees is the thing in question."New value: +"One coordinate from the dataset, in the dataset's own units, NOT\nnecessarily degrees. Named `x`/`y` rather than `lon`/`lat` precisely\nbecause whether they are degrees is the thing in question."
- Changed
verify_places7 fields changed- changed
Input schema / $defs / VerifyClaimInput / properties / locality / descriptionPrevious value: -"Optional disambiguating context, e.g. \"Oxford\". Country-level words\n(\"UK\", \"England\", …) are stripped before querying — they add noise,\nnot signal, to name search."New value: +"Optional disambiguating context, e.g. \"Oxford\". Country-level words\n(\"UK\", \"England\", …) are stripped before querying, they add noise,\nnot signal, to name search." - changed
Input schema / properties / claims / descriptionPrevious value: -"Structured claims — the reliable path, and the only path that\nsupports itinerary feasibility. Mutually exclusive with `text`.\nMax 20 per request."New value: +"Structured claims, the reliable path, and the only path that\nsupports itinerary feasibility. Mutually exclusive with `text`.\nMax 20 per request." - changed
Input schema / properties / text / descriptionPrevious value: -"Free text to extract place claims from (best-effort heuristic:\nquoted phrases and Title Case runs after \"at/in/near/to/from/\nvisiting\" — not NLP or an LLM call, and it does not attempt\nitinerary feasibility since there are no explicit times to anchor\nlegs to). Mutually exclusive with `claims`. Max 8,000 characters."New value: +"Free text to extract place claims from (best-effort heuristic:\nquoted phrases and Title Case runs after \"at/in/near/to/from/\nvisiting\", not NLP or an LLM call, and it does not attempt\nitinerary feasibility since there are no explicit times to anchor\nlegs to). Mutually exclusive with `claims`. Max 8,000 characters." - changed
Output schema / $defs / VerifyEvidence / properties / detail / descriptionPrevious value: -"Short factual note, always from a fixed template (see\n`crate::verify`) — never free-form text that could assert\nnon-existence or closure."New value: +"Short factual note, always from a fixed template (see\n`crate::verify`), never free-form text that could assert\nnon-existence or closure." - changed
Output schema / $defs / VerifyFeasibilityStatus / oneOfPrevious value: -[ - { - "enum": [ - "feasible", - "impossible" - ], - "type": "string" - }, - { - "const": "implausible", - "description": "Tight — flagged, but not asserted as impossible (not certain enough\nto contradict).", - "type": "string" - } -]New value: +[ + { + "enum": [ + "feasible", + "impossible" + ], + "type": "string" + }, + { + "const": "implausible", + "description": "Tight, flagged, but not asserted as impossible (not certain enough\nto contradict).", + "type": "string" + } +] - changed
Output schema / $defs / VerifyVerdict / descriptionPrevious value: -"The three-state verdict — see `crate::verify` module docs for why\nthere is no fourth \"does not exist\" state and never a boolean."New value: +"The three-state verdict, see `crate::verify` module docs for why\nthere is no fourth \"does not exist\" state and never a boolean." - changed
Output schema / properties / summary / descriptionPrevious value: -"Always present: a concise plain-text summary alongside the\nstructured `results` — several MCP clients (notably ChatGPT\nconnectors) drop non-text content blocks, so this must stand on\nits own. This same string is also returned as the tool call's text\ncontent block, not only inside the structured JSON."New value: +"Always present: a concise plain-text summary alongside the\nstructured `results`, several MCP clients (notably ChatGPT\nconnectors) drop non-text content blocks, so this must stand on\nits own. This same string is also returned as the tool call's text\ncontent block, not only inside the structured JSON."
7 tool updates
- Added
events_in_area - Changed
optimise_routes2 fields changed- added
Output schema / properties / view_urlAdded value: +{ + "description": "A mapmap.ai link that draws this fleet plan, one route per vehicle, on a map: open it or pass it\non as the last line of the answer. Nothing is stored server-side and\nopening it needs no key; the link itself carries the stop coordinates\nand stop names (plus any arrival clocks, dwell times and totals) and\nnothing else, so anyone holding it can read those stops. Absent when\nthe plan cannot be linked (see `view_url_note`) or the server runs\nwith links turned off (`SN_MCP_SITE_URL` empty).", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / view_url_noteAdded value: +{ + "description": "Why there is no `view_url` (too many vehicles or stops for one link,\nor over the 6,000 character cap), or what the link left out to fit\nunder the cap (arrival times, dwell times, then stop names). Relay it\nwith the link.", + "type": [ + "string", + "null" + ] +}
- Changed
plan_day2 fields changed- added
Output schema / properties / view_urlAdded value: +{ + "description": "A mapmap.ai link that draws this day plan on a map: open it or pass it\non as the last line of the answer. Nothing is stored server-side and\nopening it needs no key; the link itself carries the stop coordinates\nand stop names (plus any arrival clocks, dwell times and totals) and\nnothing else, so anyone holding it can read those stops. Absent when\nthe plan cannot be linked (see `view_url_note`) or the server runs\nwith links turned off (`SN_MCP_SITE_URL` empty).", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / view_url_noteAdded value: +{ + "description": "Why there is no `view_url` (too many vehicles or stops for one link,\nor over the 6,000 character cap), or what the link left out to fit\nunder the cap (arrival times, dwell times, then stop names). Relay it\nwith the link.", + "type": [ + "string", + "null" + ] +}
- Changed
replan_routes2 fields changed- added
Output schema / properties / view_urlAdded value: +{ + "description": "A mapmap.ai link that draws this fleet plan, one route per vehicle, on a map: open it or pass it\non as the last line of the answer. Nothing is stored server-side and\nopening it needs no key; the link itself carries the stop coordinates\nand stop names (plus any arrival clocks, dwell times and totals) and\nnothing else, so anyone holding it can read those stops. Absent when\nthe plan cannot be linked (see `view_url_note`) or the server runs\nwith links turned off (`SN_MCP_SITE_URL` empty).", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / view_url_noteAdded value: +{ + "description": "Why there is no `view_url` (too many vehicles or stops for one link,\nor over the 6,000 character cap), or what the link left out to fit\nunder the cap (arrival times, dwell times, then stop names). Relay it\nwith the link.", + "type": [ + "string", + "null" + ] +}
- Changed
route2 fields changed- added
Output schema / properties / view_urlAdded value: +{ + "description": "A mapmap.ai link that draws this route on a map: open it or pass it\non as the last line of the answer. Nothing is stored server-side and\nopening it needs no key; the link itself carries the stop coordinates\nand stop names (plus any arrival clocks, dwell times and totals) and\nnothing else, so anyone holding it can read those stops. Absent when\nthe plan cannot be linked (see `view_url_note`) or the server runs\nwith links turned off (`SN_MCP_SITE_URL` empty).", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / view_url_noteAdded value: +{ + "description": "Why there is no `view_url` (too many vehicles or stops for one link,\nor over the 6,000 character cap), or what the link left out to fit\nunder the cap (arrival times, dwell times, then stop names). Relay it\nwith the link.", + "type": [ + "string", + "null" + ] +}
- Added
space_weather_now - Added
weather_frames
1 tool update
- Changed
route7 fields changed- changed
Input schema / $defs / PedestrianSpec / descriptionPrevious value: -"Pedestrian options for costing \"pedestrian\": lit-street preference,\naccessibility type and hiking difficulty, mapped onto Valhalla\n`costing_options.pedestrian`. All preferences, never guarantees — the\nrouter prefers matching ways where the map data supports it."New value: +"Pedestrian options for costing \"pedestrian\": lit-street preference,\npedestrian type, hills, surface quality and hiking difficulty, mapped\nonto Valhalla `costing_options.pedestrian` (surface quality and the\ngrade cap are MapMap gateway fields). All preferences, never\nguarantees: the router prefers matching ways where the map data\nsupports it." - added
Input schema / $defs / PedestrianSpec / properties / max_grade_pctAdded value: +{ + "description": "Maximum grade in whole percent, 1–90. Needs the MapMap gateway:\nthe routing engine accepts this cap but does not enforce it yet,\nand the gateway's `grade.cap` says so on every route that sets it.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] +} - added
Input schema / $defs / PedestrianSpec / properties / surface_qualityAdded value: +{ + "description": "Surface quality for wheelchair routes: \"avoid\" (the default where\nthe deployment has a surface graph covering the route) or \"ignore\"\n(use the ordinary graph). Wheelchair only, and needs the MapMap\ngateway; the `surface_quality` block in the output says whether it\nwas applied.", + "type": [ + "string", + "null" + ] +} - changed
Input schema / $defs / PedestrianSpec / properties / type / descriptionPrevious value: -"Pedestrian type: \"wheelchair\" (avoids steps, kerbs and steep\ngrades where mapped) or \"blind\" (richer guidance detail). Omit for\nthe default on-foot profile."New value: +"Pedestrian type: \"wheelchair\" (avoids mapped steps and kerbs and\nthe rougher surface classes; hills per `use_hills`) or \"blind\"\n(richer guidance detail). Omit for the default on-foot profile." - added
Input schema / $defs / PedestrianSpec / properties / use_hillsAdded value: +{ + "description": "Willingness to take hills, 0.0–1.0 (0.0 = avoid climbs as strongly\nas the engine can; the engine default is 0.5). A preference, not a\ncap. The MapMap gateway sends 0.0 on a wheelchair route that does\nnot set it, and reports that in `grade.preference`.", + "format": "double", + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / gradeAdded value: +{ + "description": "The hill report on a pedestrian route (only through the MapMap\ngateway): maximum grade, total ascent and descent sampled along\nthe route from the elevation model, the hill preference sent, and\nwhether a requested grade cap was enforced. Relay `cap.enforced`\nand the caveat as given." +} - added
Output schema / properties / surface_qualityAdded value: +{ + "description": "Surface quality on a wheelchair route (only through the MapMap\ngateway): `applied` true with the region, the exact rule, the data\ntimestamp and a caveat when the route was computed on the surface\ngraph; `applied` false with a `reason` otherwise. Relay the caveat:\nit is a preference from OpenStreetMap ratings where they exist,\nand says nothing about kerbs, widths, steps or inclines." +}
1 tool update
- Changed
weather_along_route5 fields changed- changed
Output schema / properties / attribution / descriptionPrevious value: -"Data attribution (CC BY 4.0): display it with the forecast."New value: +"Data attribution (CC BY 4.0): display it with the forecast,\nverbatim." - added
Output schema / properties / attribution_urlAdded value: +{ + "description": "The link the credit carries (\"https://open-meteo.com/\"): Open-Meteo's\nlicence asks for it next to any place its data is displayed.", + "type": "string" +} - added
Output schema / properties / derived_fieldsAdded value: +{ + "description": "The sample fields MapMap derives rather than reads from Open-Meteo\n(\"precipitation_type\", \"severe\"), so a display can indicate the\nchanges the licence asks to be indicated.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / licence_urlAdded value: +{ + "description": "The data licence to link with the credit (CC BY 4.0).", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "samples", - "depart_at", - "duration_s", - "duration_source", - "sample_interval_m", - "severe_ahead", - "summary", - "attribution" -]New value: +[ + "samples", + "depart_at", + "duration_s", + "duration_source", + "sample_interval_m", + "severe_ahead", + "summary", + "attribution", + "attribution_url", + "licence_url", + "derived_fields" +]
3 tool updates
- Changed
list_style_layers5 fields changed- added
Output schema / $defs / StyleSlotInfoAdded value: +{ + "description": "One insertion slot for extra layers (Mapbox Standard names).", + "properties": { + "before": { + "description": "The skeleton layer id the slot sits directly below.", + "type": "string" + }, + "description": { + "description": "Where it sits, in words.", + "type": "string" + }, + "slot": { + "description": "`bottom`, `middle` or `top`.", + "type": "string" + } + }, + "required": [ + "slot", + "before", + "description" + ], + "type": "object" +} - added
Output schema / $defs / StyleSourcesInfoAdded value: +{ + "description": "What a theme's `sources` block accepts.", + "properties": { + "max_geojson_sources": { + "description": "At most this many of them `geojson`.", + "format": "uint", + "minimum": 0, + "type": "integer" + }, + "max_sources": { + "description": "At most this many sources per theme.", + "format": "uint", + "minimum": 0, + "type": "integer" + }, + "types": { + "description": "Accepted source types.", + "items": { + "type": "string" + }, + "type": "array" + }, + "url_rules": { + "description": "The URL rules every source URL must pass.", + "type": "string" + } + }, + "required": [ + "types", + "max_sources", + "max_geojson_sources", + "url_rules" + ], + "type": "object" +} - added
Output schema / properties / slotsAdded value: +{ + "default": [], + "description": "The insertion slots an extra layer may name (`\"slot\"`), bottom of\nthe stack first, with the layer each sits directly below. A layer\nwithout a slot goes in `middle`.", + "items": { + "$ref": "#/$defs/StyleSlotInfo" + }, + "type": "array" +} - changed
Output schema / properties / source_layers / descriptionPrevious value: -"The OpenMapTiles source-layers the tiles emit; `extra_layers` must\nreference one of these."New value: +"The OpenMapTiles source-layers the tiles emit; an extra layer on\nthe `territory` source must reference one of these." - added
Output schema / properties / sourcesAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/StyleSourcesInfo" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The rules for a theme's own `sources` (customer data by URL)." +}
- Added
nearby_stops - Added
next_departures
1 tool update
- Added
weather_along_route
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."
Related MCP Connectors
Routing, geocoding, places, matrix and map tools for location-aware AI workflows.
Hosted MCP for live place search, geocoding & turn-by-turn routes. No Maps API key to manage.
Geocode, reverse-geocode, autocomplete, route and search places.
- RijwindOAuthcom.rijwind
European maps, geocoding and routing: places, routes, travel times, reachable areas and maps.
Related MCP Servers
AlicenseAqualityBmaintenanceLocation & routing intelligence for AI agents — geocoding, truck routing, traffic, weather, and place search.2199 npm1MIT- 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.1814 npmMIT

Magic Lane MCP Serverofficial
AlicenseBqualityCmaintenanceEnables 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.85 npm7Apache 2.0- AlicenseNot gradedqualityBmaintenanceLets coding agents add working maps to apps by creating API keys, geocoding and reverse-geocoding addresses, getting MapLibre snippets for HTML, React, Vue or Svelte, and monitoring or lowering prepaid usage budgets.501 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.