Skip to main content
Glama

search_along_route

Find places (POIs) along a route with the REAL extra travel time of stopping at each, never a straight-line guess. Provide origin + destination (a route is computed) or an existing route's geometry_polyline6, plus a free-text query ("coffee", "EV charger", "truck stop") and max_detour_minutes (default 10). For a category intent ("fuel", "EV charger", "coffee") pass category instead of relying on words alone: it takes the same vocabulary as nearby_places (lowercased OSM tag values such as "fuel", "cafe", "charging_station", "parking", "pharmacy"), and common colloquial phrases are normalised server-side ("petrol station" and "gas station" to fuel, "coffee" to cafe, "EV charger" to charging_station). query alone also promotes a pure category phrase to the same browse, so "fuel" finds fuel stations rather than places whose NAME starts "Ful"; anything else stays free-text name matching. When a browse ran, the response echoes the tokens used in matched_categories. Candidates near the route corridor are priced through the routing engine with your costing: detour = (origin→place) + (place→destination) − (origin→destination). Costing "auto", "truck" (with a truck profile the detours respect dimensional/ADR restrictions), "bicycle", "pedestrian" or "motor_scooter". Returns results sorted by detour with detour_minutes, detour_km, along_route_position (0-1) and off_route_m; at most 25 candidates are priced per call (candidate_cap).

Input Schema

