ThinAir Geo
Server Details
Location & routing intelligence for AI agents — geocoding, truck routing, traffic, weather, and place search.
- Status
- Healthy
- Uptime
- 76.8% over 36 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 19 tools
Each tool targets a distinct operation: geocoding, reverse geocoding, batch geocoding, structured geocoding, intersection resolution, place lookup, POI search, discovery, road snapping, map matching, trace attributes, routing, matrices, isochrones, geofencing, traffic, weather, quota, and key management. Overlapping pairs like geocode/geocode_structured and map_match/trace_attributes are explicitly differentiated in their descriptions.
Tool names are uniformly snake_case and readable, with most following a verb_noun or clear noun pattern. However, there is not one strictly consistent convention: some names are verb-first (geocode, search_places, resolve_intersection), some are noun-first (place_get, map_match, geofence_contains), and others are single nouns (directions, traffic, weather, quota).
Nineteen tools cover a broad but coherent geospatial platform, and each tool serves a distinct function. Still, that count falls into the 16-25 range that feels heavy for an MCP server, even if the breadth is justifiable for a full geocoding/routing API.
The tool surface is comprehensive: geocoding, reverse/batch geocoding, place search, routing, distance matrices, isochrones, map matching, trace attributes, road snapping, geofencing, traffic, weather, quota, and key management are all represented. Minor gaps exist, such as no batch reverse geocoding and no elevation profiles beyond a single-point elevation option, but these are workable rather than blocking.
Available Tools
19 toolsbatch_geocodeARead-onlyIdempotentInspect
Geocode multiple addresses in one request with structured per-record results. Use for bulk operations instead of repeated single geocode calls. Max 50 per batch.
| Name | Required | Description | Default |
|---|---|---|---|
| addresses | Yes | Array of addresses to geocode (max 50 per batch) |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, and idempotentHint, reducing the burden on the description. The description adds useful behavioral context by noting 'structured per-record results,' which indicates the response format for individual addresses, and reiterates the 'Max 50 per batch' limit. It doesn't specify error handling for partial failures, but with annotations covering safety, this is adequate.
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 concise sentences: the first states the core purpose, the second gives usage guidance and the batch limit. No wasted words, making it efficiently front-loaded and easy to parse.
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 batch tool with one parameter, an output schema, and strong annotations, the description is complete. It covers the key operational constraints (bulk usage, max batch size, per-record results) without needing to elaborate on return values, which are presumably documented in the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: the single 'addresses' parameter is fully described as 'Array of addresses to geocode (max 50 per batch).' The tool description repeats this limit and doesn't add any additional semantic detail beyond what the schema already provides, so it meets the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Geocode multiple addresses in one request with structured per-record results.' It uses a specific verb ('geocode') and resource ('multiple addresses'), and distinguishes itself from the sibling 'geocode' tool by emphasizing batch processing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly directs use: 'Use for bulk operations instead of repeated single geocode calls.' This provides both a when-to-use (bulk) and a when-not-to-use (as a substitute for repeated single calls), clearly differentiating it from the alternative geocode tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
directionsARead-onlyIdempotentInspect
Generate routes, ETAs, and turn-by-turn directions between locations. Live traffic is post-route ETA enrichment and does not change the returned path (path_influenced=false); truck traffic adjustments are slowdown-only. Supports car / truck / motorcycle / pedestrian / bicycle, with hazmat + dimension + toll avoidance for commercial routing. ETAs are returned as ISO 8601 with timezone offset (in the destination's local timezone). Use vehicle_profile presets (10 total — DRY_VAN_53, FLATBED_48/_40, STEP_DECK, TANKER, BOX_TRUCK_26, AUTO_CARRIER, SPRINTER_VAN, DOUBLE_TRAILER, OVERSIZE) when routing trucks — they set height/weight/length in one parameter.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Destination: address string ('Houston, TX'), 'lat,lon' string, or { lat, lon } object | |
| via | No | Intermediate stops in order; same shape as from/to. Up to 48 waypoints (max 50 total locations). | |
| from | Yes | Origin: address string ('Houston, TX'), 'lat,lon' string, or { lat, lon } object | |
| units | No | Distance units (default: miles). Accepts 'km'/'mi' as aliases. | |
| hazmat | No | Set true when transporting hazardous materials to avoid restricted routes | |
| costing | No | Transport mode (default: auto). Use 'truck' for commercial vehicles | |
| axle_load | No | Axle weight in metric tons (e.g. 9.07t = 20,000 lbs per axle) | |
| top_speed | No | Maximum speed in km/h (default 105 for trucks) | |
| use_ferry | No | Ferry preference 0-1 (0=avoid, 1=allow) | |
| alternates | No | Number of genuine motorized alternate routes to request (0, 1, or 2). Positive values require no via waypoints. | |
| axle_count | No | Number of axles (default 5 for semi-trailer) | |
| avoid_tolls | No | Avoid toll roads when user requests toll-free routing | |
| truck_width | No | Truck width in meters (e.g. 2.6m = 8'6") | |
| truck_height | No | Truck height in meters (e.g. 4.11m = 13'6"). Triggers bridge avoidance | |
| truck_length | No | Truck length in meters (e.g. 16.2m = 53') | |
| truck_weight | No | Truck weight in metric tons (e.g. 36.3t = 80,000 lbs). Triggers weight-restricted road avoidance | |
| use_highways | No | Highway preference 0-1 (0=avoid, 1=prefer) | |
| include_traffic | No | Apply post-route live-traffic ETA enrichment (default: true). Traffic does not change the returned path; truck adjustments are slowdown-only. | |
| include_weather | No | Attach current conditions sampled along the route corridor (default: false). Post-route annotation only: weather does not change the returned path. Extra upstream lookup, opt-in only. | |
| vehicle_profile | No | Preset vehicle profile (10): DRY_VAN_53, FLATBED_48, FLATBED_40, STEP_DECK, TANKER, BOX_TRUCK_26, AUTO_CARRIER, SPRINTER_VAN, DOUBLE_TRAILER, OVERSIZE. Each sets height/weight/length/axle_count for that vehicle class in one parameter (e.g. DRY_VAN_53 = 4.11m tall, 36.3t, 22.25m long, 5 axles; OVERSIZE = 4.88m tall, 3.66m wide, 45.36t). The response echoes the applied dims in costing_options.truck. Any individual truck_height/truck_weight/etc. overrides a single field. | |
| include_geometry | No | Route geometry shape control. "none" returns origin/destination Points only. "encoded" returns an encoded polyline6 string in a top-level `geometry` field plus origin/destination Points (≈95% smaller than raw GeoJSON; decode with @mapbox/polyline at precision 6). "full" emits decoded coordinates as a LineString in `geojson.features[0]`. When omitted (default), small routes use "full" and long routes auto-downgrade to "encoded" with a `geometry_truncated` warning. | |
| include_elevation | No | When true, include available route elevation fields. Point elevation may be returned for the origin and destination. Cumulative gain/loss is returned only when route-profile elevation is available. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| alternates | No | |
| display_hint | No | |
| timezone_end | No | IANA timezone at the route destination, or null when unresolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain). |
| traffic_route | No | |
| timezone_start | No | IANA timezone at the route origin, or null when unresolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain). |
| costing_options | No | |
| elevation_end_m | No | |
| base_arrival_utc | Yes | Arrival time derived from the base duration, expressed as an ISO 8601 UTC timestamp. |
| elevation_end_ft | No | |
| elevation_gain_m | No | |
| elevation_loss_m | No | |
| elevation_gain_ft | No | |
| elevation_loss_ft | No | |
| elevation_start_m | No | |
| base_arrival_local | Yes | Arrival time derived from the base duration in the destination's local time, or null when the local timezone is unavailable. |
| elevation_start_ft | No | |
| traffic_provenance | Yes | |
| timezone_end_status | No | |
| base_duration_seconds | Yes | Route duration before any traffic-based adjustment, in seconds. |
| effective_arrival_utc | Yes | Authoritative arrival time for this response, expressed as an ISO 8601 UTC timestamp. |
| timezone_start_status | No | |
| traffic_delay_seconds | Yes | Effective duration minus base duration, in seconds. Positive means traffic made the ETA slower, negative means it made the ETA faster, and zero means the duration was unchanged. For truck costing, general traffic evidence is slowdown-only, so this value is never negative. |
| effective_arrival_local | Yes | Authoritative arrival time in the destination's local time, or null when the local timezone is unavailable. |
| timezone_artifact_version | No | |
| effective_duration_seconds | Yes | Authoritative duration for this response, in seconds, after any applicable traffic-based adjustment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only/idempotent annotations, the description discloses critical non-obvious behavior: live traffic is post-route ETA enrichment that does not alter the path, truck adjustments are slowdown-only, and ETAs are ISO 8601 with destination-local timezone offsets. It also flags include_weather behavior as post-route and opt-in. These details prevent incorrect expectations without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences with a front-loaded purpose, followed by high-value caveats (traffic behavior, timezone, vehicle profiles) and no filler. It is dense but appropriately sized for a 22-parameter routing tool, though it duplicates some 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 tool with this many parameters and an output schema present, the description covers the non-obvious behavioral caveats an agent needs to invoke it correctly: traffic doesn't reroute, truck adjustments are slowdown-only, ETAs are timezone-aware, and vehicle profiles are provided. Required params and shapes are in the schema, so 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 schema already documents every parameter and the vehicle_profile presets in detail. The description repeats the preset list and adds the 'when routing trucks' recommendation, but adds no parameter semantics beyond the schema. 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 opens with 'Generate routes, ETAs, and turn-by-turn directions between locations,' a specific verb+resource phrase that clearly distinguishes the tool from siblings like distance_matrix, isochrone, and map_match. It further lists supported travel modes and commercial-routing features, reinforcing the tool's scope.
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 clear context for when to use the tool (routing/ETA/turn-by-turn needs) and gives parameter-level guidance ('Use vehicle_profile presets ... when routing trucks'). However, it never names an alternative tool or states when not to use this one, so routing to it versus distance_matrix or map_match 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.
distance_matrixARead-onlyIdempotentInspect
Compute road distances and travel times for every origin → destination pair. Endpoints accept free-text addresses or 'lat,lon' strings; N × M is capped at 625 pairs. Use for fleet dispatch, nearest-depot, and bulk ETA tables.
| Name | Required | Description | Default |
|---|---|---|---|
| units | No | Distance units (default kilometers) | |
| costing | No | Transport mode (default auto) | |
| origins | Yes | Origin endpoints (1–25): address or 'lat,lon' | |
| destinations | Yes | Destination endpoints (1–25): address or 'lat,lon' |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| units | Yes | |
| matrix | Yes | matrix[i][j] = origin i → destination j: { distance (in the requested units), time_seconds }; both null when no route exists |
| costing | Yes | |
| origins | Yes | Geocoded origin locations |
| destinations | Yes | Geocoded destination locations |
| upstream_error | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds useful behavioral constraints beyond them: the N × M 625-pair cap and the flexible endpoint formats ('free-text addresses or lat,lon strings'). It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each with a distinct job: purpose, input constraints, and use cases. The most important information is front-loaded, with no filler or repetition of schema defaults.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the input schema fully documents parameters, the description covers everything needed to invoke it correctly: purpose, input formats, limits, and application context. 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. The description adds extra meaning by explaining the pair cap (625) and emphasizing that endpoints can be addresses or coordinates, reinforcing and slightly extending the schema's field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Compute road distances and travel times for every origin → destination pair.' This clearly distinguishes it from point-to-point routing (directions) and batch geocoding siblings by emphasizing the matrix nature (every pair, bulk ETAs).
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: 'fleet dispatch, nearest-depot, and bulk ETA tables.' This signals when to choose the matrix over simpler routing, though it does not explicitly name alternative tools or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exploreARead-onlyIdempotentInspect
BROWSING / DISCOVERY search — administrative places (cities, neighbourhoods, boroughs, counties, regions) near a location. Use this when the user is exploring a REGION rather than looking for a specific category. Supports population filtering ('cities > 100k'), ranking by significance or distance, and layer filtering (locality / neighbourhood / borough / county / region). Venues, addresses and streets are NOT served here — for venues and POI categories (gas, food, charging, etc.) use search_places instead. Each result carries its distance in the caller's units and a bearing from the center.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude of center point | |
| lon | No | Longitude of center point | |
| size | No | Max results (default 10, max 50) | |
| sort | No | Ranking basis. Default `population` — significance (population where the source has it) with distance as the tiebreak. `distance` is nearest first; `combined` blends population against a distance decay. The basis applied is echoed in meta.ranking. | |
| units | No | Units for a bare numeric `radius`: miles (default) or kilometers. Accepts the aliases mi, mile, imperial (miles) and km, kilometer, kilometre, kilometres, metric (kilometers), any case; echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Does not supply a radius on its own (the default is per layer — 150 km for locality/county/region, 25 km for neighbourhood/borough; tightest wins when mixed) but selects the display unit of the meta.radius / meta.units echo. | |
| layers | No | Comma-separated administrative layers: locality (default), neighbourhood, borough, county, region. venue, address, street and unknown names are rejected with a structured invalid_layer error — use search_places for venues. Radius policy is per layer: locality/county/region default 150 km and cap at 500 km; neighbourhood/borough default 25 km and cap at 100 km; a mixed request takes the tightest default and cap. With several layers, `size` is split evenly between them (remainder to the first) so one dense layer cannot flood the result. | |
| radius | No | Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('50km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('50km', '30mi') is also accepted for compatibility and its suffix wins. Per-layer policy: locality/county/region default 150 km (93.206 mi) and cap at 500 km (~310 mi); neighbourhood/borough default 25 km (15.534 mi) and cap at 100 km (~62 mi); a request naming several layers takes the tightest default and cap among them. Numeric values above 500 fail input validation before the tool runs; a string form over the maximum ('600km') or an in-range number that is over the cap once read as miles (e.g. 400, or 400 with units 'miles' — 644 km) returns a structured radius_exceeds_max error naming the governing cap instead of results. | |
| location | No | Center point address or 'lat,lon' | |
| min_population | No | Minimum population filter, applied JS-side to whichever layers are served (locality, neighbourhood, borough, county, region). | |
| boundary_country | No | ISO country code to restrict results (alpha-2 or alpha-3) |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent), the description reveals behavioral nuances: per-layer default radii and caps, how `size` is split across layers, the `meta.ranking` echo, and structured error responses like `radius_exceeds_max`. It also explains that `units` does not supply a radius on its own. This exceeds the annotation baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but logically organized, front-loading the core purpose and usage. Every sentence carries information, though some redundancy exists (e.g., repeated mentions of 'radius policy is per layer' and unit aliases in multiple parameters). Slightly verbose but not 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?
For a tool with 10 parameters and complex interdependencies, the description covers all critical interactions: how radius and units combine, layer-specific caps, error cases, and tie-breaking behavior. Since an output schema is present, lack of return details is acceptable. The agent has enough context to invoke it correctly in any scenario.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers 100% of parameters, but the description adds substantial meaning: `units` aliases and precedence rules, `layers` per-layer radius policies, `radius` error conditions and unit-suffix handling, and `sort` ranking semantics. This transforms bare schemas into actionable knowledge, well above the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is for browsing/discovery of administrative places near a location, and immediately distinguishes it from `search_places` for venues. The verb 'explore' and resource 'administrative places' are explicit, making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to use this tool ('when the user is exploring a REGION') and when not to use it ('venues, addresses and streets are NOT served here... use search_places'), plus provides detailed guidance on radius policies, layer restrictions, and unit handling. This leaves no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocodeARead-onlyIdempotentInspect
Convert an address, place name, street, or intersection into coordinates and structured location results. Use when input is text and you need coordinates before routing, weather, or search. Supports street-level resolution and proximity biasing.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Number of candidates to return (default 5, max 40) | |
| query | Yes | Address, place name, street, intersection (e.g. 'Broadway and 42nd Street New York'), or free-form location text | |
| layers | No | Restrict to: address, street, venue, locality. Use layers=street when user clearly wants a street entity. Use layers=venue for stadiums, monuments, parks, and named POIs (e.g. 'Minute Maid Park', 'Lambeau Field', 'Statue of Liberty') — bypasses address-parser tokenization that otherwise resolves venue+state to the state region centroid | |
| focus_lat | No | Bias results near this latitude — use when user says 'near me' or 'close to' | |
| focus_lon | No | Bias results near this longitude | |
| boundary_country | No | ISO country code to reduce ambiguity (alpha-2 or alpha-3) |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| precision | No | |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds behavioral capability context ('street-level resolution and proximity biasing'), which is useful, but says nothing about result ordering, fallback behavior when no match, or accuracy/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?
Three sentences, front-loaded with the core operation before usage and capabilities. Compact and no filler, though the capability sentence is somewhat redundant with the schema's parameter descriptions.
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. The description covers what the tool does, when to use it, and its resolution capability, which is enough for a geocoding call. The main gap is lack of sibling differentiation in a crowded geocoding family.
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 all six parameters are already richly documented in the schema (including the detailed layers guidance and focus_lat/lon biasing). The description only gestures at 'proximity biasing,' which the schema already explains, so it adds little beyond the structured fields. 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 ('Convert') and resource ('address, place name, street, or intersection into coordinates'). This implicitly distinguishes it from reverse_geocode (the inverse operation), though it never names siblings like geocode_structured or batch_geocode for explicit differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides usage context ('Use when input is text and you need coordinates before routing, weather, or search'), which implies when the tool is needed. However, it does not distinguish this tool from near-siblings such as geocode_structured, batch_geocode, or resolve_intersection, leaving the agent to infer which one to pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geocode_structuredARead-onlyIdempotentInspect
Geocode from discrete address components (address, locality, region, postalcode, country) instead of one free-text string. Use when the input is already fielded (forms, CRM records, stop tables) — skips free-text parsing so components can't be mis-tokenized. At least one component is required. No cross-street field: for named intersections use resolve_intersection or geocode.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Number of candidates to return (default 5, max 40) | |
| region | No | State / province — full name or abbreviation (e.g. 'TX') | |
| address | No | Street address — house number + street name (e.g. '1600 Pennsylvania Ave NW') | |
| country | No | ISO 3166-1 alpha-2/alpha-3 country code (full names also resolve) | |
| locality | No | City / town name | |
| focus_lat | No | Bias results near this latitude | |
| focus_lon | No | Bias results near this longitude | |
| postalcode | No | Postal / ZIP code | |
| boundary_country | No | Scope results to this ISO country code — wins over `country` for boundary filtering |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| precision | No | |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, openWorld and idempotent, so safety is covered. The description adds non-obvious behavioral facts: that free-text parsing is skipped (so components can't be mis-tokenized), that at least one component is required despite required=0 in the schema, and that there is no cross-street field. It stops short of describing the candidate set or ordering, but the added context is substantial.
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: the differentiator is front-loaded, the usage trigger comes second, and the exclusion/alternative routing comes last. No filler and nothing repeated from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. Given a 9-parameter, fully documented schema plus safety annotations, the description supplies exactly the extra context an agent needs — the input-shape constraint, the minimum-component requirement, and the missing cross-street capability.
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 every parameter including size, focus_lat/lon and boundary_country is already documented in the schema; the baseline is 3. The description enumerates the component fields but adds no syntax or precedence guidance beyond the schema (e.g. boundary_country winning over country is left to the 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 (Geocode) and the distinctive resource/input mode (discrete address components vs. one free-text string), and immediately distinguishes itself from geocode and resolve_intersection. An agent can tell this apart from its 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?
Explicitly says when to use it ('input is already fielded (forms, CRM records, stop tables)') and names the alternatives for the excluded case ('for named intersections use resolve_intersection or geocode'). Both routing conditions are stated, not inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
geofence_containsARead-onlyIdempotentInspect
Test one or more points for containment inside a caller-supplied GeoJSON polygon (or MultiPolygon / Feature / FeatureCollection). Pure geometry — boundary points count as contained. Returns one boolean per input point. Errors when the polygon is structurally invalid.
| Name | Required | Description | Default |
|---|---|---|---|
| points | Yes | Points to test ({ lat, lon } each), up to 1000 | |
| polygon | No | A GeoJSON Polygon / MultiPolygon geometry, a Feature wrapping one, or a FeatureCollection |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes | One containment boolean per input point (in order) |
| warnings | No | |
| point_count | Yes | Number of points tested |
| contained_count | Yes | How many input points are contained |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, openWorldHint, idempotentHint), the description discloses boundary point containment ('boundary points count as contained'), return shape ('Returns one boolean per input point'), and an error condition ('Errors when the polygon is structurally invalid'). This adds substantial 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?
The description is four sentences, all information-dense and front-loaded with the primary purpose. Every sentence adds value: purpose, geometry types/purity, boundary behavior, return format, and error condition. No redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers return format ('one boolean per input point'), boundary semantics, accepted geometry variants, and error behavior. Combined with the output schema and annotations, an agent has sufficient context to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters, so the baseline is 3. The description does not add meaningful parameter-level detail; it merely restates the polygon types already listed in the schema. No additional semantics about point format or polygon properties are provided.
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 'Test one or more points for containment inside a caller-supplied GeoJSON polygon', which clearly states the specific action and resource. It also enumerates supported geometry types and distinguishes this tool from the geocoding/routing siblings by focusing on pure geometric containment.
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 'Pure geometry' implies this is for geometric queries rather than place lookups, but no explicit 'use this instead of X' guidance is provided. There is no clear statement of when not to use the tool or how it compares to alternatives like reverse_geocode or search_places.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
isochroneARead-onlyIdempotentInspect
Generate travel-time or travel-distance reachability polygons from an origin. Pass MULTIPLE bands in one call — e.g. contours_minutes:[10,20,30] returns three nested polygons in a single response (one round-trip, not three). Use for service coverage, dispatch range, territory design, 'how far can I get in X minutes' questions, and concentric zone visualizations. Output is GeoJSON ready for Mapbox / Leaflet.
| Name | Required | Description | Default |
|---|---|---|---|
| costing | No | Transport mode | |
| location | Yes | Center point address or 'lat,lon' | |
| contours_km | No | Distance bands in km. Max 4 bands per call (over returns 400). | |
| truck_height | No | Truck height in meters | |
| truck_weight | No | Truck weight in metric tons | |
| contours_minutes | No | Time bands in minutes, e.g. [10, 20, 30]. Max 4 bands per call (over returns 400). |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering the safety and idempotency profile. The description adds meaningful behavior beyond annotations: multiple bands return nested polygons in a single response, and output is GeoJSON ready for Mapbox/Leaflet. This gives the agent useful operational context without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences, each earning its place: core function, multi-band efficiency tip with example, intended use cases, and output format. It is front-loaded with the primary purpose and contains zero filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of helpful annotations, an output schema, and full schema description coverage, the description supplies the essential extra context: clear use cases, multi-band round-trip optimization, and GeoJSON output. There is no need for it to restate parameter details or return value structure already captured elsewhere.
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 each parameter is already documented. The description supplements this with a concrete example (`contours_minutes:[10,20,30]`) and explains the efficiency advantage of multiple bands, which adds semantic value beyond the schema's basic descriptions. It doesn't explain the truck parameters, but the schema covers them adequately.
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 'Generate travel-time or travel-distance reachability polygons from an origin,' which is a specific verb and resource. It clearly distinguishes this tool from siblings like directions or distance_matrix by focusing on reachability polygons, and reinforces with concrete use cases like 'service coverage' and 'territory design.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong context for when to use the tool: 'Use for service coverage, dispatch range, territory design, how far can I get in X minutes questions, and concentric zone visualizations.' It also provides a practical efficiency tip about passing multiple bands in one call. However, it does not explicitly name alternative tools or when not to use it, so it doesn't earn a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
issue_api_keyAInspect
Issue a fresh ta_geo_* API key for ThinAir GEO (geocoding/routing) for your current authenticated user/tenant, and rotate: any previous key keeps working for one hour, then stops — the response reports how many and exactly when (previous_keys_retiring, previous_keys_retire_at). Use it to rotate, or when a CLI/MCP client needs a key and can't reach the console. The new key is tied to your existing plan. Counts as 1 query against your daily quota. NOTE: this key works ONLY against ThinAir Geo — it does NOT authenticate against ThinAir Data, which issues its own ta_data_* key from its own identically-named tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| plan | No | |
| user | No | |
| error | No | |
| usage | No | |
| key_id | No | Non-secret fingerprint of the issued key. Safe to log and surface in UI. |
| status | Yes | |
| api_key | No | One-time API key secret. Returned only on successful creation, in both structuredContent.api_key and content[0].text — save it immediately. The server stores only sha-256 of the secret; once this response is lost, the key is unrecoverable and must be rotated. Matches AWS IAM / Stripe / GitHub PAT one-time-reveal semantics. |
| previous_keys_retiring | No | How many previously-live keys this mint scheduled to retire. issue_api_key rotates: after the grace window the returned key is the only live key on the account. 0 means there was nothing else. |
| previous_keys_retire_at | No | ISO 8601 instant when the previous keys stop working (one hour after this mint). Present only when previous_keys_retiring > 0. Update anything still using them before this time. |
| credential_returned_once | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses rotation behavior beyond annotations: previous keys keep working for one hour then stop, the response reports retirement details, the key is tied to the existing plan, and the call counts against the daily quota. These behaviors are not inferable from the annotations and are clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and rotation behavior, then adds essential usage, quota, and scope caveats. Every sentence adds value, and the NOTE about ThinAir Data versus ThinAir Geo is clearly separated for emphasis.
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 zero parameters, an output schema, and annotations, the description covers everything needed to invoke the tool correctly: rotation semantics, exact retirement timing, quota cost, plan linkage, and scope restrictions. No critical context appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema is empty, so there is no parameter documentation burden. The description compensates by explaining that the key is scoped to the current authenticated user/tenant and tied to the existing plan, which clarifies why no parameters are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Issue a fresh ta_geo_* API key') and identifies the exact resource and scope (ThinAir GEO geocoding/routing for the current authenticated user/tenant). It also explicitly distinguishes this key from the ta_data_* key issued by ThinAir Data, preventing confusion with an identically-named sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: 'Use it to rotate, or when a CLI/MCP client needs a key and can't reach the console.' It also provides a clear exclusion by stating the key does NOT authenticate against ThinAir Data and that the Data tool issues its own key.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
locateARead-onlyIdempotentInspect
Snap one coordinate to the road network and return the matched road's context: name, road class, speed limit, bearing, snap distance, side of street, truck legality, and toll/ferry/highway/bridge/tunnel flags — plus the IANA timezone. Use to answer 'what road is this point on and what are its rules?' for fleet/telematics snapping, geofence edge checks, or enriching a GPS fix. Set include_elevation for terrain-sourced point elevation_m; grade_pct is a forward-compatible field that stays null for now. Returns matched:false when no routable road is near the point — never a guess.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude | |
| lon | Yes | Longitude | |
| units | No | Unit system for the human summary — auto-detected (US/UK → imperial) when omitted. | |
| costing | No | Travel profile scoping edge access/legality. Default 'auto'. | |
| include_elevation | No | Opt-in to point elevation — populates elevation_m/elevation_ft from terrain data (null with an 'elevation_unavailable' warning only where terrain isn't covered). grade_pct is a forward-compatible field that stays null for now (reserved for an elevation-enhanced road network). |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| road | No | |
| items | No | |
| geojson | No | |
| matched | No | |
| metrics | No | |
| summary | No | |
| location | No | |
| timezone | No | IANA timezone for the point, or null unless timezone_status is resolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain). |
| warnings | No | |
| grade_pct | No | |
| elevation_m | No | |
| display_hint | No | |
| elevation_ft | No | |
| timezone_status | No | |
| timezone_artifact_version | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld/idempotent annotations, it discloses a no-guess failure mode ('Returns matched:false ... never a guess'), the forward-compatible null behavior for grade_pct, and the elevation-unavailable warning. This is rich non-obvious 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 with no filler; the key purpose and output list are front-loaded, followed by usage guidance and failure behavior. The dense but organized structure lets an agent parse the essentials quickly.
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 plus full parameter coverage, the description still adds complete operational context: failure return, optional elevation behavior, and output field caveat. No critical calling context 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 applies; lat/lon/units/costing are already documented in the schema. The description only restates include_elevation behavior rather than adding new parameter-level semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Snap one coordinate to the road network') and enumerates the returned road context (name, road class, speed limit, bearing, etc.). It frames the tool's question ('what road is this point on and what are its rules?'), which clearly separates it from geocoding or direction 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?
It states explicit use contexts: fleet/telematics snapping, geofence edge checks, and enriching a GPS fix. It does not name sibling tools explicitly or provide when-not-to-use exclusion, but the use cases are clear enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
map_matchARead-onlyIdempotentInspect
Map matching snaps raw GPS breadcrumbs to the road network. Feed a recorded trace (2–100 points) and get back the road-accurate route that was actually driven: matched geometry, distance, time, road names, and a 0–1 match confidence. Use for fleet trace cleanup, mileage from GPS logs, and reconstructing routes from telemetry. road_names come from the route's maneuver points, so they cover the roads the route turns onto or starts on — for the name of every segment actually travelled, use trace_attributes. For planning a route between places, use directions instead.
| Name | Required | Description | Default |
|---|---|---|---|
| shape | Yes | Raw GPS breadcrumb trail in travel order — 2 to 100 points of { lat, lon, time? }. `time` is optional epoch seconds; timestamps improve match quality on noisy traces. | |
| costing | No | Transport mode the trace was recorded with (default: auto) | |
| search_radius | No | Snap radius in meters around each point (1–100). Increase for noisy GPS. | |
| vehicle_profile | No | Truck preset (DRY_VAN_53, FLATBED_48, BOX_TRUCK_26, …) — same 10-profile table as directions. Implies costing=truck. |
Output Schema
| Name | Required | Description |
|---|---|---|
| legs | Yes | |
| meta | No | |
| costing | Yes | |
| geojson | No | |
| matched | Yes | |
| geometry | No | |
| confidence | Yes | 0–1: fraction of input GPS points within the snap tolerance of the matched route |
| road_names | Yes | |
| distance_km | Yes | |
| costing_options | No | |
| vehicle_profile | No | |
| duration_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety. The description adds meaningful behavioral context beyond the schema: it discloses the return contents (matched geometry, distance, time, road names, confidence) and exposes a limitation (road_names derived only from maneuver points, not every segment). This is useful, non-obvious 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 with a distinct job: the core operation, use cases, a caveat about road names, and a routing to the correct sibling. The most important information is front-loaded, and there is no filler or repetition of schema details.
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 annotations, a fully described schema, and an output schema, the description covers use cases, limitations, alternatives, and expected results. An agent has everything it needs to decide when to call this tool and what to expect from it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents parameters such as shape, costing, search_radius, and vehicle_profile. The description reinforces the 2–100 point range and mentions the optional `time` field indirectly, but does not add meaning beyond 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: 'snaps raw GPS breadcrumbs to the road network' and explicitly lists the returned artifacts (matched geometry, distance, time, road names, confidence). It distinguishes itself from related tools by naming `directions` for route planning and `trace_attributes` for per-segment road 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?
It gives concrete use cases ('fleet trace cleanup, mileage from GPS logs, reconstructing routes from telemetry') and explicitly states when not to use it: 'For planning a route between places, use `directions` instead.' It also routes the agent to `trace_attributes` for a different need, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
place_getARead-onlyIdempotentInspect
Look up a place by its stable ThinAir id (ta_place_… / ta_intersection_…) as returned in the id field of geocode, reverse_geocode, search_places, or resolve_intersection results. Ids are deterministic and survive re-serves — safe to store as favorites or foreign keys. Returns the canonical name, label, layer, and coordinates. Unknown or expired ids error with re-search guidance.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ThinAir place id exactly as returned in a previous response's `id` field — ta_place_<key> or ta_intersection_<key> |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| lat | Yes | |
| lon | Yes | |
| meta | No | |
| name | No | |
| type | Yes | |
| label | No | |
| layer | No | |
| components | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, lowering the burden. The description adds meaningful behavior: ids survive re-serves (idempotency), return value contents, and error handling for unknown/expired ids with re-search guidance. This goes well beyond the annotations and gives the agent a clear model of what happens.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each contributing unique information: purpose, id source/stability, and return/error behavior. It is front-loaded with the core action 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 simple single-parameter lookup tool with an output schema and rich annotations, the description is complete. It covers purpose, id provenance, stability, return content, and error behavior. No significant gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides full parameter coverage (100%) including the id format and constraints. The description adds value by naming the exact source tools (geocode, reverse_geocode, search_places, resolve_intersection) and highlighting id stability and determinism, which are not in the schema. This enriches the semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb ('Look up') with a specific resource ('place by its stable ThinAir id') and identifies the id format (ta_place_… / ta_intersection_…). It also names the sibling tools that produce these ids, which distinguishes this lookup tool from geocoding and search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool: when you have an id from geocode, reverse_geocode, search_places, or resolve_intersection, and want canonical data. It emphasizes the ids are deterministic and safe to store, implying reuse over repeated lookups. It doesn't explicitly state when not to use alternatives, but the context is strong enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
quotaARead-onlyInspect
Check current usage, remaining limits, plan, and quota breakdown for the caller. FREE TO CALL — never counts against your quota, never blocked by it. Use this proactively when the user asks about usage or seems near limits.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| mcp | Yes | |
| upstream | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description reveals a critical behavioral trait: the call never counts against quota and is never blocked by it. This is valuable context not present in annotations and directly influences the agent's willingness to call the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose, then a high-value clarifying detail about quota impact. Every word earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, parameterless tool, the description fully covers what it returns (usage, limits, plan, breakdown) and when to call it. The output schema exists to detail return structure, so the description is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so no parameter descriptions are needed. The schema already fully covers this aspect (100% coverage with no properties), meeting the baseline for no-parameter tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Check current usage, remaining limits, plan, and quota breakdown for the caller.' It uses a specific verb ('Check') and precise resource identifiers, distinguishing it from sibling tools like issue_api_key or geocoding services.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: 'Use this proactively when the user asks about usage or seems near limits.' Also adds that it is 'FREE TO CALL — never counts against your quota, never blocked by it,' reinforcing why it should be used without hesitation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_intersectionARead-onlyIdempotentInspect
Resolve a NAMED cross-street (street1 × street2 within a locality/region/country) to a single best coordinate with a confidence score and a fleet-safe fallback. High-confidence tier matches US-metro highway corners; named non-highway streets resolve via the geocoder fallback. For free-form streets use geocode.
| Name | Required | Description | Default |
|---|---|---|---|
| region | No | State / province (full name or abbreviation, e.g. 'TX') | |
| country | No | ISO 3166-1 alpha-2/alpha-3 country code | |
| street1 | Yes | First street of the cross-street pair | |
| street2 | Yes | Second (cross) street of the pair | |
| locality | No | City / town that scopes the lookup |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| admin | No | |
| feature | Yes | Best resolved intersection feature, including validated optional intersection provenance, or null when nothing resolved |
| warnings | No | |
| precision | No | |
| confidence | Yes | Resolved confidence 0–1 (0 when nothing resolved) |
| fallback_used | No | True when the geocoder fallback produced the answer |
| upstream_error | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld/idempotent, so the safety profile is covered. The description adds genuine behavioral context beyond that: a confidence score is returned, a fleet-safe fallback exists, and resolution is tiered (high-confidence highway corners vs geocoder fallback). It does not discuss failure modes 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?
Three sentences, front-loaded with the core action and scope, followed by tier behavior and the routing hint. Dense but each sentence carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return value shape need not be described, and annotations cover the safety profile. The description supplies the tiering and fallback context an agent needs to interpret results; only sibling disambiguation against geocode_structured 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 all five parameters (street1, street2, locality, region, country) are already documented in the schema. The description restates the street1 × street2 pairing and the locality/region/country scoping but adds no format or constraint detail beyond it; 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 (Resolve) and resource (a NAMED cross-street, defined as street1 × street2 scoped by locality/region/country), and explicitly names the sibling it is not (geocode for free-form streets). An agent can distinguish this from geocode/geocode_structured 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 a clear routing rule: use this for NAMED cross-streets, use geocode for free-form streets. It also explains that high-confidence tier matches US-metro highway corners while named non-highway streets fall back to the geocoder. It does not disambiguate against geocode_structured, so it stops short of full when/when-not coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reverse_geocodeARead-onlyIdempotentInspect
Convert coordinates into the nearest address, street, or place. Use when starting from GPS coordinates or a map position.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude | |
| lon | Yes | Longitude | |
| size | No | Number of nearby candidates (default 3, max 40) | |
| layers | No | Restrict to a comma list of: address, street, venue, neighbourhood, borough, locality, localadmin, county, macrocounty, region, macroregion, dependency, country, continent, postalcode, coarse. Admin layers resolve from the nearest indexed feature's parent hierarchy. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| precision | No | |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds no behavioral context such as whether multiple candidates are returned or how layers affect the result, so it earns only the baseline plus usage framing.
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 short sentences with zero waste; the purpose is front-loaded before the usage cue.
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 described, and annotations cover the safety profile. For a simple two-required-parameter tool this is nearly complete, though it omits any note on candidate limits or layer effects.
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%, with lat/lon, size and layers fully documented in the schema. The description contributes no additional parameter 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 ('Convert') and resource ('coordinates into nearest address, street, or place'), making the inverse-of-geocode direction explicit. An agent can distinguish this from geocode/geocode_structured 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?
'Use when starting from GPS coordinates or a map position' gives a clear triggering condition. It does not name the forward alternative (geocode) or exclusions, so it stops short of full when/when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_placesARead-onlyIdempotentInspect
CATEGORY-specific POI search near a point — gas stations, truck stops, restaurants, charging stations, etc. Use this when the user has a specific TYPE of place in mind (food / health / retail / fuel / accommodation / nightlife / transport / government / recreation). For broader DISCOVERY (e.g. 'cities within 50 miles' or 'venues by population'), use explore instead.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Center latitude (alternative to `center` object) | |
| lon | No | Center longitude (alternative to `center` object) | |
| limit | No | Max results (default 10, max 50) | |
| query | No | Free-text place query such as 'truck stop', 'restaurant', 'charging station'. One of `query` or `categories` is required — a bare center (`lat`+`lon`/`center`) with neither is rejected. | |
| units | No | Units for a bare numeric `radius`: miles (default) or kilometers. Accepts the aliases mi, mile, imperial (miles) and km, kilometer, kilometre, kilometres, metric (kilometers), any case; echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Not valid with `radius_m` alone — radius_m is always meters, so that pair is rejected. Does not supply a radius on its own (the default 50 km applies) but selects the display unit of the `units` echo. | |
| center | No | Center point for nearby search ({lat, lon} object or JSON string). You can also pass flat lat/lon. | |
| layers | No | Restrict to: venue, address | |
| radius | No | Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('5km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('30mi', '5km') is also accepted and its suffix wins. Default 50 km (about 31 mi); maximum 50 km (up to 31.068 mi). Preferred over `radius_m`. Numeric values above 50 fail input validation before the tool runs; a string form over the maximum ('60km') or an in-range number that is over the cap once read as miles (e.g. 40, or 40 with units 'miles' — 64 km) is rejected with a radius error instead of results. | |
| radius_m | No | Search radius in meters (max 50000 — i.e. 50 km / ~31 mi; default 50 km; 0 means 'not supplied' and applies the default). Accepted alias; `radius` + `units` is preferred. Sending both is only valid when they agree. Do not pair with `units`. | |
| categories | No | Structured categories: food, fuel, charging_station, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation. One of `categories` or `query` is required — a bare center (`lat`+`lon`/`center`) with neither is rejected. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety and idempotency. The description adds the behavioral nuance that this is a category-filtered, point-anchored search, which clarifies its scope beyond the annotations. It doesn't cover return details, but the output schema exists, so the bar is lower.
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 compact sentences: the first states the tool's purpose with concrete examples, the second gives usage guidance and names the alternative. No filler, and the key category-specific behavior 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 tool with 10 parameters, nested objects, and a full output schema, the description provides the essential decision context (when to use vs `explore`) without duplicating schema details. Everything an agent needs to decide on and invoke it correctly is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 10 parameters are fully documented in the schema. The description reinforces the importance of the categories parameter by listing examples, but does not add substantive semantics beyond what the schema already provides. 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 clearly states the tool performs a CATEGORY-specific POI search near a point, with explicit examples and a list of categories. It also distinguishes itself from the sibling `explore` by naming the specific use case (specific type vs broader discovery), making its purpose 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?
Explicitly tells when to use this tool ('when the user has a specific TYPE of place in mind') and when not to, pointing directly to `explore` as the alternative for broader discovery. This is the ideal level of routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trace_attributesARead-onlyIdempotentInspect
Trace attributes return road/network attributes for matched traces. Feed a GPS breadcrumb trail (2–100 points) and get per-segment road names, road classes, speed limits, surfaces, truck-route flags, and segment lengths along the matched route, plus a matcher confidence score. Use to audit what roads a vehicle actually used (speed-limit compliance, truck-route adherence, surface checks). For just the matched route line, use map_match.
| Name | Required | Description | Default |
|---|---|---|---|
| shape | Yes | Raw GPS breadcrumb trail in travel order — 2 to 100 points of { lat, lon, time? }. `time` is optional epoch seconds; timestamps improve match quality on noisy traces. | |
| costing | No | Transport mode the trace was recorded with (default: auto) | |
| search_radius | No | Snap radius in meters around each point (1–100). Increase for noisy GPS. | |
| vehicle_profile | No | Truck preset (DRY_VAN_53, FLATBED_48, BOX_TRUCK_26, …) — same 10-profile table as directions. Implies costing=truck. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| edges | Yes | |
| admins | No | |
| costing | Yes | |
| geojson | No | |
| matched | Yes | |
| geometry | No | |
| confidence | Yes | Matcher confidence 0–1 |
| edge_count | Yes | |
| road_names | Yes | |
| distance_km | Yes | |
| costing_options | No | |
| vehicle_profile | No | |
| duration_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true. The description adds behavioral context by revealing the matcher confidence score and the segment-level output, and the audit use case. No contradictions.
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: function, output/use case, and sibling alternative. Front-loaded with the main verb and resource, no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a strong output schema and detailed parameter schema, the description covers purpose, use case, and alternatives. It is complete for a read-only trace-analysis tool with good annotations.
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 baseline is 3. The description doesn't add parameter-specific meaning beyond what the schema already provides; it only summarizes the input (GPS breadcrumb) and output. No new semantics 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?
States it 'return road/network attributes for matched traces' and lists the concrete attributes (road names, classes, speed limits, etc.). Explicitly distinguishes from sibling `map_match` by saying 'For just the matched route line, use `map_match`'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear when-to-use context: 'Use to audit what roads a vehicle actually used (speed-limit compliance, truck-route adherence, surface checks)'. Also explicitly names the alternative `map_match` for route-line-only needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trafficARead-onlyInspect
Retrieve live traffic conditions, congestion, and speed for a location. Use when traffic is needed independently of routing — for corridor monitoring, area congestion, or incident checks. COVERAGE: live data for ~30 major US metros; returns degraded or empty values outside these areas. For rural coordinates, qualify the response (e.g. 'no live traffic coverage here — showing free-flow speeds').
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude | |
| lon | Yes | Longitude | |
| units | No | Speed units — auto-detected from location (mph in US/UK, km/h elsewhere). Override if needed. Accepts 'km'/'mi' as aliases. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond annotations by disclosing coverage limitations (~30 major US metros), degraded/empty values outside those areas, and instructing to qualify responses for rural locations. This adds significant behavioral context that annotations (readOnlyHint, openWorldHint, idempotentHint) do not 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?
The description is three sentences, each serving a distinct purpose: core function, usage context, and coverage caveat. It is front-loaded and concise, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple location-based tool, the description covers the essential caveat (coverage limitation) and usage context. An output schema exists, so return values are already specified, and annotations provide safety hints. The description is complete enough for an agent to select and invoke 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 parameters are already well-documented (lat/lon, units with auto-detection and aliases). The description adds no meaningful parameter information beyond the schema, so the baseline score 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 clearly states the tool retrieves live traffic conditions, congestion, and speed for a location, with a specific verb and resource. It distinguishes this tool from siblings by noting 'independently of routing', which separates it from directions and routing-focused tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use the tool ('when traffic is needed independently of routing') and provides use cases (corridor monitoring, area congestion, incident checks). It also includes guidance for handling rural coordinates, which shows thoughtful usage instructions beyond alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
weatherARead-onlyInspect
Get current and forecast weather for a location, including severe weather alerts and minute-by-minute precipitation. Use for destination conditions, travel planning, or route risk assessment.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude | |
| lon | No | Longitude | |
| units | No | Temperature/wind units (default: imperial) | |
| location | No | Place name or address (will be geocoded) | |
| forecast_days | No | Forecast days 1-16 (default 5) | |
| include_alerts | No | Include severe weather alerts and warnings (default: true) | |
| include_forecast | No | Include multi-day hourly forecast | |
| include_minutely | No | Include minute-by-minute precipitation for next 60 min |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | |
| alerts | No | |
| geojson | No | |
| metrics | No | |
| summary | No | Map of scalar facts the LLM should surface verbatim |
| alerts_error | No | |
| display_hint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=true, so the safety profile is already known. The description adds useful behavioral detail beyond annotations by specifying that the response includes current conditions, forecasts, severe alerts, and minutely precipitation. It does not contradict annotations and gives the agent a clear sense of the tool's data scope.
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 sentences with no filler. The first sentence states the core function and key included data; the second provides concrete use cases. 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?
The description is complete enough given the annotations, 100% schema coverage, and the presence of an output schema. It names the core data products and use cases. It does not explicitly discuss rate limits, fallback behavior when no location is supplied, or exact return structure, but these are either covered by annotations/schema or are not required for calling the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter already has a meaningful description. The tool description adds general context about location and weather features but does not explain parameter nuances such as how to choose between lat/lon and the geocoded 'location' parameter, which is acceptable because the schema already covers these.
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 ('Get current and forecast weather') on a clear resource ('a location') and explicitly names notable outputs ('severe weather alerts', 'minute-by-minute precipitation'). This makes the tool's function immediately identifiable and distinct from the broader sibling 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 use cases: 'destination conditions, travel planning, or route risk assessment.' It does not mention explicitly when not to use the tool or name alternative siblings, but the use-case framing is sufficient for an agent to select it appropriately in most contexts.
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
search_places8 fields changed- added
Input schema / properties / center / properties / lat / $refAdded value: +"#/properties/lat" - removed
Input schema / properties / center / properties / lat / maximumRemoved value: -90 - removed
Input schema / properties / center / properties / lat / minimumRemoved value: --90 - removed
Input schema / properties / center / properties / lat / typeRemoved value: -"number" - added
Input schema / properties / center / properties / lon / $refAdded value: +"#/properties/lon" - removed
Input schema / properties / center / properties / lon / maximumRemoved value: -180 - removed
Input schema / properties / center / properties / lon / minimumRemoved value: --180 - removed
Input schema / properties / center / properties / lon / typeRemoved value: -"number"
1 tool update
- Changed
weather1 field changed- added
Output schema / properties / alerts_errorAdded value: +{ + "type": "string" +}
4 tool updates
- Changed
geocode1 field changed- changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 read from the selected result's own postal-code field. While origin enforcement is active this field is emitted ONLY when the engine stamped the value as coming from the address record itself (`source_record` provenance); a value inherited from a parent area, or a result cached before that evidence existed, is omitted rather than emitted without provenance — so an absent ZIP under enforcement means \"not proven for this record\", not \"no such ZIP\". Provenance describes only WHERE the value came from. It is not a postal operator check of any kind — no certification, no address-quality rating, and no statement about whether mail would arrive — so a syntactically correct, correctly-sourced value can still be wrong for the address. Also omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
- Changed
geocode_structured1 field changed- changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 read from the selected result's own postal-code field. While origin enforcement is active this field is emitted ONLY when the engine stamped the value as coming from the address record itself (`source_record` provenance); a value inherited from a parent area, or a result cached before that evidence existed, is omitted rather than emitted without provenance — so an absent ZIP under enforcement means \"not proven for this record\", not \"no such ZIP\". Provenance describes only WHERE the value came from. It is not a postal operator check of any kind — no certification, no address-quality rating, and no statement about whether mail would arrive — so a syntactically correct, correctly-sourced value can still be wrong for the address. Also omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
- Changed
resolve_intersection1 field changed- changed
Output schema / properties / feature / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "address_components": { - "additionalProperties": false, - "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", - "properties": { - "country_code": { - "type": "string" - }, - "house_number": { - "type": "string" - }, - "locality": { - "type": "string" - }, - "postal_code": { - "type": "string" - }, - "region_code": { - "type": "string" - }, - "region_name": { - "type": "string" - }, - "street": { - "type": "string" - }, - "unit": { - "type": "string" - } - }, - "type": "object" - }, - "address_evidence": { - "additionalProperties": false, - "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", - "properties": { - "house_number": { - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "locality": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "postal_code": { - "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "region": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "street": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - } - }, - "required": [ - "house_number", - "street", - "locality", - "region", - "postal_code" - ], - "type": "object" - }, - "address_line1": { - "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", - "type": "string" - }, - "address_line2": { - "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", - "type": "string" - }, - "confidence": { - "type": "number" - }, - "confidence_scope": { - "const": "query_to_candidate", - "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", - "type": "string" - }, - "cross_street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "cross_street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - }, - "formatted_address": { - "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", - "type": "string" - }, - "id": { - "type": "string" - }, - "intersection_precision": { - "enum": [ - "geometric_crossing", - "tangent_intersection", - "centroid_cluster", - "approximate" - ], - "type": "string" - }, - "intersection_type": { - "enum": [ - "corner", - "interchange" - ], - "type": "string" - }, - "label": { - "type": "string" - }, - "lat": { - "type": "number" - }, - "layer": { - "type": "string" - }, - "lon": { - "type": "number" - }, - "method": { - "type": "string" - }, - "name": { - "type": "string" - }, - "place_type": { - "type": "string" - }, - "postal_code": { - "description": "An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", - "pattern": "^[0-9]{5}$", - "type": "string" - }, - "postal_input_match": { - "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", - "enum": [ - "match", - "conflict", - "unavailable" - ], - "type": "string" - }, - "street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "address_components": { + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "region_name": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" + }, + "address_evidence": { + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" + }, + "address_line1": { + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" + }, + "address_line2": { + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" + }, + "confidence": { + "type": "number" + }, + "confidence_scope": { + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" + }, + "cross_street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "cross_street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "formatted_address": { + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" + }, + "id": { + "type": "string" + }, + "intersection_precision": { + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" + }, + "intersection_type": { + "enum": [ + "corner", + "interchange" + ], + "type": "string" + }, + "label": { + "type": "string" + }, + "lat": { + "type": "number" + }, + "layer": { + "type": "string" + }, + "lon": { + "type": "number" + }, + "method": { + "type": "string" + }, + "name": { + "type": "string" + }, + "place_type": { + "type": "string" + }, + "postal_code": { + "description": "An eligible US ZIP5 read from the selected result's own postal-code field. While origin enforcement is active this field is emitted ONLY when the engine stamped the value as coming from the address record itself (`source_record` provenance); a value inherited from a parent area, or a result cached before that evidence existed, is omitted rather than emitted without provenance — so an absent ZIP under enforcement means \"not proven for this record\", not \"no such ZIP\". Provenance describes only WHERE the value came from. It is not a postal operator check of any kind — no certification, no address-quality rating, and no statement about whether mail would arrive — so a syntactically correct, correctly-sourced value can still be wrong for the address. Also omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" + }, + "postal_input_match": { + "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", + "enum": [ + "match", + "conflict", + "unavailable" + ], + "type": "string" + }, + "street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + { + "type": "null" + } +]
- Changed
reverse_geocode1 field changed- changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 read from the selected result's own postal-code field. While origin enforcement is active this field is emitted ONLY when the engine stamped the value as coming from the address record itself (`source_record` provenance); a value inherited from a parent area, or a result cached before that evidence existed, is omitted rather than emitted without provenance — so an absent ZIP under enforcement means \"not proven for this record\", not \"no such ZIP\". Provenance describes only WHERE the value came from. It is not a postal operator check of any kind — no certification, no address-quality rating, and no statement about whether mail would arrive — so a syntactically correct, correctly-sourced value can still be wrong for the address. Also omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
4 tool updates
- Changed
geocode2 fields changed- added
Output schema / properties / items / items / properties / address_components / properties / region_nameAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / postal_input_matchAdded value: +{ + "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", + "enum": [ + "match", + "conflict", + "unavailable" + ], + "type": "string" +}
- Changed
geocode_structured2 fields changed- added
Output schema / properties / items / items / properties / address_components / properties / region_nameAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / postal_input_matchAdded value: +{ + "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", + "enum": [ + "match", + "conflict", + "unavailable" + ], + "type": "string" +}
- Changed
resolve_intersection1 field changed- changed
Output schema / properties / feature / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "address_components": { - "additionalProperties": false, - "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", - "properties": { - "country_code": { - "type": "string" - }, - "house_number": { - "type": "string" - }, - "locality": { - "type": "string" - }, - "postal_code": { - "type": "string" - }, - "region_code": { - "type": "string" - }, - "street": { - "type": "string" - }, - "unit": { - "type": "string" - } - }, - "type": "object" - }, - "address_evidence": { - "additionalProperties": false, - "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", - "properties": { - "house_number": { - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "locality": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "postal_code": { - "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "region": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "street": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - } - }, - "required": [ - "house_number", - "street", - "locality", - "region", - "postal_code" - ], - "type": "object" - }, - "address_line1": { - "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", - "type": "string" - }, - "address_line2": { - "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", - "type": "string" - }, - "confidence": { - "type": "number" - }, - "confidence_scope": { - "const": "query_to_candidate", - "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", - "type": "string" - }, - "cross_street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "cross_street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - }, - "formatted_address": { - "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", - "type": "string" - }, - "id": { - "type": "string" - }, - "intersection_precision": { - "enum": [ - "geometric_crossing", - "tangent_intersection", - "centroid_cluster", - "approximate" - ], - "type": "string" - }, - "intersection_type": { - "enum": [ - "corner", - "interchange" - ], - "type": "string" - }, - "label": { - "type": "string" - }, - "lat": { - "type": "number" - }, - "layer": { - "type": "string" - }, - "lon": { - "type": "number" - }, - "method": { - "type": "string" - }, - "name": { - "type": "string" - }, - "place_type": { - "type": "string" - }, - "postal_code": { - "description": "An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", - "pattern": "^[0-9]{5}$", - "type": "string" - }, - "street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "address_components": { + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "region_name": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" + }, + "address_evidence": { + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" + }, + "address_line1": { + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" + }, + "address_line2": { + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" + }, + "confidence": { + "type": "number" + }, + "confidence_scope": { + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" + }, + "cross_street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "cross_street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "formatted_address": { + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" + }, + "id": { + "type": "string" + }, + "intersection_precision": { + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" + }, + "intersection_type": { + "enum": [ + "corner", + "interchange" + ], + "type": "string" + }, + "label": { + "type": "string" + }, + "lat": { + "type": "number" + }, + "layer": { + "type": "string" + }, + "lon": { + "type": "number" + }, + "method": { + "type": "string" + }, + "name": { + "type": "string" + }, + "place_type": { + "type": "string" + }, + "postal_code": { + "description": "An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" + }, + "postal_input_match": { + "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", + "enum": [ + "match", + "conflict", + "unavailable" + ], + "type": "string" + }, + "street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + { + "type": "null" + } +]
- Changed
reverse_geocode2 fields changed- added
Output schema / properties / items / items / properties / address_components / properties / region_nameAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / postal_input_matchAdded value: +{ + "description": "STRUCTURED GEOCODING ONLY (`geocode_structured` / `POST /v1/search/structured`); absent from free-text geocoding. Whether the postcode YOU SUBMITTED agrees with this candidate's own postcode — `match` (same five-digit value), `conflict` (they differ), `unavailable` (no comparison was possible). This compares two values already in hand: no lookup, no external reference, and your query text is never parsed to find one. `conflict` does NOT say which side is wrong — your input may name a neighbouring area, the candidate may be a near-miss, or the record's own value may be stale; treat it as a prompt to ask a human, never as a correction to apply automatically. The candidate side counts only when its postcode came from the address record itself; one inherited from a parent area yields `unavailable` rather than a misleading verdict. `unavailable` also covers: nothing submitted, a submitted value not readable as a US five-digit code, and results cached before this field existed.", + "enum": [ + "match", + "conflict", + "unavailable" + ], + "type": "string" +}
4 tool updates
- Changed
geocode5 fields changed- added
Output schema / properties / items / items / properties / address_componentsAdded value: +{ + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" +} - added
Output schema / properties / items / items / properties / address_line1Added value: +{ + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" +} - added
Output schema / properties / items / items / properties / address_line2Added value: +{ + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" +} - added
Output schema / properties / items / items / properties / formatted_addressAdded value: +{ + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" +} - changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
- Changed
geocode_structured5 fields changed- added
Output schema / properties / items / items / properties / address_componentsAdded value: +{ + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" +} - added
Output schema / properties / items / items / properties / address_line1Added value: +{ + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" +} - added
Output schema / properties / items / items / properties / address_line2Added value: +{ + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" +} - added
Output schema / properties / items / items / properties / formatted_addressAdded value: +{ + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" +} - changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
- Changed
resolve_intersection1 field changed- changed
Output schema / properties / feature / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "address_evidence": { - "additionalProperties": false, - "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", - "properties": { - "house_number": { - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "locality": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "postal_code": { - "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "region": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "street": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - } - }, - "required": [ - "house_number", - "street", - "locality", - "region", - "postal_code" - ], - "type": "object" - }, - "confidence": { - "type": "number" - }, - "confidence_scope": { - "const": "query_to_candidate", - "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", - "type": "string" - }, - "cross_street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "cross_street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - }, - "id": { - "type": "string" - }, - "intersection_precision": { - "enum": [ - "geometric_crossing", - "tangent_intersection", - "centroid_cluster", - "approximate" - ], - "type": "string" - }, - "intersection_type": { - "enum": [ - "corner", - "interchange" - ], - "type": "string" - }, - "label": { - "type": "string" - }, - "lat": { - "type": "number" - }, - "layer": { - "type": "string" - }, - "lon": { - "type": "number" - }, - "method": { - "type": "string" - }, - "name": { - "type": "string" - }, - "place_type": { - "type": "string" - }, - "postal_code": { - "description": "Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", - "pattern": "^[0-9]{5}$", - "type": "string" - }, - "street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "address_components": { + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" + }, + "address_evidence": { + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" + }, + "address_line1": { + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" + }, + "address_line2": { + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" + }, + "confidence": { + "type": "number" + }, + "confidence_scope": { + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" + }, + "cross_street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "cross_street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "formatted_address": { + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" + }, + "id": { + "type": "string" + }, + "intersection_precision": { + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" + }, + "intersection_type": { + "enum": [ + "corner", + "interchange" + ], + "type": "string" + }, + "label": { + "type": "string" + }, + "lat": { + "type": "number" + }, + "layer": { + "type": "string" + }, + "lon": { + "type": "number" + }, + "method": { + "type": "string" + }, + "name": { + "type": "string" + }, + "place_type": { + "type": "string" + }, + "postal_code": { + "description": "An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" + }, + "street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + { + "type": "null" + } +]
- Changed
reverse_geocode5 fields changed- added
Output schema / properties / items / items / properties / address_componentsAdded value: +{ + "additionalProperties": false, + "description": "The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.", + "properties": { + "country_code": { + "type": "string" + }, + "house_number": { + "type": "string" + }, + "locality": { + "type": "string" + }, + "postal_code": { + "type": "string" + }, + "region_code": { + "type": "string" + }, + "street": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "type": "object" +} - added
Output schema / properties / items / items / properties / address_line1Added value: +{ + "description": "House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.", + "type": "string" +} - added
Output schema / properties / items / items / properties / address_line2Added value: +{ + "description": "Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.", + "type": "string" +} - added
Output schema / properties / items / items / properties / formatted_addressAdded value: +{ + "description": "Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.", + "type": "string" +} - changed
Output schema / properties / items / items / properties / postal_code / descriptionPrevious value: -"Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."New value: +"An eligible US ZIP5 normalized from the selected native result's available postal-code field; direct address-record origin is not yet guaranteed. Not checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied."
4 tool updates
- Changed
geocode1 field changed- added
Output schema / properties / items / items / properties / postal_codeAdded value: +{ + "description": "Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" +}
- Changed
geocode_structured1 field changed- added
Output schema / properties / items / items / properties / postal_codeAdded value: +{ + "description": "Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" +}
- Changed
resolve_intersection1 field changed- changed
Output schema / properties / feature / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "address_evidence": { - "additionalProperties": false, - "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", - "properties": { - "house_number": { - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "locality": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "postal_code": { - "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", - "enum": [ - "matched", - "partial", - "absent" - ], - "type": "string" - }, - "region": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - }, - "street": { - "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" - } - }, - "required": [ - "house_number", - "street", - "locality", - "region", - "postal_code" - ], - "type": "object" - }, - "confidence": { - "type": "number" - }, - "confidence_scope": { - "const": "query_to_candidate", - "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", - "type": "string" - }, - "cross_street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "cross_street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - }, - "id": { - "type": "string" - }, - "intersection_precision": { - "enum": [ - "geometric_crossing", - "tangent_intersection", - "centroid_cluster", - "approximate" - ], - "type": "string" - }, - "intersection_type": { - "enum": [ - "corner", - "interchange" - ], - "type": "string" - }, - "label": { - "type": "string" - }, - "lat": { - "type": "number" - }, - "layer": { - "type": "string" - }, - "lon": { - "type": "number" - }, - "method": { - "type": "string" - }, - "name": { - "type": "string" - }, - "place_type": { - "type": "string" - }, - "street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "address_evidence": { + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" + }, + "confidence": { + "type": "number" + }, + "confidence_scope": { + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" + }, + "cross_street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "cross_street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "id": { + "type": "string" + }, + "intersection_precision": { + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" + }, + "intersection_type": { + "enum": [ + "corner", + "interchange" + ], + "type": "string" + }, + "label": { + "type": "string" + }, + "lat": { + "type": "number" + }, + "layer": { + "type": "string" + }, + "lon": { + "type": "number" + }, + "method": { + "type": "string" + }, + "name": { + "type": "string" + }, + "place_type": { + "type": "string" + }, + "postal_code": { + "description": "Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" + }, + "street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + { + "type": "null" + } +]
- Changed
reverse_geocode1 field changed- added
Output schema / properties / items / items / properties / postal_codeAdded value: +{ + "description": "Five-digit ZIP taken from the postcode supplied with this address record. It is reported by that record's own data source and has not been checked against any postal operator's records, so a syntactically correct value can still be wrong for the address. Omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.", + "pattern": "^[0-9]{5}$", + "type": "string" +}
4 tool updates
- Changed
geocode2 fields changed- added
Output schema / properties / items / items / properties / address_evidenceAdded value: +{ + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" +} - added
Output schema / properties / items / items / properties / confidence_scopeAdded value: +{ + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" +}
- Changed
geocode_structured2 fields changed- added
Output schema / properties / items / items / properties / address_evidenceAdded value: +{ + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" +} - added
Output schema / properties / items / items / properties / confidence_scopeAdded value: +{ + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" +}
- Changed
resolve_intersection1 field changed- changed
Output schema / properties / feature / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": { - "confidence": { - "type": "number" - }, - "cross_street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "cross_street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - }, - "id": { - "type": "string" - }, - "intersection_precision": { - "enum": [ - "geometric_crossing", - "tangent_intersection", - "centroid_cluster", - "approximate" - ], - "type": "string" - }, - "intersection_type": { - "enum": [ - "corner", - "interchange" - ], - "type": "string" - }, - "label": { - "type": "string" - }, - "lat": { - "type": "number" - }, - "layer": { - "type": "string" - }, - "lon": { - "type": "number" - }, - "method": { - "type": "string" - }, - "name": { - "type": "string" - }, - "place_type": { - "type": "string" - }, - "street_kind": { - "enum": [ - "street", - "route" - ], - "type": "string" - }, - "street_route": { - "maxLength": 128, - "minLength": 1, - "type": "string" - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": true, + "properties": { + "address_evidence": { + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/feature/anyOf/0/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" + }, + "confidence": { + "type": "number" + }, + "confidence_scope": { + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" + }, + "cross_street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "cross_street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "id": { + "type": "string" + }, + "intersection_precision": { + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" + }, + "intersection_type": { + "enum": [ + "corner", + "interchange" + ], + "type": "string" + }, + "label": { + "type": "string" + }, + "lat": { + "type": "number" + }, + "layer": { + "type": "string" + }, + "lon": { + "type": "number" + }, + "method": { + "type": "string" + }, + "name": { + "type": "string" + }, + "place_type": { + "type": "string" + }, + "street_kind": { + "enum": [ + "street", + "route" + ], + "type": "string" + }, + "street_route": { + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + { + "type": "null" + } +]
- Changed
reverse_geocode2 fields changed- added
Output schema / properties / items / items / properties / address_evidenceAdded value: +{ + "additionalProperties": false, + "description": "What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.", + "properties": { + "house_number": { + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "locality": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "postal_code": { + "description": "Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.", + "enum": [ + "matched", + "partial", + "absent" + ], + "type": "string" + }, + "region": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + }, + "street": { + "$ref": "#/properties/items/items/properties/address_evidence/properties/house_number" + } + }, + "required": [ + "house_number", + "street", + "locality", + "region", + "postal_code" + ], + "type": "object" +} - added
Output schema / properties / items / items / properties / confidence_scopeAdded value: +{ + "const": "query_to_candidate", + "description": "What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.", + "type": "string" +}
2 tool updates
- Changed
directions5 fields changed- added
Output schema / properties / timezone_artifact_versionAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / timezone_end / descriptionAdded value: +"IANA timezone at the route destination, or null when unresolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain)." - added
Output schema / properties / timezone_end_statusAdded value: +{ + "enum": [ + "resolved", + "boundary_ambiguous", + "source_conflict", + "not_covered", + "unavailable" + ], + "type": "string" +} - added
Output schema / properties / timezone_start / descriptionAdded value: +"IANA timezone at the route origin, or null when unresolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain)." - added
Output schema / properties / timezone_start_statusAdded value: +{ + "enum": [ + "resolved", + "boundary_ambiguous", + "source_conflict", + "not_covered", + "unavailable" + ], + "type": "string" +}
- Changed
locate3 fields changed- added
Output schema / properties / timezone / descriptionAdded value: +"IANA timezone for the point, or null unless timezone_status is resolved. Contains information from timezone-boundary-builder, which is made available under the Open Database License (ODbL) v1.0. Timezone boundaries © OpenStreetMap contributors. US legal-zone cross-check: U.S. Department of Transportation, Bureau of Transportation Statistics (public domain)." - added
Output schema / properties / timezone_artifact_versionAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / timezone_statusAdded value: +{ + "enum": [ + "resolved", + "boundary_ambiguous", + "source_conflict", + "not_covered", + "unavailable" + ], + "type": "string" +}
1 tool update
- Changed
search_places2 fields changed- changed
Input schema / properties / categories / descriptionPrevious value: -"Structured categories: food, fuel, charging_station, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation"New value: +"Structured categories: food, fuel, charging_station, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation. One of `categories` or `query` is required — a bare center (`lat`+`lon`/`center`) with neither is rejected." - changed
Input schema / properties / query / descriptionPrevious value: -"Free-text place query such as 'truck stop', 'restaurant', 'charging station'"New value: +"Free-text place query such as 'truck stop', 'restaurant', 'charging station'. One of `query` or `categories` is required — a bare center (`lat`+`lon`/`center`) with neither is rejected."
2 tool updates
- Changed
explore16 fields changed- changed
Input schema / properties / layers / descriptionPrevious value: -"Comma-separated: venue, address, street, locality, neighbourhood (default: locality)"New value: +"Comma-separated administrative layers: locality (default), neighbourhood, borough, county, region. venue, address, street and unknown names are rejected with a structured invalid_layer error — use search_places for venues. Radius policy is per layer: locality/county/region default 150 km and cap at 500 km; neighbourhood/borough default 25 km and cap at 100 km; a mixed request takes the tightest default and cap. With several layers, `size` is split evenly between them (remainder to the first) so one dense layer cannot flood the result." - changed
Input schema / properties / min_population / descriptionPrevious value: -"Minimum population filter for locality results"New value: +"Minimum population filter, applied JS-side to whichever layers are served (locality, neighbourhood, borough, county, region)." - changed
Input schema / properties / radius / descriptionPrevious value: -"Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('50km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('50km', '30mi') is also accepted for compatibility and its suffix wins. Default 150 km (93.206 mi), maximum 500 km (~310 mi). Numeric values above 500 fail input validation before the tool runs; a string form over the maximum ('600km') or an in-range number that is over the cap once read as miles (e.g. 400, or 400 with units 'miles' — 644 km) returns a structured radius_exceeds_max error instead of results."New value: +"Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('50km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('50km', '30mi') is also accepted for compatibility and its suffix wins. Per-layer policy: locality/county/region default 150 km (93.206 mi) and cap at 500 km (~310 mi); neighbourhood/borough default 25 km (15.534 mi) and cap at 100 km (~62 mi); a request naming several layers takes the tightest default and cap among them. Numeric values above 500 fail input validation before the tool runs; a string form over the maximum ('600km') or an in-range number that is over the cap once read as miles (e.g. 400, or 400 with units 'miles' — 644 km) returns a structured radius_exceeds_max error naming the governing cap instead of results." - changed
Input schema / properties / sort / descriptionPrevious value: -"Sort mode (default: combined)"New value: +"Ranking basis. Default `population` — significance (population where the source has it) with distance as the tiebreak. `distance` is nearest first; `combined` blends population against a distance decay. The basis applied is echoed in meta.ranking." - changed
Input schema / properties / units / descriptionPrevious value: -"Units for a bare numeric `radius`: miles (default) or kilometers. Accepts 'mi'/'km'/'imperial'/'metric' as aliases (any case), echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Does not supply a radius on its own (the default 150 km applies) but selects the display unit of the meta.radius / meta.units echo."New value: +"Units for a bare numeric `radius`: miles (default) or kilometers. Accepts the aliases mi, mile, imperial (miles) and km, kilometer, kilometre, kilometres, metric (kilometers), any case; echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Does not supply a radius on its own (the default is per layer — 150 km for locality/county/region, 25 km for neighbourhood/borough; tightest wins when mixed) but selects the display unit of the meta.radius / meta.units echo." - added
Output schema / properties / items / items / properties / bearingAdded value: +{ + "maximum": 359, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / items / items / properties / distanceAdded value: +{ + "type": "number" +} - added
Output schema / properties / items / items / properties / distance_unitAdded value: +{ + "enum": [ + "miles", + "kilometers" + ], + "type": "string" +} - added
Output schema / properties / meta / properties / layersAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / meta / properties / rankingAdded value: +{ + "type": "string" +} - added
Output schema / properties / meta / properties / total_candidatesAdded value: +{ + "type": "integer" +} - added
Output schema / properties / meta / properties / truncatedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / meta / properties / units / $refAdded value: +"#/properties/items/items/properties/distance_unit" - removed
Output schema / properties / meta / properties / units / enumRemoved value: -[ - "miles", - "kilometers" -] - removed
Output schema / properties / meta / properties / units / typeRemoved value: -"string" - removed
Output schema / properties / meta / requiredRemoved value: -[ - "radius_km", - "radius", - "units" -]
- Changed
search_places2 fields changed- changed
Input schema / properties / radius / descriptionPrevious value: -"Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('5km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('30mi', '5km') is also accepted and its suffix wins. Default 50 km (31.069 mi); maximum 50 km (~31 mi). Preferred over `radius_m`. Numeric values above 50 fail input validation before the tool runs; a string form over the maximum ('60km') or an in-range number that is over the cap once read as miles (e.g. 40, or 40 with units 'miles' — 64 km) is rejected with a radius error instead of results."New value: +"Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('5km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('30mi', '5km') is also accepted and its suffix wins. Default 50 km (about 31 mi); maximum 50 km (up to 31.068 mi). Preferred over `radius_m`. Numeric values above 50 fail input validation before the tool runs; a string form over the maximum ('60km') or an in-range number that is over the cap once read as miles (e.g. 40, or 40 with units 'miles' — 64 km) is rejected with a radius error instead of results." - changed
Input schema / properties / units / descriptionPrevious value: -"Units for a bare numeric `radius`: miles (default) or kilometers. Accepts 'mi'/'km'/'imperial'/'metric' as aliases (any case), echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Not valid with `radius_m` alone — radius_m is always meters, so that pair is rejected. Does not supply a radius on its own (the default 50 km applies) but selects the display unit of the `units` echo."New value: +"Units for a bare numeric `radius`: miles (default) or kilometers. Accepts the aliases mi, mile, imperial (miles) and km, kilometer, kilometre, kilometres, metric (kilometers), any case; echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Not valid with `radius_m` alone — radius_m is always meters, so that pair is rejected. Does not supply a radius on its own (the default 50 km applies) but selects the display unit of the `units` echo."
3 tool updates
- Changed
distance_matrix3 fields changed- changed
Output schema / properties / matrix / descriptionPrevious value: -"matrix[i][j] = origin i → destination j (distance + duration)"New value: +"matrix[i][j] = origin i → destination j: { distance (in the requested units), time_seconds }; both null when no route exists" - added
Output schema / properties / matrix / items / itemsAdded value: +{ + "additionalProperties": false, + "properties": { + "distance": { + "type": [ + "number", + "null" + ] + }, + "time_seconds": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "distance", + "time_seconds" + ], + "type": "object" +} - added
Output schema / properties / units / enumAdded value: +[ + "miles", + "kilometers" +]
- Changed
explore6 fields changed- added
Input schema / properties / radius / anyOfAdded value: +[ + { + "exclusiveMinimum": 0, + "maximum": 500, + "type": "number" + }, + { + "maxLength": 32, + "type": "string" + } +] - changed
Input schema / properties / radius / descriptionPrevious value: -"Search radius with unit, e.g. '50km', '30mi' (default: 150km, max: 500km / ~310mi). Larger radii return 400 INVALID_QUERY."New value: +"Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('50km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('50km', '30mi') is also accepted for compatibility and its suffix wins. Default 150 km (93.206 mi), maximum 500 km (~310 mi). Numeric values above 500 fail input validation before the tool runs; a string form over the maximum ('600km') or an in-range number that is over the cap once read as miles (e.g. 400, or 400 with units 'miles' — 644 km) returns a structured radius_exceeds_max error instead of results." - removed
Input schema / properties / radius / maxLengthRemoved value: -16 - removed
Input schema / properties / radius / typeRemoved value: -"string" - added
Input schema / properties / unitsAdded value: +{ + "description": "Units for a bare numeric `radius`: miles (default) or kilometers. Accepts 'mi'/'km'/'imperial'/'metric' as aliases (any case), echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Does not supply a radius on its own (the default 150 km applies) but selects the display unit of the meta.radius / meta.units echo.", + "enum": [ + "miles", + "kilometers" + ], + "type": "string" +} - added
Output schema / properties / metaAdded value: +{ + "additionalProperties": true, + "properties": { + "radius": { + "type": "number" + }, + "radius_km": { + "type": "number" + }, + "units": { + "enum": [ + "miles", + "kilometers" + ], + "type": "string" + } + }, + "required": [ + "radius_km", + "radius", + "units" + ], + "type": "object" +}
- Changed
search_places4 fields changed- added
Input schema / properties / radiusAdded value: +{ + "anyOf": [ + { + "exclusiveMinimum": 0, + "maximum": 50, + "type": "number" + }, + { + "maxLength": 32, + "type": "string" + } + ], + "description": "Search radius — e.g. radius: 30, units: 'miles'. Bare numbers are miles unless units is set; kilometers via units or a km suffix ('5km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('30mi', '5km') is also accepted and its suffix wins. Default 50 km (31.069 mi); maximum 50 km (~31 mi). Preferred over `radius_m`. Numeric values above 50 fail input validation before the tool runs; a string form over the maximum ('60km') or an in-range number that is over the cap once read as miles (e.g. 40, or 40 with units 'miles' — 64 km) is rejected with a radius error instead of results." +} - changed
Input schema / properties / radius_m / descriptionPrevious value: -"Search radius in meters (default 1000, max 50000)"New value: +"Search radius in meters (max 50000 — i.e. 50 km / ~31 mi; default 50 km; 0 means 'not supplied' and applies the default). Accepted alias; `radius` + `units` is preferred. Sending both is only valid when they agree. Do not pair with `units`." - added
Input schema / properties / unitsAdded value: +{ + "description": "Units for a bare numeric `radius`: miles (default) or kilometers. Accepts 'mi'/'km'/'imperial'/'metric' as aliases (any case), echoed as miles|kilometers. Ignored when `radius` already carries a unit suffix; a contradicting pair is rejected. Not valid with `radius_m` alone — radius_m is always meters, so that pair is rejected. Does not supply a radius on its own (the default 50 km applies) but selects the display unit of the `units` echo.", + "enum": [ + "miles", + "kilometers" + ], + "type": "string" +} - added
Output schema / properties / metaAdded value: +{ + "additionalProperties": true, + "properties": { + "radius_km": { + "type": "number" + }, + "units": { + "enum": [ + "miles", + "kilometers" + ], + "type": "string" + } + }, + "required": [ + "radius_km", + "units" + ], + "type": "object" +}
1 tool update
- Changed
reverse_geocode1 field changed- changed
Input schema / properties / layers / descriptionPrevious value: -"Restrict to: address, street, venue, locality"New value: +"Restrict to a comma list of: address, street, venue, neighbourhood, borough, locality, localadmin, county, macrocounty, region, macroregion, dependency, country, continent, postalcode, coarse. Admin layers resolve from the nearest indexed feature's parent hierarchy."
1 tool update
- Changed
directions1 field changed- added
Input schema / properties / include_weatherAdded value: +{ + "description": "Attach current conditions sampled along the route corridor (default: false). Post-route annotation only: weather does not change the returned path. Extra upstream lookup, opt-in only.", + "type": "boolean" +}
1 tool update
- Changed
issue_api_key2 fields changed- added
Output schema / properties / previous_keys_retire_atAdded value: +{ + "description": "ISO 8601 instant when the previous keys stop working (one hour after this mint). Present only when previous_keys_retiring > 0. Update anything still using them before this time.", + "type": "string" +} - added
Output schema / properties / previous_keys_retiringAdded value: +{ + "description": "How many previously-live keys this mint scheduled to retire. issue_api_key rotates: after the grace window the returned key is the only live key on the account. 0 means there was nothing else.", + "minimum": 0, + "type": "integer" +}
1 tool update
- Changed
directions7 fields changed- changed
Input schema / properties / include_traffic / descriptionPrevious value: -"Include live traffic conditions along route (default: true)"New value: +"Apply post-route live-traffic ETA enrichment (default: true). Traffic does not change the returned path; truck adjustments are slowdown-only." - changed
Output schema / properties / traffic_delay_seconds / descriptionPrevious value: -"Difference between effective and base duration, in seconds; zero when traffic did not change the duration."New value: +"Effective duration minus base duration, in seconds. Positive means traffic made the ETA slower, negative means it made the ETA faster, and zero means the duration was unchanged. For truck costing, general traffic evidence is slowdown-only, so this value is never negative." - changed
Output schema / properties / traffic_provenance / properties / outcome / descriptionPrevious value: -"Neutral, stable reason code for what happened to traffic evidence on this request. `TRAFFIC_DISABLED`: no traffic evidence was sought. `PROVIDER_DISABLED`: evidence was sought but the traffic backend was unreachable or unconfigured. `QUOTA_EXHAUSTED`: the traffic backend's spend allotment was exhausted. `NO_SEGMENT_MATCH`: the backend answered but no sample matched a live road segment. `INSUFFICIENT_COVERAGE`: the backend reported no sensor coverage for the sampled area. `STALE_EVIDENCE`: an adjustment was computed, but the oldest observation behind it is older than this response is willing to call current. `UPSTREAM_ERROR`: a generic or network failure prevented reading traffic evidence. `APPLIED`: an adjustment was computed and reached this response; inspect the nullable freshness and source-time fields to determine whether its observation age is known. "New value: +"Neutral, stable reason code for what happened to traffic evidence on this request. `TRAFFIC_DISABLED`: no traffic evidence was sought. `PROVIDER_DISABLED`: evidence was sought but the traffic backend was not configured. `QUOTA_EXHAUSTED`: the traffic backend's spend allotment was exhausted. `NO_SEGMENT_MATCH`: the backend answered but no sample matched a live road segment. `INSUFFICIENT_COVERAGE`: the backend reported no sensor coverage for the sampled area. `STALE_EVIDENCE`: an adjustment was computed, but the oldest observation behind it is older than this response is willing to call current. `UPSTREAM_ERROR`: a configured backend or network failure prevented reading all requested traffic evidence. `APPLIED`: an adjustment was computed and reached this response; inspect the nullable freshness and source-time fields to determine whether its observation age is known. Material failure codes take precedence over `APPLIED` when only partial evidence adjusted the duration; `duration_influenced` remains true in that case." - added
Output schema / properties / traffic_provenance / properties / retrieval_age_secondsAdded value: +{ + "description": "Age, in seconds, of the oldest retrieved traffic tile bytes used by this response. This is cache/acquisition age, not traffic-observation freshness. Null for point traffic or when tile cache metadata is unavailable.", + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / traffic_provenance / properties / retrieved_atAdded value: +{ + "description": "ISO 8601 time when the oldest traffic tile bytes used by this response were retrieved or cached. This is acquisition metadata, not the time the traffic was observed. Null for point traffic or when tile cache metadata is unavailable.", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / traffic_provenance / properties / route_coverage_pct / descriptionPrevious value: -"Percentage of the route's distance backed by a live traffic observation. Null today: traffic is sampled at a few points along the route and each answer covers a point rather than a measured length of road, so no honest percentage can be derived."New value: +"Percentage of the route's distance backed by a live traffic observation. This is a MEASURED figure, not an attributed one: it sums the length of road each traffic observation actually matched and divides by the route distance. Coverage can range from sparse observations to most of a corridor, depending on the evidence available for this request; use the returned value rather than assuming a sampling pattern. A low percentage does not mean the ETA is unreliable; it means most of the route's duration comes from the road network's own speeds rather than from live observation. Null when no live traffic observation carried a measurable length." - changed
Output schema / properties / traffic_provenance / requiredPrevious value: -[ - "mode", - "outcome", - "path_influenced", - "duration_influenced", - "source_as_of", - "route_coverage_pct", - "freshness_seconds", - "routing_release_id", - "overlay_epoch" -]New value: +[ + "mode", + "outcome", + "path_influenced", + "duration_influenced", + "source_as_of", + "route_coverage_pct", + "freshness_seconds", + "retrieved_at", + "retrieval_age_seconds", + "routing_release_id", + "overlay_epoch" +]
19 tool updates
- Changed
batch_geocode11 fields changed- changed
Input schema / properties / addresses / descriptionPrevious value: -"Array of addresses to geocode"New value: +"Array of addresses to geocode (max 50 per batch)" - added
Input schema / properties / addresses / items / maxLengthAdded value: +2000 - added
Input schema / properties / addresses / maxItemsAdded value: +50 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / items / items / properties / cross_street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / cross_street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_precisionAdded value: +{ + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_typeAdded value: +{ + "enum": [ + "corner", + "interchange" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / metricsAdded value: +{}
- Changed
directions48 fields changed- added
Input schema / properties / alternatesAdded value: +{ + "description": "Number of genuine motorized alternate routes to request (0, 1, or 2). Positive values require no via waypoints.", + "maximum": 2, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / axle_count / maximumAdded value: +20 - added
Input schema / properties / axle_count / minimumAdded value: +1 - added
Input schema / properties / axle_load / maximumAdded value: +100 - added
Input schema / properties / axle_load / minimumAdded value: +0 - added
Input schema / properties / from / maxLengthAdded value: +2000 - added
Input schema / properties / include_elevationAdded value: +{ + "description": "When true, include available route elevation fields. Point elevation may be returned for the origin and destination. Cumulative gain/loss is returned only when route-profile elevation is available.", + "type": "boolean" +} - changed
Input schema / properties / include_geometry / descriptionPrevious value: -"Route geometry shape control. \"none\" returns origin/destination Points only. \"encoded\" returns the Valhalla polyline6 string in a top-level `geometry` field plus origin/destination Points (≈95% smaller than raw GeoJSON; decode with @mapbox/polyline at precision 6). \"full\" emits decoded coordinates as a LineString in `geojson.features[0]`. When omitted (default), small routes use \"full\" and long routes auto-downgrade to \"encoded\" with a `geometry_truncated` warning."New value: +"Route geometry shape control. \"none\" returns origin/destination Points only. \"encoded\" returns an encoded polyline6 string in a top-level `geometry` field plus origin/destination Points (≈95% smaller than raw GeoJSON; decode with @mapbox/polyline at precision 6). \"full\" emits decoded coordinates as a LineString in `geojson.features[0]`. When omitted (default), small routes use \"full\" and long routes auto-downgrade to \"encoded\" with a `geometry_truncated` warning." - added
Input schema / properties / top_speed / maximumAdded value: +300 - added
Input schema / properties / top_speed / minimumAdded value: +0 - added
Input schema / properties / truck_height / maximumAdded value: +30 - added
Input schema / properties / truck_height / minimumAdded value: +0 - added
Input schema / properties / truck_length / maximumAdded value: +60 - added
Input schema / properties / truck_length / minimumAdded value: +0 - added
Input schema / properties / truck_weight / maximumAdded value: +200 - added
Input schema / properties / truck_weight / minimumAdded value: +0 - added
Input schema / properties / truck_width / maximumAdded value: +10 - added
Input schema / properties / truck_width / minimumAdded value: +0 - added
Input schema / properties / use_ferry / maximumAdded value: +1 - added
Input schema / properties / use_ferry / minimumAdded value: +0 - added
Input schema / properties / use_highways / maximumAdded value: +1 - added
Input schema / properties / use_highways / minimumAdded value: +0 - changed
Input schema / properties / vehicle_profile / descriptionPrevious value: -"Preset vehicle (10 total, see lib/truck-costing.ts:VEHICLE_PROFILE_IDS): DRY_VAN_53, FLATBED_48, FLATBED_40, STEP_DECK, TANKER, BOX_TRUCK_26, AUTO_CARRIER, SPRINTER_VAN, DOUBLE_TRAILER, OVERSIZE. Sets height/weight/length automatically. Individual params override."New value: +"Preset vehicle profile (10): DRY_VAN_53, FLATBED_48, FLATBED_40, STEP_DECK, TANKER, BOX_TRUCK_26, AUTO_CARRIER, SPRINTER_VAN, DOUBLE_TRAILER, OVERSIZE. Each sets height/weight/length/axle_count for that vehicle class in one parameter (e.g. DRY_VAN_53 = 4.11m tall, 36.3t, 22.25m long, 5 axles; OVERSIZE = 4.88m tall, 3.66m wide, 45.36t). The response echoes the applied dims in costing_options.truck. Any individual truck_height/truck_weight/etc. overrides a single field." - added
Input schema / properties / vehicle_profile / maxLengthAdded value: +64 - changed
Input schema / properties / via / descriptionPrevious value: -"Intermediate stops in order; same shape as from/to"New value: +"Intermediate stops in order; same shape as from/to. Up to 48 waypoints (max 50 total locations)." - added
Input schema / properties / via / maxItemsAdded value: +48 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / alternatesAdded value: +{ + "items": { + "additionalProperties": true, + "properties": { + "distance": { + "type": "number" + }, + "distance_units": { + "enum": [ + "miles", + "kilometers" + ], + "type": "string" + }, + "duration_seconds": { + "type": "number" + }, + "geojson": { + "$ref": "#/properties/geojson" + }, + "geometry": { + "additionalProperties": {}, + "type": "object" + }, + "legs": { + "items": { + "additionalProperties": true, + "properties": { + "distance": { + "type": "number" + }, + "duration_seconds": { + "type": "number" + }, + "leg": { + "type": "number" + }, + "maneuvers": { + "type": "number" + } + }, + "required": [ + "leg", + "distance", + "duration_seconds", + "maneuvers" + ], + "type": "object" + }, + "type": "array" + }, + "maneuvers": { + "items": { + "$ref": "#/properties/items/items" + }, + "type": "array" + } + }, + "required": [ + "distance", + "distance_units", + "duration_seconds", + "legs", + "maneuvers" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / base_arrival_localAdded value: +{ + "description": "Arrival time derived from the base duration in the destination's local time, or null when the local timezone is unavailable.", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / base_arrival_utcAdded value: +{ + "description": "Arrival time derived from the base duration, expressed as an ISO 8601 UTC timestamp.", + "type": "string" +} - added
Output schema / properties / base_duration_secondsAdded value: +{ + "description": "Route duration before any traffic-based adjustment, in seconds.", + "type": "number" +} - added
Output schema / properties / effective_arrival_localAdded value: +{ + "description": "Authoritative arrival time in the destination's local time, or null when the local timezone is unavailable.", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / effective_arrival_utcAdded value: +{ + "description": "Authoritative arrival time for this response, expressed as an ISO 8601 UTC timestamp.", + "type": "string" +} - added
Output schema / properties / effective_duration_secondsAdded value: +{ + "description": "Authoritative duration for this response, in seconds, after any applicable traffic-based adjustment.", + "type": "number" +} - added
Output schema / properties / elevation_end_ftAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_end_mAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_gain_ftAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_gain_mAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_loss_ftAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_loss_mAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_start_ftAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / elevation_start_mAdded value: +{ + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / timezone_endAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / timezone_startAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / traffic_delay_secondsAdded value: +{ + "description": "Difference between effective and base duration, in seconds; zero when traffic did not change the duration.", + "type": "number" +} - added
Output schema / properties / traffic_provenanceAdded value: +{ + "additionalProperties": false, + "properties": { + "duration_influenced": { + "description": "Whether traffic actually changed the duration returned by THIS request. False when no traffic adjustment was applied, even if traffic was requested and fetched successfully.", + "type": "boolean" + }, + "freshness_seconds": { + "description": "Age, in seconds, of the oldest traffic observation behind this response. Null when the traffic provider did not report an observation age.", + "type": [ + "number", + "null" + ] + }, + "mode": { + "description": "Which traffic-processing rung this request attempted. `none`: no traffic data was consulted. `eta_enrichment`: after the route was chosen, traffic evidence was sought only to adjust its estimated duration; the roads returned are unchanged. The attempt may fail or produce no adjustment, so inspect `outcome` and `duration_influenced` for what reached this answer. `candidate_ranking`: traffic re-ranked several candidate routes against each other. `native_live_routing`: live speeds were used to choose which roads to take. `native_predicted_routing`: as above, plus time-of-day predicted speeds for a future departure.", + "enum": [ + "none", + "eta_enrichment", + "candidate_ranking", + "native_live_routing", + "native_predicted_routing" + ], + "type": "string" + }, + "outcome": { + "description": "Neutral, stable reason code for what happened to traffic evidence on this request. `TRAFFIC_DISABLED`: no traffic evidence was sought. `PROVIDER_DISABLED`: evidence was sought but the traffic backend was unreachable or unconfigured. `QUOTA_EXHAUSTED`: the traffic backend's spend allotment was exhausted. `NO_SEGMENT_MATCH`: the backend answered but no sample matched a live road segment. `INSUFFICIENT_COVERAGE`: the backend reported no sensor coverage for the sampled area. `STALE_EVIDENCE`: an adjustment was computed, but the oldest observation behind it is older than this response is willing to call current. `UPSTREAM_ERROR`: a generic or network failure prevented reading traffic evidence. `APPLIED`: an adjustment was computed and reached this response; inspect the nullable freshness and source-time fields to determine whether its observation age is known. ", + "enum": [ + "TRAFFIC_DISABLED", + "PROVIDER_DISABLED", + "QUOTA_EXHAUSTED", + "NO_SEGMENT_MATCH", + "INSUFFICIENT_COVERAGE", + "STALE_EVIDENCE", + "UPSTREAM_ERROR", + "APPLIED" + ], + "type": "string" + }, + "overlay_epoch": { + "description": "Identifier of the live-speed overlay applied to the road network. Null today: no live-speed overlay is in use.", + "type": [ + "string", + "null" + ] + }, + "path_influenced": { + "description": "Whether traffic could have changed WHICH roads were returned. False today: the route is selected from the road network's own speeds, so traffic never changes the path — only the estimated duration.", + "type": "boolean" + }, + "route_coverage_pct": { + "description": "Percentage of the route's distance backed by a live traffic observation. Null today: traffic is sampled at a few points along the route and each answer covers a point rather than a measured length of road, so no honest percentage can be derived.", + "type": [ + "number", + "null" + ] + }, + "routing_release_id": { + "description": "Identifier of the road-network build that produced this route. Null today: the routing engine does not report one.", + "type": [ + "string", + "null" + ] + }, + "source_as_of": { + "description": "ISO 8601 time at which the traffic observations behind this response were made. Null when the traffic provider did not report an observation time.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "mode", + "outcome", + "path_influenced", + "duration_influenced", + "source_as_of", + "route_coverage_pct", + "freshness_seconds", + "routing_release_id", + "overlay_epoch" + ], + "type": "object" +} - added
Output schema / properties / traffic_routeAdded value: +{ + "additionalProperties": false, + "properties": { + "current_speed_admitted": { + "const": true, + "type": "boolean" + }, + "max_age_seconds": { + "exclusiveMinimum": 0, + "type": "integer" + }, + "observed_at": { + "type": "string" + }, + "release_id": { + "type": "string" + } + }, + "required": [ + "current_speed_admitted" + ], + "type": "object" +} - added
Output schema / requiredAdded value: +[ + "base_duration_seconds", + "effective_duration_seconds", + "traffic_delay_seconds", + "base_arrival_utc", + "base_arrival_local", + "effective_arrival_utc", + "effective_arrival_local", + "traffic_provenance" +]
- Added
distance_matrix - Changed
explore15 fields changed- changed
Input schema / properties / boundary_country / descriptionPrevious value: -"ISO country code to restrict results"New value: +"ISO country code to restrict results (alpha-2 or alpha-3)" - added
Input schema / properties / boundary_country / maxLengthAdded value: +3 - added
Input schema / properties / lat / maximumAdded value: +90 - added
Input schema / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / layers / maxLengthAdded value: +200 - added
Input schema / properties / location / maxLengthAdded value: +2000 - added
Input schema / properties / lon / maximumAdded value: +180 - added
Input schema / properties / lon / minimumAdded value: +-180 - added
Input schema / properties / min_population / maximumAdded value: +10000000000 - added
Input schema / properties / min_population / minimumAdded value: +0 - added
Input schema / properties / radius / maxLengthAdded value: +16 - added
Input schema / properties / size / maximumAdded value: +50 - added
Input schema / properties / size / minimumAdded value: +1 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / metricsAdded value: +{}
- Changed
geocode21 fields changed- changed
Input schema / properties / boundary_country / descriptionPrevious value: -"ISO country code to reduce ambiguity"New value: +"ISO country code to reduce ambiguity (alpha-2 or alpha-3)" - added
Input schema / properties / boundary_country / maxLengthAdded value: +3 - added
Input schema / properties / focus_lat / maximumAdded value: +90 - added
Input schema / properties / focus_lat / minimumAdded value: +-90 - added
Input schema / properties / focus_lon / maximumAdded value: +180 - added
Input schema / properties / focus_lon / minimumAdded value: +-180 - added
Input schema / properties / layers / maxLengthAdded value: +200 - added
Input schema / properties / query / maxLengthAdded value: +2000 - changed
Input schema / properties / size / descriptionPrevious value: -"Number of candidates to return (default 5)"New value: +"Number of candidates to return (default 5, max 40)" - added
Input schema / properties / size / maximumAdded value: +40 - added
Input schema / properties / size / minimumAdded value: +1 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / items / items / properties / cross_street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / cross_street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / items / items / properties / idAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_precisionAdded value: +{ + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_typeAdded value: +{ + "enum": [ + "corner", + "interchange" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / metricsAdded value: +{} - added
Output schema / properties / precisionAdded value: +{ + "additionalProperties": true, + "properties": { + "class": { + "type": "string" + }, + "learning_overlay": { + "additionalProperties": true, + "properties": { + "actions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "applied": { + "type": "boolean" + }, + "rule_ids": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "applied" + ], + "type": "object" + }, + "required_context": { + "items": { + "type": "string" + }, + "type": "array" + }, + "risk_flags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "class", + "risk_flags", + "required_context", + "learning_overlay" + ], + "type": "object" +}
- Added
geocode_structured - Added
geofence_contains - Changed
isochrone15 fields changed- removed
Input schema / properties / contours_km / $refRemoved value: -"#/properties/contours_minutes" - changed
Input schema / properties / contours_km / descriptionPrevious value: -"Distance bands in km. Max 4 bands per call (Valhalla limit; over returns 400)."New value: +"Distance bands in km. Max 4 bands per call (over returns 400)." - added
Input schema / properties / contours_km / itemsAdded value: +{ + "type": "number" +} - added
Input schema / properties / contours_km / maxItemsAdded value: +4 - added
Input schema / properties / contours_km / typeAdded value: +"array" - changed
Input schema / properties / contours_minutes / descriptionPrevious value: -"Time bands in minutes, e.g. [10, 20, 30]. Max 4 bands per call (Valhalla limit; over returns 400)."New value: +"Time bands in minutes, e.g. [10, 20, 30]. Max 4 bands per call (over returns 400)." - added
Input schema / properties / contours_minutes / maxItemsAdded value: +4 - added
Input schema / properties / location / maxLengthAdded value: +2000 - added
Input schema / properties / truck_height / maximumAdded value: +30 - added
Input schema / properties / truck_height / minimumAdded value: +0 - added
Input schema / properties / truck_weight / maximumAdded value: +200 - added
Input schema / properties / truck_weight / minimumAdded value: +0 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / itemsAdded value: +{ + "items": { + "additionalProperties": {}, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / metricsAdded value: +{}
- Changed
issue_api_key2 fields changed- changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - changed
Output schema / properties / api_key / descriptionPrevious value: -"One-time API key secret. Returned only on successful creation. Treat as a credential — never log, echo, or render in text channels."New value: +"One-time API key secret. Returned only on successful creation, in both structuredContent.api_key and content[0].text — save it immediately. The server stores only sha-256 of the secret; once this response is lost, the key is unrecoverable and must be rotated. Matches AWS IAM / Stripe / GitHub PAT one-time-reveal semantics."
- Added
locate - Added
map_match - Added
place_get - Changed
quota4 fields changed- changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - changed
Output schema / properties / mcp / additionalPropertiesPrevious value: -{}New value: +true - added
Output schema / properties / mcp / propertiesAdded value: +{ + "daily_limit": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "unlimited", + "type": "string" + } + ] + }, + "monthly_limit": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "unlimited", + "type": "string" + } + ] + }, + "plan": { + "type": "string" + }, + "price_per_month": { + "type": "string" + }, + "remaining_today": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "unlimited", + "type": "string" + } + ] + }, + "reset_at": { + "type": "string" + }, + "suggested_upgrade": { + "type": [ + "string", + "null" + ] + }, + "upgrade_url": { + "type": [ + "string", + "null" + ] + }, + "used_today": { + "type": "number" + } +} - added
Output schema / properties / mcp / requiredAdded value: +[ + "plan", + "used_today", + "daily_limit", + "remaining_today", + "monthly_limit", + "price_per_month" +]
- Added
resolve_intersection - Changed
reverse_geocode18 fields changed- added
Input schema / properties / lat / maximumAdded value: +90 - added
Input schema / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / layers / maxLengthAdded value: +200 - added
Input schema / properties / lon / maximumAdded value: +180 - added
Input schema / properties / lon / minimumAdded value: +-180 - changed
Input schema / properties / size / descriptionPrevious value: -"Number of nearby candidates (default 3)"New value: +"Number of nearby candidates (default 3, max 40)" - added
Input schema / properties / size / maximumAdded value: +40 - added
Input schema / properties / size / minimumAdded value: +1 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / items / items / properties / cross_street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / cross_street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / items / items / properties / idAdded value: +{ + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_precisionAdded value: +{ + "enum": [ + "geometric_crossing", + "tangent_intersection", + "centroid_cluster", + "approximate" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / intersection_typeAdded value: +{ + "enum": [ + "corner", + "interchange" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_kindAdded value: +{ + "enum": [ + "street", + "route" + ], + "type": "string" +} - added
Output schema / properties / items / items / properties / street_routeAdded value: +{ + "maxLength": 128, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / metricsAdded value: +{} - added
Output schema / properties / precisionAdded value: +{ + "additionalProperties": true, + "properties": { + "class": { + "type": "string" + }, + "learning_overlay": { + "additionalProperties": true, + "properties": { + "actions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "applied": { + "type": "boolean" + }, + "rule_ids": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "applied" + ], + "type": "object" + }, + "required_context": { + "items": { + "type": "string" + }, + "type": "array" + }, + "risk_flags": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "class", + "risk_flags", + "required_context", + "learning_overlay" + ], + "type": "object" +}
- Changed
search_places21 fields changed- changed
Input schema / properties / categories / descriptionPrevious value: -"Structured categories: food, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation"New value: +"Structured categories: food, fuel, charging_station, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation" - added
Input schema / properties / categories / items / maxLengthAdded value: +2000 - added
Input schema / properties / categories / maxItemsAdded value: +20 - added
Input schema / properties / center / properties / lat / maximumAdded value: +90 - added
Input schema / properties / center / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / center / properties / lon / maximumAdded value: +180 - added
Input schema / properties / center / properties / lon / minimumAdded value: +-180 - added
Input schema / properties / lat / maximumAdded value: +90 - added
Input schema / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / layers / maxLengthAdded value: +200 - added
Input schema / properties / limit / maximumAdded value: +50 - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / lon / maximumAdded value: +180 - added
Input schema / properties / lon / minimumAdded value: +-180 - added
Input schema / properties / query / maxLengthAdded value: +2000 - changed
Input schema / properties / radius_m / descriptionPrevious value: -"Search radius in meters (default 1000)"New value: +"Search radius in meters (default 1000, max 50000)" - added
Input schema / properties / radius_m / maximumAdded value: +50000 - added
Input schema / properties / radius_m / minimumAdded value: +0 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / items / items / properties / idAdded value: +{ + "type": "string" +} - added
Output schema / properties / metricsAdded value: +{}
- Added
trace_attributes - Changed
traffic6 fields changed- added
Input schema / properties / lat / maximumAdded value: +90 - added
Input schema / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / lon / maximumAdded value: +180 - added
Input schema / properties / lon / minimumAdded value: +-180 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / metricsAdded value: +{}
- Changed
weather10 fields changed- added
Input schema / properties / forecast_days / maximumAdded value: +16 - added
Input schema / properties / forecast_days / minimumAdded value: +1 - added
Input schema / properties / lat / maximumAdded value: +90 - added
Input schema / properties / lat / minimumAdded value: +-90 - added
Input schema / properties / location / maxLengthAdded value: +2000 - added
Input schema / properties / lon / maximumAdded value: +180 - added
Input schema / properties / lon / minimumAdded value: +-180 - changed
Output schema / additionalPropertiesPrevious value: -falseNew value: +true - added
Output schema / properties / geojsonAdded value: +{ + "additionalProperties": true, + "properties": { + "features": { + "items": { + "additionalProperties": true, + "properties": { + "geometry": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "coordinates": {}, + "geometries": { + "items": {}, + "type": "array" + }, + "type": { + "anyOf": [ + { + "enum": [ + "Point", + "LineString", + "Polygon", + "MultiPoint", + "MultiLineString", + "MultiPolygon", + "GeometryCollection" + ], + "type": "string" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": [ + "string", + "number" + ] + }, + "properties": { + "additionalProperties": {}, + "type": "object" + }, + "type": { + "const": "Feature", + "type": "string" + } + }, + "required": [ + "type", + "geometry" + ], + "type": "object" + }, + "type": "array" + }, + "type": { + "const": "FeatureCollection", + "type": "string" + } + }, + "required": [ + "type", + "features" + ], + "type": "object" +} - added
Output schema / properties / itemsAdded value: +{ + "items": { + "additionalProperties": {}, + "type": "object" + }, + "type": "array" +}
1 tool update
- Changed
directions1 field changed- added
Input schema / properties / include_geometryAdded value: +{ + "description": "Route geometry shape control. \"none\" returns origin/destination Points only. \"encoded\" returns the Valhalla polyline6 string in a top-level `geometry` field plus origin/destination Points (≈95% smaller than raw GeoJSON; decode with @mapbox/polyline at precision 6). \"full\" emits decoded coordinates as a LineString in `geojson.features[0]`. When omitted (default), small routes use \"full\" and long routes auto-downgrade to \"encoded\" with a `geometry_truncated` warning.", + "enum": [ + "none", + "encoded", + "full" + ], + "type": "string" +}
Publisher details
- Operator
- ThinAir Telematics, LLC · Publisher source
- Operator website
- https://geo.thinair.co
- Vendor relationship
- First-party · Publisher source
- Documentation
- https://geo.thinair.co/developers
- Trust center
- Not available
- Restrictions
- Free tier available without a credit card. Paid plans add higher quotas and dedicated API keys. Authentication via OAuth 2.1 (keyless, no custom OAuth app required) or Bearer API key. No admin approval or allowlisting required. Global coverage, no regional restrictions. · Publisher source
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables brand visibility monitoring across major AI platforms like ChatGPT, Claude, Gemini, and Perplexity. It allows users to track visibility scores, analyze competitor data, and receive actionable insights to improve AI-generated brand recommendations.167 npm1MIT
- AlicenseCqualityAmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs119 npm49 PyPIMIT
- AlicenseNot gradedqualityBmaintenanceEnables tracking competitor websites, changelogs, blog feeds, and pricing pages with meaningful diffs, classification, and Markdown digests via MCP tools for listing, adding, removing competitors, running checks, and retrieving digests or changes.MIT

industrylens-mcpofficial
AlicenseNot gradedqualityBmaintenanceBrowse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.