ThinAir Geo
Server Details
Location & routing intelligence for AI agents — geocoding, truck routing, traffic, weather, and place search.
- Status
- Healthy
- Uptime
- 85.9% over 56 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 19 tools
Tools are differentiated by input type, output type, and use case: forward/reverse/structured/batch geocoding, named intersection resolution, place-ID lookup, routing, matrix, isochrone, map matching, trace attributes, live traffic, weather, and admin operations are all clearly scoped. Overlaps like map_match vs trace_attributes and directions vs distance_matrix are explicitly contrasted in the descriptions.
All names are snake_case, but the set mixes verb_noun (search_places, resolve_intersection), noun_verb (batch_geocode, geofence_contains, place_get, trace_attributes), and bare noun phrases (directions, isochrone, quota, traffic, weather). The names remain readable and descriptive, but there is no single predictable naming pattern.
19 tools is slightly above the typical 3–15 range, but the server covers a broad geospatial platform spanning geocoding, routing, POI search, traffic, weather, geofencing, fleet tracing, and quota/API-key management. Most tools have a distinct capability, so the count is reasonable though heavy.
The surface covers core geospatial workflows well: forward/reverse/structured/batch geocoding, intersection and place lookup, routing, matrices, isochrones, map matching, trace attributes, road snapping, place discovery, POI search, geofence containment, traffic, weather, and admin quota/key operations. Minor gaps remain, such as route optimization/multi-stop sequencing and geofence management beyond containment testing.
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 readOnly/idempotent annotations, the description discloses key behaviors: traffic does not change the returned path, truck traffic adjustments are slowdown-only, ETAs use ISO 8601 with timezone offset in the destination's timezone, and vehicle_profile presets set dimensions in one parameter. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences with no filler: purpose first, then high-value behavioral caveats, supported modes, ETA format, and truck-profile usage. The vehicle_profile list is long but earns its place as a quick reference, and the description stays well under the point of overwhelming the agent.
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 22-parameter routing tool, the description captures the essential behavioral nuances (path-invariant traffic, slowdown-only truck traffic, ETA timezone, hazmat/dimension/toll support) while the input schema covers parameters and the output schema covers return shape. Nothing critical is missing for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline applies: the schema already documents all 22 parameters and even gives vehicle_profile examples. The description reinforces vehicle_profile usage and adds the ETA timezone note, but that is primarily output semantics rather than new parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence says 'Generate routes, ETAs, and turn-by-turn directions between locations' — a specific verb and resource with no tautology. It is clear about what the tool does, but it does not explicitly differentiate itself from sibling tools such as distance_matrix, so the differentiation is implicit rather than stated.
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 when-to-use guidance: 'Use vehicle_profile presets (10 total ...) when routing trucks' and explains that traffic is a post-route ETA enrichment that does not alter the path. It does not spell out when not to use the tool or name alternative tools for many-to-many/matrix use cases.
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. Durations do NOT include live or historical traffic — see duration_basis; use directions for a traffic-adjusted ETA between two specific points.
| 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 |
| duration_basis | No | How matrix durations were computed. `static_road_speeds` (the only value today): durations come from the road network's own speed data — posted limits and road-class defaults — never from historical or live traffic. Use `directions` for a traffic-adjusted ETA between two specific points. |
| upstream_error | No | |
| traffic_applied | No | Whether live or historical traffic influenced any matrix duration. Always false today — see `duration_basis`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only/idempotent, so the description adds non-obvious behavior: the 625-pair cap, endpoint format flexibility, and the crucial caveat that durations exclude live or historical traffic, pointing to duration_basis. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences front-load the core capability, then add usage context and the key caveat. Every sentence earns its place 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 four-parameter tool with full schema coverage and an output schema, the description covers selection, invocation constraints, and the main behavioral caveat. The reference to duration_basis is acceptable as a pointer to an output field.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters. The description adds the 625-pair cap and endpoint formats, but these are mostly derived from or redundant with the schema, so no extra parameter burden is 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?
Clearly names a concrete operation (compute road distances and travel times) on a defined resource (every origin→destination pair). It also distinguishes itself from directions by noting it is for bulk pair matrices, not a single traffic-adjusted route.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly lists use cases (fleet dispatch, nearest-depot, bulk ETA tables) and names directions as the alternative when a traffic-adjusted point-to-point ETA is needed. This gives an agent a clear decision rule rather than a vague hint.
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
Tests one or more points for containment inside a polygon you supply as GeoJSON (Polygon, MultiPolygon, or a Feature/FeatureCollection wrapping one). Pure geometry against your own shape - it does not search a place index, so use explore or search_places to find what's near a point instead. Boundary points count as contained. Up to 1000 points per call, against a polygon of up to 100 rings/parts and 1000 positions per ring; larger inputs are rejected. Runs locally with no external lookup, but still counts as one metered request like other tools, so batch points into a single call rather than looping. Errors, rather than returning false, when the polygon is structurally invalid. Returns one boolean per point, in order, plus contained_count and point_count.
| 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?
The description discloses several behaviors beyond the annotations: boundary points count as contained, structurally invalid polygons cause errors rather than false returns, and it runs locally with no external lookup yet still counts as a metered request. It also clarifies that it returns one boolean per point plus counts. No contradictions with readOnlyHint, openWorldHint, or idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured, front-loading the core purpose and then systematically covering limits, behavior, error handling, and alternatives. Each sentence adds distinct value without redundancy, and the length is justified by the richness of behavioral details needed for correct usage.
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 that an output schema exists (though not shown here) and annotations cover safety and idempotency, the description addresses all critical aspects: inputs, limits, error behavior, batching, local execution, and alternative tools. Nothing an agent needs to invoke this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes both parameters with constraints (maxItems for points, GeoJSON types for polygon). The description adds context about limits and batching but does not introduce new parameter-specific semantics beyond what the schema provides. With 100% schema description coverage, a baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('tests') and resource ('points for containment inside a polygon you supply as GeoJSON'), and explicitly distinguishes itself from sibling tools by noting it does not search a place index and directing users to explore or search_places for proximity queries. This makes the tool's purpose unmistakable and differentiates it from similar tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool (testing containment against a user-supplied polygon) and when not to (finding places near a point), naming the alternative tools. It also provides operational guidance on batching points into a single call to avoid repeated metered requests, which is actionable and prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
isochroneARead-onlyIdempotentInspect
Computes reachability polygons: the area reachable from an origin within given travel-time or travel-distance bands. Use for service coverage, dispatch range, territory design, and 'how far can I get in X minutes' questions; use directions or distance_matrix for a route or distance between specific points instead. Pass multiple bands in one call (contours_minutes:[10,20,30]) for nested polygons in one response, up to 4 bands, defaulting to 15/30/60-minute driving bands if none given. location accepts an address string or 'lat,lon'. costing selects the travel profile (auto default, or truck/bicycle/pedestrian/motorcycle). Read-only and cached. Returns a GeoJSON FeatureCollection of nested polygon contours, one per band.
| 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. The description adds 'Read-only and cached' (caching is not in annotations) and details the default band behavior (15/30/60-minute driving) and output format (GeoJSON FeatureCollection of nested polygon contours). This goes well beyond the structured metadata, providing rich behavioral context without contradicting any annotation.
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 efficiently structured: it opens with the core function, then use cases, then usage specifics, and finally output format. Every sentence contributes essential information with no filler. The length is justified by the tool's complexity, and the key points are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for an agent to call the tool correctly. It covers the purpose, usage context, parameter behavior, defaults, and output format. With an output schema present, the description need not detail return structures beyond the high-level summary it provides. Nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds meaningful usage context beyond the schema: it explains that location accepts an address or 'lat,lon' (schema already says this, but the description reinforces it), and it clarifies how to pass multiple bands with an example and the default. It also highlights that costing selects the travel profile with the default auto. These additions slightly elevate the value beyond the schema, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise definition: 'Computes reachability polygons: the area reachable from an origin within given travel-time or travel-distance bands.' It immediately distinguishes itself from sibling tools by explicitly naming directions and distance_matrix for point-to-point routes. This is a specific verb+resource that leaves no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage guidance is explicit: it lists concrete use cases (service coverage, dispatch range, territory design) and tells the agent to use directions or distance_matrix instead for routes between specific points. It also explains how to pass multiple bands (contours_minutes:[10,20,30]) and the default bands, giving clear when-to-use and how-to-use instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
issue_api_keyRead-onlyIdempotentInspect
Get the link to create a ThinAir GEO (geocoding/routing) API key. Returns console_url (the signed-in ThinAir Geo console) and instructions; it does NOT return a key and does not create, rotate or revoke any key. The owner signs in, creates the key there and sees it once in their own browser, then sends it as an Authorization: Bearer header. Existing keys keep working. Counts as 1 query against your daily quota. NOTE: keys created there work ONLY against ThinAir Geo — they do NOT authenticate against ThinAir Data, which issues its own ta_data_* keys from its own identically-named tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| plan | No | |
| error | No | |
| status | Yes | |
| console_url | No | Link to the signed-in ThinAir Geo console, where the owner creates an API key and sees it once in their own browser. This tool never returns a key. |
| instructions | No | How to create the key in the console and send it (Authorization: Bearer). Surface to the user as written. |
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. Read road_status, not matched alone: matched — a road was found and road is filled; no_road_nearby — a real answer: no routable road is near the point for this travel profile; unavailable — the road lookup could not be answered right now, so matched:false / road:null say nothing about the point, retryable is true, and the timezone and any requested elevation are still looked up separately (see timezone_status and warnings). 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 | |
| retryable | No | Present and true only when `road_status` is `unavailable`: the same call may succeed shortly. |
| elevation_m | No | |
| road_status | No | Why `road` is what it is. `matched`: a routable road was found. `no_road_nearby`: the lookup answered and found no routable road near the point for this travel profile. `unavailable`: the road lookup could not be answered right now; this says nothing about the point, `retryable` is true, and the timezone and any requested elevation are still looked up separately. |
| 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?
Annotations already cover read-only/idempotent/open-world, yet the description adds substantial behavior: the three-valued road_status contract, the warning that 'unavailable' makes matched:false meaningless about the point, that retryable is set, and that timezone/elevation are still looked up independently. This is exactly the beyond-annotations context the bar is meant to reward.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, then usage, then a well-structured status-contract paragraph. It is long and mildly redundant, restating the elevation/grade_pct caveat that the schema already carries, but nearly every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate return values, yet it fully explains the road_status state machine, the nullability caveats, and retry semantics — the precise gaps an agent would otherwise misread. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so lat/lon/units/costing/include_elevation are already documented; baseline 3 applies. The description re-explains include_elevation and the forward-compatible grade_pct but adds no new syntax or constraints (units auto-detection and costing profiles live only in 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?
Opens with a specific verb+resource: 'Snap one coordinate to the road network and return the matched road's context.' Enumerates the returned fields (name, road class, speed limit, bearing, side of street, truck legality, flags, timezone), which separates it cleanly from siblings like map_match, reverse_geocode, and trace_attributes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit use contexts — fleet/telematics snapping, geofence edge checks, enriching a GPS fix — and frames the question it answers. However, it never names an alternative sibling (e.g., reverse_geocode or map_match) or states when-not to use it, so routing between near-neighbors 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.
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. matched: true only means a route was returned — gate on match_status: full when every input point was matched or interpolated onto the road network and the match is one continuous section, none when no point was, otherwise partial. coverage gives the per-point counts, unmatched_ranges (0-based input indexes that did not match) and route_sections (above 1, the geometry, distance and time cover only the first section — split the trace there). match_status is null, with coverage.unavailable_reason, when the per-point check could not be completed. Sparsely-reported traces (consecutive fixes farther apart than the default breakage distance — e.g. fleet units reporting every several minutes on a highway) can split into multiple sections; increase breakage_distance_m to keep them as one. Total matched distance is limited to 200 km per call — split longer sparse traces by distance, not only by the 100-point cap. 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. | |
| breakage_distance_m | No | Maximum gap, in meters, between consecutive fixes before the trace is split into separate sections (100–20000). Increase for sparsely-reported GPS, such as fleet units reporting every several minutes on a highway. Optional — omitted uses the default. |
Output Schema
| Name | Required | Description |
|---|---|---|
| legs | Yes | |
| meta | No | |
| costing | Yes | |
| geojson | No | |
| matched | Yes | True when a route was returned for the trace. It does NOT mean the whole trace matched — use `match_status`. |
| coverage | No | Per-point coverage of the trace from the matcher's own per-point status — independent of the distance-based `confidence`. Every key is always present. |
| geometry | No | |
| confidence | Yes | 0–1: fraction of input GPS points within the snap tolerance of the matched route. A distance heuristic: it ignores point order and which parallel roadway was matched. For the matcher's own per-point result use `match_status` / `coverage`. |
| road_names | Yes | |
| distance_km | Yes | |
| match_status | No | Whole-trace match status from the matcher's own per-point results. `full`: every input point was matched or interpolated onto the road network AND the match is one continuous section. `none`: no input point was matched or interpolated. `partial`: anything else — some points unmatched, or the match broke into more than one section. null when the per-point check could not be completed; `coverage.unavailable_reason` says why. Gate on this field, not on `matched`. |
| costing_options | No | |
| vehicle_profile | No | |
| duration_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and idempotentHint=true, and the description does not contradict them — map matching is a pure read operation. Beyond the annotations, the description discloses substantial behavior: the matched:true vs match_status distinction (full/none/partial), coverage counts, unmatched_ranges, route_sections semantics (above 1, only first section's geometry/distance/time returned), the 200 km matched-distance cap, sparse-trace splitting behavior, and the caveat that road_names derive only from maneuver points. This is rich context well beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long and information-dense, but every sentence carries real behavioral or routing content — return semantics, edge cases, limits, alternatives. It is front-loaded with the core purpose and output before diving into nuance. Given the subtlety of match_status and route_sections, the length is earned; it's thorough rather than bloated.
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 high-complexity tool with subtle return semantics, the description covers purpose, all critical edge cases (sparse traces, 200 km limit, per-point matching failure via unavailable_reason), return-value interpretation, and sibling routing. An output schema exists for structured returns, and the description still clarifies the ambiguous parts (what matched:true really means, what route_sections>1 implies). Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value on top: it explains the behavioral consequence of breakage_distance_m (sparse traces split into sections; increase to keep them one), ties the 200 km limit to distance-based splitting of long traces, and clarifies costing/vehicle_profile interplay via the truck preset note. It doesn't deeply re-explain every param since the schema already does, but the added behavioral context pushes it above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('snaps raw GPS breadcrumbs to the road network') and enumerates the output (matched geometry, distance, time, road names, match confidence). It explicitly distinguishes itself from siblings — 'For planning a route between places, use directions instead' and 'use trace_attributes' for per-segment names — so an agent can select it correctly without opening other 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?
Provides explicit use cases ('Use for fleet trace cleanup, mileage from GPS logs, and reconstructing routes from telemetry') plus clear exclusions with named alternatives ('For planning a route between places, use directions instead'; 'for the name of every segment actually travelled, use trace_attributes'). This is exactly the when/when-not guidance the rubric rewards.
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
Converts a coordinate pair into the nearest addresses, streets, venues, or administrative places, ordered by proximity. Use when starting from GPS or a map position; for text-to-coordinates use geocode, and for a point's road-network context (name, class, speed limit, legality) use locate instead. Read-only and cached. Near the poles (|lat| >= 85 degrees) the index is too sparse for a real nearest match, so this returns no results rather than a distant wrong guess. Returns up to size candidates (default 5, max 40); layers restricts the type returned (address, street, venue, neighbourhood, locality, county, region, country, postalcode, and more). Each result carries a confidence score, layer, label, and coordinates, same shape as geocode.
| Name | Required | Description | Default |
|---|---|---|---|
| lat | Yes | Latitude | |
| lon | Yes | Longitude | |
| size | No | Number of nearby candidates (default 5, 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 cover read-only, open-world, and idempotent behavior, but the description adds caching and the important pole edge case where it returns no results rather than a distant wrong guess. It also explains that results are bounded by size and carry confidence scores, labels, and coordinates.
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 purpose, then routing alternatives, then behavioral caveats, so the most important information comes first. It is information-dense and earns most of its length, though 'Read-only and cached' partly repeats annotations and the layers enumeration is somewhat verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers purpose, alternatives, edge cases, return cardinality, and layer semantics, while the output schema handles result shape. With rich annotations and full schema coverage, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents lat/lon bounds, size default/max, and the layers list in more detail. The description repeats the size default/max and gives layer examples, but adds no new syntax or semantic detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: converts a coordinate pair into nearest addresses, streets, venues, or administrative places, ordered by proximity. This clearly distinguishes the tool from siblings like geocode and locate, so an agent can identify it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use it when starting from GPS or a map position, and names the alternatives: geocode for text-to-coordinates and locate for road-network context. The when/when-not routing is unambiguous.
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. Sparsely-reported traces (consecutive fixes farther apart than the default breakage distance — e.g. fleet units reporting every several minutes on a highway) can split into multiple sections; increase breakage_distance_m to keep them as one. Total matched distance is limited to 200 km per call — split longer sparse traces by distance, not only by the 100-point cap. 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. | |
| breakage_distance_m | No | Maximum gap, in meters, between consecutive fixes before the trace is split into separate sections (100–20000). Increase for sparsely-reported GPS, such as fleet units reporting every several minutes on a highway. Optional — omitted uses the default. |
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, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds valuable behavioral context: sparse traces can split into multiple sections, and total matched distance is capped at 200 km. This goes beyond the structured hints, though it stops short of describing output schema details (which are separately provided).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet dense: three sentences carry purpose, edge-case handling, and alternatives. The key purpose is front-loaded, and the usage note is placed at the end. It earns its length, though the split/limit guidance could be tightened slightly.
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 description enumerates returned attributes), the description covers all operational needs: input range (2–100 points), spatial limits, splitting behavior, and use-case fit. It leaves no critical gap for an agent to decide when and how to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning for breakage_distance_m (explains why to increase it for sparse GPS) and vehicle_profile (implies costing=truck), and clarifies the shape parameter's optional time field. These enrich the schema without redundancy.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear, specific verb–resource pairing ('return road/network attributes for matched traces') and enumerates the exact attributes returned (road names, classes, speed limits, surfaces, truck-route flags, segment lengths, confidence score). It explicitly distinguishes itself from the sibling map_match ('For just the matched route line, use map_match'), so an agent can differentiate without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states explicit use cases ('audit what roads a vehicle actually used – speed-limit compliance, truck-route adherence, surface checks') and explicitly names the alternative for route geometry. It also gives operational guidance on when to adjust breakage_distance_m and how to handle the 200 km limit, which is actionable context.
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
issue_api_key9 fields changed- removed
Output schema / properties / api_keyRemoved value: -{ - "description": "One-time API key secret. Returned only on successful creation, in both structuredContent.api_key and content[0].text. Save this key now. It is shown once. ThinAir authenticates using a hash of the key. Matches AWS IAM / Stripe / GitHub PAT one-time-reveal semantics.", - "type": "string" -} - added
Output schema / properties / console_urlAdded value: +{ + "description": "Link to the signed-in ThinAir Geo console, where the owner creates an API key and sees it once in their own browser. This tool never returns a key.", + "type": "string" +} - removed
Output schema / properties / credential_returned_onceRemoved value: -{ - "type": "boolean" -} - added
Output schema / properties / instructionsAdded value: +{ + "description": "How to create the key in the console and send it (Authorization: Bearer). Surface to the user as written.", + "type": "string" +} - removed
Output schema / properties / key_idRemoved value: -{ - "description": "Non-secret fingerprint of the issued key. Safe to log and surface in UI.", - "type": "string" -} - removed
Output schema / properties / previous_keys_retire_atRemoved 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" -} - removed
Output schema / properties / previous_keys_retiringRemoved 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" -} - removed
Output schema / properties / usageRemoved value: -{ - "type": "string" -} - removed
Output schema / properties / userRemoved value: -{ - "type": "string" -}
1 tool update
- Changed
issue_api_key1 field changed- changed
Output schema / properties / api_key / descriptionPrevious 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."New value: +"One-time API key secret. Returned only on successful creation, in both structuredContent.api_key and content[0].text. Save this key now. It is shown once. ThinAir authenticates using a hash of the key. Matches AWS IAM / Stripe / GitHub PAT one-time-reveal semantics."
1 tool update
- Changed
locate4 fields changed- changed
Output schema / properties / meta / additionalPropertiesPrevious value: -{}New value: +true - added
Output schema / properties / meta / propertiesAdded value: +{ + "degraded": { + "description": "Present and true only when `road_status` is `unavailable`: the road part of the answer is missing; the rest is real.", + "type": "boolean" + } +} - added
Output schema / properties / retryableAdded value: +{ + "description": "Present and true only when `road_status` is `unavailable`: the same call may succeed shortly.", + "type": "boolean" +} - added
Output schema / properties / road_statusAdded value: +{ + "description": "Why `road` is what it is. `matched`: a routable road was found. `no_road_nearby`: the lookup answered and found no routable road near the point for this travel profile. `unavailable`: the road lookup could not be answered right now; this says nothing about the point, `retryable` is true, and the timezone and any requested elevation are still looked up separately.", + "enum": [ + "matched", + "no_road_nearby", + "unavailable" + ], + "type": "string" +}
1 tool update
- Changed
reverse_geocode1 field changed- changed
Input schema / properties / size / descriptionPrevious value: -"Number of nearby candidates (default 3, max 40)"New value: +"Number of nearby candidates (default 5, max 40)"
1 tool update
- Changed
directions5 fields changed- changed
Output schema / properties / traffic_provenance / properties / freshness_seconds / descriptionPrevious value: -"Age, in seconds, of the oldest traffic observation behind this response. Null when the traffic provider did not report an observation age."New value: +"DEPRECATED since 2026-09-24, always null — same reason as `source_as_of`. See `retrieval_age_seconds` for the acquisition age ThinAir CAN report honestly. Will be removed in /v2." - 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 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."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 evidence behind it was fetched more than 30 minutes ago because the provider could not refresh it. `UPSTREAM_ERROR`: a configured backend or network failure prevented reading all requested traffic evidence. `APPLIED`: an adjustment was computed and reached this response; inspect `retrieved_at` / `retrieval_age_seconds` to see how old the evidence behind it is (acquisition age — this traffic source reports no observation time, see those fields' own descriptions). Material failure codes take precedence over `APPLIED` when only partial evidence adjusted the duration; `duration_influenced` remains true in that case." - changed
Output schema / properties / traffic_provenance / properties / retrieval_age_seconds / descriptionPrevious value: -"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."New value: +"Age, in seconds, of `retrieved_at` — how long ago ThinAir fetched the traffic evidence behind this response (point or tile). This is acquisition/cache age, not traffic-observation freshness. Null under the same condition as `retrieved_at`." - changed
Output schema / properties / traffic_provenance / properties / retrieved_at / descriptionPrevious value: -"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."New value: +"ISO 8601 time when ThinAir fetched the traffic evidence behind this response (point or tile). This is acquisition metadata, not the time the traffic was observed — the traffic source reports no observation time (see `source_as_of`). Null when no consulted sample's acquisition time was determinable." - changed
Output schema / properties / traffic_provenance / properties / source_as_of / descriptionPrevious value: -"ISO 8601 time at which the traffic observations behind this response were made. Null when the traffic provider did not report an observation time."New value: +"DEPRECATED since 2026-09-24, always null. The traffic source provides no observation timestamp, so this field can never be filled honestly. See `retrieved_at` for when ThinAir fetched the traffic evidence (not when it was observed). Will be removed in /v2."
2 tool updates
- Changed
map_match4 fields changed- added
Input schema / properties / breakage_distance_mAdded value: +{ + "description": "Maximum gap, in meters, between consecutive fixes before the trace is split into separate sections (100–20000). Increase for sparsely-reported GPS, such as fleet units reporting every several minutes on a highway. Optional — omitted uses the default.", + "maximum": 20000, + "minimum": 100, + "type": "integer" +} - changed
Output schema / properties / meta / additionalPropertiesPrevious value: -{}New value: +true - added
Output schema / properties / meta / propertiesAdded value: +{ + "breakage_distance_m": { + "description": "Echoes the breakage_distance_m the caller requested, for confirmation — present only when the caller set it. This is the value SENT to the matcher, not a claim about what it did with it.", + "type": "integer" + }, + "point_count": { + "type": "integer" + }, + "upstream_ms": { + "type": "number" + } +} - added
Output schema / properties / meta / requiredAdded value: +[ + "upstream_ms", + "point_count" +]
- Changed
trace_attributes4 fields changed- added
Input schema / properties / breakage_distance_mAdded value: +{ + "description": "Maximum gap, in meters, between consecutive fixes before the trace is split into separate sections (100–20000). Increase for sparsely-reported GPS, such as fleet units reporting every several minutes on a highway. Optional — omitted uses the default.", + "maximum": 20000, + "minimum": 100, + "type": "integer" +} - changed
Output schema / properties / meta / additionalPropertiesPrevious value: -{}New value: +true - added
Output schema / properties / meta / propertiesAdded value: +{ + "breakage_distance_m": { + "description": "Echoes the breakage_distance_m the caller requested, for confirmation — present only when the caller set it. This is the value SENT to the matcher, not a claim about what it did with it.", + "type": "integer" + }, + "point_count": { + "type": "integer" + }, + "upstream_ms": { + "type": "number" + } +} - added
Output schema / properties / meta / requiredAdded value: +[ + "upstream_ms", + "point_count" +]
2 tool updates
- Changed
distance_matrix2 fields changed- added
Output schema / properties / duration_basisAdded value: +{ + "const": "static_road_speeds", + "description": "How matrix durations were computed. `static_road_speeds` (the only value today): durations come from the road network's own speed data — posted limits and road-class defaults — never from historical or live traffic. Use `directions` for a traffic-adjusted ETA between two specific points.", + "type": "string" +} - added
Output schema / properties / traffic_appliedAdded value: +{ + "const": false, + "description": "Whether live or historical traffic influenced any matrix duration. Always false today — see `duration_basis`.", + "type": "boolean" +}
- Changed
map_match4 fields changed- changed
Output schema / properties / confidence / descriptionPrevious value: -"0–1: fraction of input GPS points within the snap tolerance of the matched route"New value: +"0–1: fraction of input GPS points within the snap tolerance of the matched route. A distance heuristic: it ignores point order and which parallel roadway was matched. For the matcher's own per-point result use `match_status` / `coverage`." - added
Output schema / properties / coverageAdded value: +{ + "additionalProperties": true, + "description": "Per-point coverage of the trace from the matcher's own per-point status — independent of the distance-based `confidence`. Every key is always present.", + "properties": { + "interpolated_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Input points the matcher placed on the road network by interpolating between matched neighbours; counted as covered. null when unavailable." + }, + "matched_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Input points the matcher placed on the road network directly. null when unavailable." + }, + "point_count": { + "description": "Number of input GPS points", + "type": "integer" + }, + "ratio": { + "description": "0–1: (matched_count + interpolated_count) / point_count, rounded down to 3 decimals so a partial trace never reads 1. null when unavailable.", + "type": [ + "number", + "null" + ] + }, + "route_sections": { + "description": "Number of disjoint sections the match broke into (1 = continuous). When greater than 1, the returned geometry, distance and duration cover only the FIRST section — split the trace at the break and match the parts separately.", + "type": "integer" + }, + "unavailable_reason": { + "anyOf": [ + { + "enum": [ + "upstream_error", + "timeout", + "no_point_status", + "point_count_mismatch", + "unknown_point_type" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why the per-point counts and `match_status` are null: `upstream_error` (the per-point check failed), `timeout` (it did not answer in time), `no_point_status` (it answered without per-point results), `point_count_mismatch` (its results did not line up one-to-one with the input points), `unknown_point_type` (it reported a status this API does not recognise). null when coverage is available." + }, + "unmatched_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Input points the matcher could not place on the road network. null when unavailable." + }, + "unmatched_ranges": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "end_index": { + "description": "0-based index of the last unmatched input point in this run (inclusive)", + "type": "integer" + }, + "point_count": { + "description": "Number of input points in this run", + "type": "integer" + }, + "start_index": { + "description": "0-based index of the first unmatched input point in this run", + "type": "integer" + } + }, + "required": [ + "start_index", + "end_index", + "point_count" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Contiguous runs of unmatched input points, as 0-based inclusive index ranges into `shape`, in trace order. Empty when every point was covered; null when unavailable." + } + }, + "required": [ + "point_count", + "matched_count", + "interpolated_count", + "unmatched_count", + "ratio", + "unmatched_ranges", + "route_sections", + "unavailable_reason" + ], + "type": "object" +} - added
Output schema / properties / match_statusAdded value: +{ + "anyOf": [ + { + "enum": [ + "full", + "partial", + "none" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Whole-trace match status from the matcher's own per-point results. `full`: every input point was matched or interpolated onto the road network AND the match is one continuous section. `none`: no input point was matched or interpolated. `partial`: anything else — some points unmatched, or the match broke into more than one section. null when the per-point check could not be completed; `coverage.unavailable_reason` says why. Gate on this field, not on `matched`." +} - added
Output schema / properties / matched / descriptionAdded value: +"True when a route was returned for the trace. It does NOT mean the whole trace matched — use `match_status`."
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."
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.1624 npm1MIT
- AlicenseCqualityBmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs117 npmMIT
- AlicenseAqualityCmaintenanceRevnuvo Company Intelligence tells AI agents what changed at a company, with evidence. It observes company websites, technologies, and DNS over time and returns timestamped, confidence-aware changes, signals, and monitoring.9MIT

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.