NameRequiredDescriptionDefault
queryYesFree-text POI query, e.g. "coffee", "EV charger", "truck stop".
truckNoTruck profile (dimensions + ADR declaration). Requires costing "truck"; the detours then respect dimensional/ADR restrictions.
originNoRoute origin (with `destination`, when no geometry is given).
costingNoCosting model for the route and detour matrix: "auto" (default), "truck", "bicycle", "pedestrian" or "motor_scooter".auto
categoryNoExplicit place category ("fuel", "cafe", "charging_station", same vocabulary as nearby_places). Colloquial phrases are normalised server-side; prefer this over query for category intents.
destinationNoRoute destination.
max_resultsNoMaximum results (default 5, at most 25).
geometry_polyline6NoAn existing route geometry as an encoded polyline6 (the `route` tool's `geometry_polyline6`). Provide either this or `origin` + `destination`, not both.
max_detour_minutesNoLargest acceptable detour in minutes (default 10, at most 120).

Output Schema

NameRequiredDescriptionDefault
queryYesThe query as interpreted.
costingYesThe costing the detours were priced with.
resultsYesPlaces within the detour budget, cheapest detour first.
candidate_capYesThe matrix fan-out cap in force.
route_length_mYesLength of the route geometry in metres.
fuel_attributionNoAttribution string for fuel-price data sources, present only when at least one returned result carries `fuel_prices` (gateway-preferred mode with `SN_FUEL_PRICES` configured; see [`AlongRouteHit`]).
route_distance_mNoDirect origin→destination distance in metres.
route_duration_sNoDirect origin→destination travel time in seconds (same estimator as the detour legs), when routable.
candidates_costedYesCandidates actually priced through the engine (fan-out is capped at `candidate_cap` nearest-to-route).
matched_categoriesNoThe normalised category tokens the candidates were browsed by, present only when a category browse actually ran (an explicit `category`, or a query the server promoted to one). Absent means free-text name matching answered the call, so a caller can tell how its words were understood rather than inferring it from the results.
max_detour_minutesYesThe detour budget applied, minutes.
candidates_consideredYesCandidates found near the corridor before pricing.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • changedInput schema / $defs / TruckSpec / properties / tunnel_code / description
      Previous value: -"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(—)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."New value: +"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."
    • changedInput schema / properties / category / description
      Previous value: -"Explicit place category (\"fuel\", \"cafe\", \"charging_station\" — same\nvocabulary as nearby_places). Colloquial phrases are normalised\nserver-side; prefer this over query for category intents."New value: +"Explicit place category (\"fuel\", \"cafe\", \"charging_station\", same\nvocabulary as nearby_places). Colloquial phrases are normalised\nserver-side; prefer this over query for category intents."
    • changedOutput schema / $defs / AlongRouteHit / properties / fuel_prices / description
      Previous value: -"Live pump prices for this fuel/petrol station, keyed by fuel code\n(e.g. \"diesel\", \"petrol_95\"), each `{value, currency, updated_at}`.\nOnly ever present when the server is gateway-preferred AND the\ndeployment configured `SN_FUEL_PRICES` AND this result matched a\nstation within range — never fabricated. Direct-backend fallback\nnever sets this (see the gap this closes in the PR description)."New value: +"Live pump prices for this fuel/petrol station, keyed by fuel code\n(e.g. \"diesel\", \"petrol_95\"), each `{value, currency, updated_at}`.\nOnly ever present when the server is gateway-preferred AND the\ndeployment configured `SN_FUEL_PRICES` AND this result matched a\nstation within range, never fabricated. Direct-backend fallback\nnever sets this (see the gap this closes in the PR description)."
    • changedOutput schema / $defs / GeocodeHit / properties / match / description
      Previous value: -"How far this hit can be trusted to be the place that was asked\nfor — see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on."New value: +"How far this hit can be trusted to be the place that was asked\nfor, see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on."
    • changedOutput schema / $defs / GeocodeMatch / description
      Previous value: -"How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n  answer does not carry the address that was asked for — an `unmatched`\n  postcode means the result has no postcode at all, `inferred` means it\n  has a different one. Neither is a match. Say so rather than presenting\n  the hit as the address, and reach for `verify_places` when the address\n  came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n  and the runner-up, which is exactly when to show the alternatives\n  instead of picking one for the user."New value: +"How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n  answer does not carry the address that was asked for, an `unmatched`\n  postcode means the result has no postcode at all, `inferred` means it\n  has a different one. Neither is a match. Say so rather than presenting\n  the hit as the address, and reach for `verify_places` when the address\n  came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n  and the runner-up, which is exactly when to show the alternatives\n  instead of picking one for the user."
    • changedOutput schema / $defs / GeocodeMatch / properties / score_gap / description
      Previous value: -"The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score — so a `0` is \"no signal\", not\n\"a tie\"."New value: +"The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score, so a `0` is \"no signal\", not\n\"a tie\"."
    • changedOutput schema / $defs / GeocodeMatchComponents / description
      Previous value: -"Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\" — the result's own field carries the value asked for (case-\n  and accent-insensitive, and by containment, so `city: \"London\"`\n  matches \"City of London\").\n* \"inferred\" — the result carries a value for that component, but not\n  the one asked for. It reached the page through ranking, as when a\n  street is found by its transliterated name and displayed under its\n  canonical one.\n* \"unmatched\" — the result carries no value for that component at all."New value: +"Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\", the result's own field carries the value asked for (case-\n  and accent-insensitive, and by containment, so `city: \"London\"`\n  matches \"City of London\").\n* \"inferred\", the result carries a value for that component, but not\n  the one asked for. It reached the page through ranking, as when a\n  street is found by its transliterated name and displayed under its\n  canonical one.\n* \"unmatched\", the result carries no value for that component at all."
  2. Changed6 schema fields changed
    • addedInput schema / $defs / LatLon / anyOf
      Added value: +[
      +  {
      +    "properties": {
      +      "lat": {
      +        "description": "Latitude in decimal degrees (−90 to 90).",
      +        "format": "double",
      +        "type": "number"
      +      },
      +      "lon": {
      +        "description": "Longitude in decimal degrees (−180 to 180).",
      +        "format": "double",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "lat",
      +      "lon"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "description": "GeoJSON position [lon, lat]: longitude FIRST.",
      +    "items": {
      +      "format": "double",
      +      "type": "number"
      +    },
      +    "maxItems": 2,
      +    "minItems": 2,
      +    "type": "array"
      +  }
      +]
    • changedInput schema / $defs / LatLon / description
      Previous value: -"A WGS84 coordinate pair in decimal degrees."New value: +"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server."
    • removedInput schema / $defs / LatLon / properties
      Removed value: -{
      -  "lat": {
      -    "description": "Latitude in decimal degrees (−90 to 90).",
      -    "format": "double",
      -    "type": "number"
      -  },
      -  "lon": {
      -    "description": "Longitude in decimal degrees (−180 to 180).",
      -    "format": "double",
      -    "type": "number"
      -  }
      -}
    • removedInput schema / $defs / LatLon / required
      Removed value: -[
      -  "lat",
      -  "lon"
      -]
    • removedInput schema / $defs / LatLon / type
      Removed value: -"object"
    • addedInput schema / additionalProperties
      Added value: +false
  3. Changed3 schema fields changed
    • addedOutput schema / $defs / GeocodeHit / properties / match
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/$defs/GeocodeMatch"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "How far this hit can be trusted to be the place that was asked\nfor — see [`GeocodeMatch`]. Present whenever the MapMap gateway\nanswered; absent on a deployment falling back to the direct Photon\ngeocoder, and absent on the gateway's own fast paths (a pasted\ncoordinate pair, a bare UK outward code, a category browse), which\nanswer without a ranking to report on."
      +}
    • addedOutput schema / $defs / GeocodeMatch
      Added value: +{
      +  "description": "How well one geocoding result answers what was actually asked.\n\nGeocoding's real failure mode is not \"no answer\" but a confident answer\nto a different question: a plausible row on the wrong street, with\nnothing in the response to say so. This object is that missing say-so,\nand an agent should read it before acting on an address.\n\nHow to read it:\n\n* Any component `unmatched` or `inferred` on the TOP hit means the\n  answer does not carry the address that was asked for — an `unmatched`\n  postcode means the result has no postcode at all, `inferred` means it\n  has a different one. Neither is a match. Say so rather than presenting\n  the hit as the address, and reach for `verify_places` when the address\n  came from a model or a user and needs checking rather than using.\n* A small `score_gap` means the ranking barely chose between this hit\n  and the runner-up, which is exactly when to show the alternatives\n  instead of picking one for the user.",
      +  "properties": {
      +    "components": {
      +      "$ref": "#/$defs/GeocodeMatchComponents",
      +      "description": "Per-component verdict on this hit: one entry for each structured\ncomponent supplied, and empty when the query was free text only."
      +    },
      +    "score_gap": {
      +      "description": "The top result's score minus the runner-up's, rounded to 3 decimal\nplaces. `0` for a single result, and `0` from the `photon` source,\nwhich publishes no per-result score — so a `0` is \"no signal\", not\n\"a tie\".",
      +      "format": "double",
      +      "type": "number"
      +    },
      +    "source": {
      +      "description": "Which backend answered: \"mapmap-index\" (the first-party index) or\n\"photon\".",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "components",
      +    "score_gap",
      +    "source"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / $defs / GeocodeMatchComponents
      Added value: +{
      +  "description": "Per-component verdicts inside a [`GeocodeMatch`]. Each is one of\n\"matched\", \"inferred\" or \"unmatched\"; a component that was not supplied\nis absent entirely.\n\n* \"matched\" — the result's own field carries the value asked for (case-\n  and accent-insensitive, and by containment, so `city: \"London\"`\n  matches \"City of London\").\n* \"inferred\" — the result carries a value for that component, but not\n  the one asked for. It reached the page through ranking, as when a\n  street is found by its transliterated name and displayed under its\n  canonical one.\n* \"unmatched\" — the result carries no value for that component at all.",
      +  "properties": {
      +    "city": {
      +      "description": "Verdict on the supplied `city`.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "country": {
      +      "description": "Verdict on the supplied `country`.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "housenumber": {
      +      "description": "Verdict on the supplied `housenumber`.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "postcode": {
      +      "description": "Verdict on the supplied `postcode`.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "street": {
      +      "description": "Verdict on the supplied `street`.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    }
      +  },
      +  "type": "object"
      +}
  4. First observed

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so the description carries the full burden. It discloses the detour formula, the candidate_cap of 25 priced per call, the matched_categories echo, costings supported, and server-side normalisation of colloquial phrases. It omits auth/permission needs and rate limits, but for a read-only search this is strong disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, but it is one very dense block that packs normalisation rules, costing notes, and return fields together. Every claim is relevant, yet the structure makes it hard to skim for the parameter guidance an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be spelled out, yet the description still summarises detour_minutes, detour_km, along_route_position and off_route_m. Combined with the routing/costing context, this is complete enough to call the tool correctly without opening the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real value beyond the schema: the origin+destination / geometry_polyline6 mutual exclusion, category normalisation rules, and the query-promotes-to-category behaviour are behaviour the schema does not express.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (find POIs along a route) with a differentiating angle: real detour time rather than straight-line distance. An agent can distinguish it from nearby_places (area search) and from cheapest_fuel_along_route / cheapest_charging_along_route (cost-optimised searches).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit conditions for choosing origin+destination vs geometry_polyline6, and for category vs query ("For a category intent ... pass category instead of relying on words alone"). It names nearby_places as the vocabulary source but never states when a sibling like nearby_places would be the better tool, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources