Skip to main content
Glama

openstreetmap-mcp-server

Reverse geocode coordinates to an address

openstreetmap_reverse_geocode
Read-onlyIdempotent

Convert a latitude/longitude pair to the nearest address or named place via Nominatim. The result is the closest indexed OSM object at the requested zoom (18 building, 10 city), which in dense areas can be a neighbouring feature rather than the one containing the coordinate; proximity and layer pick it, never an OSM attribute tag, so find features by tag with openstreetmap_query_nearby, openstreetmap_query_bbox, or openstreetmap_query_raw.

Input Schema

NameRequiredDescriptionDefault
latYesLatitude in WGS84 decimal degrees.
lonYesLongitude in WGS84 decimal degrees.
zoomNoAddress detail level, roughly corresponding to map zoom. 18=building, 16=street, 14=neighbourhood, 12=town, 10=city, 8=county, 5=state, 3=country.
layerNoRestrict which OSM layer is matched: one of address, poi, railway, natural, manmade, or a comma-separated list of them, in any casing. Any other name is rejected here, not upstream; an empty value counts as omitted. Default: address,poi.
languageNoPreferred language for the result (BCP 47 code or Accept-Language string).
extratagsNoInclude the matched object's extra OSM tags — contact and metadata (phone, website, opening_hours, wikidata) and physical attributes (surface, tracktype, sac_scale, ele, access). An absent tag describes that object, not OpenStreetMap.

Output Schema

NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
resultNoThe closest matching OSM object at the given coordinates.
attributionNoRequired data attribution.
tagSelectionCaveatNoStanding caveat: tag-based selection lives on the Overpass tools (openstreetmap_query_nearby, openstreetmap_query_bbox, openstreetmap_query_raw), never here. extratags decorates the returned objects rather than selecting them, so a missing tag is not evidence the tag is missing from OpenStreetMap. Present when extratags was requested.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim reported no OSM data at the coordinates — open ocean or unmapped territory. `invalid_parameters`: Nominatim returned HTTP 400, refusing one of the forwarded parameters; its own message names which one. `rate_limited`: Nominatim returned HTTP 429, or HTTP 200 with a throttle document in place of JSON — the one request per second policy was exceeded. `upstream_error`: Nominatim returned a non-2xx status other than 429, or HTTP 200 with a non-JSON body carrying no throttle signature. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim reported no OSM data at the coordinates — open ocean or unmapped territory. `invalid_parameters`: Nominatim returned HTTP 400, refusing one of the forwarded parameters; its own message names which one. `rate_limited`: Nominatim returned HTTP 429, or HTTP 200 with a throttle document in place of JSON — the one request per second policy was exceeded. `upstream_error`: Nominatim returned a non-2xx status other than 400 or 429, or HTTP 200 with a non-JSON body carrying no throttle signature, or never answered: connection refused, host not found, or timed out. Other values are possible when a failure originates below the handler."
  2. Changed7 schema fields changed
    • changedOutput schema / properties / result / properties / boundingbox / description
      Previous value: -"Bounding box as [south, north, west, east] strings."New value: +"Bounding box as [south, north, west, east] in WGS84 decimal degrees."
    • changedOutput schema / properties / result / properties / boundingbox / prefixItems
      Previous value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "type": "number"
      +  },
      +  {
      +    "type": "number"
      +  },
      +  {
      +    "type": "number"
      +  },
      +  {
      +    "type": "number"
      +  }
      +]
    • changedOutput schema / properties / result / properties / lat / description
      Previous value: -"Latitude of the matched OSM object."New value: +"Latitude in WGS84 decimal degrees."
    • changedOutput schema / properties / result / properties / lat / type
      Previous value: -"string"New value: +"number"
    • changedOutput schema / properties / result / properties / lon / description
      Previous value: -"Longitude of the matched OSM object."New value: +"Longitude in WGS84 decimal degrees."
    • changedOutput schema / properties / result / properties / lon / type
      Previous value: -"string"New value: +"number"
    • changedOutput schema / properties / result / properties / osm_id / description
      Previous value: -"OSM object ID. Combine with osm_type for openstreetmap_lookup_objects."New value: +"OSM object ID. Combine with osm_type for openstreetmap_lookup_objects, or pass \"R\"/\"W\" + this id as within on openstreetmap_query_bbox to search inside this boundary. The same scope in openstreetmap_query_raw is rel(<osm_id>);map_to_area->.a; or way(<osm_id>);map_to_area->.a; then (area.a) on each statement."
  3. Changed6 schema fields changed
    • changedInput schema / properties / extratags / description
      Previous value: -"Include the extra OSM tags the matched object carries — contact and metadata tags (phone, website, opening_hours, wikidata) and physical attribute tags alike (surface, tracktype, sac_scale, ele, access). Opportunistic, not selective: it reports whatever the matched object happens to carry, so an absent tag describes that object rather than OpenStreetMap, and no value here can steer which object is matched."New value: +"Include the matched object's extra OSM tags — contact and metadata (phone, website, opening_hours, wikidata) and physical attributes (surface, tracktype, sac_scale, ele, access). An absent tag describes that object, not OpenStreetMap."
    • changedInput schema / properties / layer / description
      Previous value: -"Restrict which OSM layer is matched. One value or a comma-separated list drawn from: address, poi, railway, natural, manmade, in any casing. An undocumented layer name is rejected here rather than by Nominatim; an empty value is accepted and treated as omitted. Default: address,poi."New value: +"Restrict which OSM layer is matched: one of address, poi, railway, natural, manmade, or a comma-separated list of them, in any casing. Any other name is rejected here, not upstream; an empty value counts as omitted. Default: address,poi."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim returns an error indicating no OSM data at the given coordinates (e.g., open ocean or unmapped territory). `invalid_parameters`: Nominatim returned HTTP 400 — it refused one of the forwarded parameters. Its own message names the parameter and is carried in this error. `rate_limited`: Nominatim returned HTTP 429, or answered HTTP 200 with a throttle document instead of JSON — the one request per second usage policy was exceeded. `upstream_error`: Nominatim returned an unexpected non-2xx status other than 429, or answered HTTP 200 with a body that is not JSON and carries no throttle signature. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim reported no OSM data at the coordinates — open ocean or unmapped territory. `invalid_parameters`: Nominatim returned HTTP 400, refusing one of the forwarded parameters; its own message names which one. `rate_limited`: Nominatim returned HTTP 429, or HTTP 200 with a throttle document in place of JSON — the one request per second policy was exceeded. `upstream_error`: Nominatim returned a non-2xx status other than 429, or HTTP 200 with a non-JSON body carrying no throttle signature. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / result / properties / address / description
      Previous value: -"Structured address. Keys vary by feature type. Common: house_number, road, suburb, city, state, postcode, country, country_code."New value: +"Structured address, keys varying by feature type: house_number, road, suburb, city, state, postcode, country, country_code."
    • changedOutput schema / properties / result / properties / category / description
      Previous value: -"OSM feature category (e.g., \"amenity\", \"building\")."New value: +"OSM feature category (e.g. \"amenity\", \"building\")."
    • changedOutput schema / properties / result / properties / name / description
      Previous value: -"Feature name if the result is a named place."New value: +"Feature name when the object is named."
  4. Changed5 schema fields changed
    • addedInput schema / properties / layer / anyOf
      Added value: +[
      +  {
      +    "const": "",
      +    "type": "string"
      +  },
      +  {
      +    "description": "One documented layer name, or a comma-separated list of them, in any casing.",
      +    "pattern": "^\\s*(?:(?:[aA][dD][dD][rR][eE][sS][sS]|[pP][oO][iI]|[rR][aA][iI][lL][wW][aA][yY]|[nN][aA][tT][uU][rR][aA][lL]|[mM][aA][nN][mM][aA][dD][eE])(?:\\s*,\\s*(?:[aA][dD][dD][rR][eE][sS][sS]|[pP][oO][iI]|[rR][aA][iI][lL][wW][aA][yY]|[nN][aA][tT][uU][rR][aA][lL]|[mM][aA][nN][mM][aA][dD][eE]))*)?\\s*$",
      +    "type": "string"
      +  }
      +]
    • changedInput schema / properties / layer / description
      Previous value: -"Restrict which OSM layer is matched. Comma-separated: address, poi, railway, natural, manmade. Default: address,poi."New value: +"Restrict which OSM layer is matched. One value or a comma-separated list drawn from: address, poi, railway, natural, manmade, in any casing. An undocumented layer name is rejected here rather than by Nominatim; an empty value is accepted and treated as omitted. Default: address,poi."
    • removedInput schema / properties / layer / type
      Removed value: -"string"
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim returns an error indicating no OSM data at the given coordinates (e.g., open ocean or unmapped territory). `rate_limited`: Nominatim returned HTTP 429, or answered HTTP 200 with a throttle document instead of JSON — the one request per second usage policy was exceeded. `upstream_error`: Nominatim returned an unexpected non-2xx status other than 429, or answered HTTP 200 with a body that is not JSON and carries no throttle signature. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim returns an error indicating no OSM data at the given coordinates (e.g., open ocean or unmapped territory). `invalid_parameters`: Nominatim returned HTTP 400 — it refused one of the forwarded parameters. Its own message names the parameter and is carried in this error. `rate_limited`: Nominatim returned HTTP 429, or answered HTTP 200 with a throttle document instead of JSON — the one request per second usage policy was exceeded. `upstream_error`: Nominatim returned an unexpected non-2xx status other than 429, or answered HTTP 200 with a body that is not JSON and carries no throttle signature. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "no_coverage",
      -  "rate_limited",
      -  "upstream_error"
      -]New value: +[
      +  "no_coverage",
      +  "invalid_parameters",
      +  "rate_limited",
      +  "upstream_error"
      +]
  5. Changed3 schema fields changed
    • addedOutput schema / properties / result / properties / boundingbox / items
      Added value: +false
    • addedOutput schema / properties / result / properties / boundingbox / maxItems
      Added value: +4
    • addedOutput schema / properties / result / properties / boundingbox / minItems
      Added value: +4
  6. Changed8 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "result",
      +      "attribution"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `no_coverage`: Nominatim returns an error indicating no OSM data at the given coordinates (e.g., open ocean or unmapped territory). `rate_limited`: Nominatim returned HTTP 429, or answered HTTP 200 with a throttle document instead of JSON — the one request per second usage policy was exceeded. `upstream_error`: Nominatim returned an unexpected non-2xx status other than 429, or answered HTTP 200 with a body that is not JSON and carries no throttle signature. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "no_coverage",
      +            "rate_limited",
      +            "upstream_error"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / properties / result / properties / boundingbox / items
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]
    • addedOutput schema / properties / result / properties / boundingbox / prefixItems
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • removedOutput schema / required
      Removed value: -[
      -  "result",
      -  "attribution"
      -]
  7. Changed3 schema fields changed
    • changedInput schema / properties / extratags / description
      Previous value: -"Include extra OSM tags when available (phone, website, opening_hours, wikidata, etc.)."New value: +"Include the extra OSM tags the matched object carries — contact and metadata tags (phone, website, opening_hours, wikidata) and physical attribute tags alike (surface, tracktype, sac_scale, ele, access). Opportunistic, not selective: it reports whatever the matched object happens to carry, so an absent tag describes that object rather than OpenStreetMap, and no value here can steer which object is matched."
    • changedOutput schema / properties / result / properties / extratags / description
      Previous value: -"Additional OSM tags (phone, website, opening_hours, wikidata). Present only when extratags was requested."New value: +"Extra OSM tags this object carries — contact and metadata (phone, website, opening_hours, wikidata) and physical attributes (surface, tracktype, sac_scale, ele, access). Present only when extratags was requested; an absent tag describes this object, not OpenStreetMap."
    • addedOutput schema / properties / tagSelectionCaveat
      Added value: +{
      +  "description": "Standing caveat: tag-based selection lives on the Overpass tools (openstreetmap_query_nearby, openstreetmap_query_bbox, openstreetmap_query_raw), never here. extratags decorates the returned objects rather than selecting them, so a missing tag is not evidence the tag is missing from OpenStreetMap. Present when extratags was requested.",
      +  "type": "string"
      +}
  8. Added

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already declare readOnly, openWorld, and idempotent, and the description still adds real behavioral context: selection is by proximity and layer, not by OSM attribute tags, so in dense areas the match may be a neighbouring feature rather than the containing one. That caveat is exactly the kind of non-obvious behavior an agent needs to interpret results correctly.

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

Conciseness4/5

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

Two sentences with the purpose front-loaded and no filler; the caveat and sibling routing come after the core definition. The second sentence is long and clause-heavy ('proximity and layer pick it, never an OSM attribute tag'), which costs a little readability but not correctness.

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?

With an output schema present, return values need not be explained, and annotations cover the safety profile, so the remaining burden is the matching caveat — which the description handles well. It stops short of noting failure modes such as no match found or Nominatim rate/usage limits for a network-dependent call, a minor gap.

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

Parameters3/5

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

Schema description coverage is 100% and the schema already explains lat/lon ranges, the zoom ladder (18=building, 10=city), the layer vocabulary, language, and extratags. The description's only added semantic is that proximity and layer drive matching, which is helpful but marginal against an already complete schema, so the baseline 3 applies.

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 and resource ('Convert a latitude/longitude pair to the nearest address or named place via Nominatim') and immediately bounds the answer to 'the closest indexed OSM object at the requested zoom'. It explicitly distinguishes itself from the query_* siblings, so an agent can tell what it does and does not return 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.

Usage Guidelines4/5

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

It gives a clear condition for using the alternatives: when you need to find features by tag, use query_nearby, query_bbox, or query_raw. There is no true one-to-one alternative for reverse geocoding, so the guidance is a limitation-and-routing statement rather than a full when/when-not pair, but the routing is explicit and actionable.

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.