Openstreetmap Mcp Server

io.github.cyanheads由 GitHub 帳號 cyanheads 發布v0.7.1更新於 Nov 5, 2026

Geocode, reverse geocode, and run Overpass spatial queries on OpenStreetMap data.

已驗證Streamable HTTP可網頁執行資料庫位置與生活

概覽

AI 產生的概覽

OpenStreetMap 地理編碼與 Overpass 空間查詢伺服器:把地名解析為座標、把座標解析為地址,並依標籤檢索 OSM 圖徵。

可以做什麼
  • 將地名或結構化地址地理編碼為座標,並將座標反向解析為最近的地址或地名
  • 依 OSM 物件 ID 查詢完整的地址記錄
  • 在某一點周圍指定半徑內尋找 OSM 圖徵,可依 amenity 或標籤鍵值過濾
  • 在矩形範圍內或某個 OSM 邊界(如城市、公園)內檢索圖徵
  • 執行任意 Overpass QL 查詢,用於聯合查詢、關係成員、正規表達式標籤或歷史資料
適用情境
適合需要真實地理資料的情境:把地址解析為座標、說明某地點附近有什麼,或列出某區域內的圖徵,用於地圖、旅遊或在地調查任務。
執行需求
可使用託管的 HTTP 端點,也可透過 npx(Node.js)在本機執行,原始碼建置需要 Bun。不需要 API 金鑰。選用變數可設定 Nominatim 與 Overpass 端點、Overpass 併發與容錯切換,以及使用政策要求的 OSM_USER_AGENT。需要能連線至 Nominatim 與 Overpass 的網路。
安裝前請注意
查詢會送往有速率限制的公開 Nominatim 與 Overpass 實例,大量使用時應以 OSM_NOMINATIM_BASE_URL 和 OSM_OVERPASS_BASE_URL 指向自架實例。在 OSM_OVERPASS_ENDPOINTS 加入項目會把查詢送給第三方,須自行確認其政策與資料新舊。工具為唯讀,回傳的 OpenStreetMap 資料依 ODbL 1.0 授權,需標示出處。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Openstreetmap Mcp Server,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.cyanheads%2Fopenstreetmap-mcp-server/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "openstreetmap": {
      "type": "http",
      "url": "https://openstreetmap.caseyjhand.com/mcp"
    }
  }
}

README

@cyanheads/openstreetmap-mcp-server

Geocode, reverse geocode, and run Overpass spatial queries on OpenStreetMap data via MCP. STDIO or Streamable HTTP.

6 Tools


Overview

OpenStreetMap data through Nominatim and the Overpass API. Geocode places and addresses, resolve coordinates to the nearest address, look up known OSM objects, and query features by tag around a point, inside a bounding box, or inside an OSM boundary.

Tools

ToolDescription
openstreetmap_search_placesConvert a place name or address to coordinates and structured place data
openstreetmap_reverse_geocodeConvert latitude/longitude to the nearest address or place name
openstreetmap_lookup_objectsFetch address records for known OSM objects by ID
openstreetmap_query_nearbyFind OSM features within a radius of a point
openstreetmap_query_bboxFind OSM features inside a bounding box or an OSM boundary such as a city, park, or region
openstreetmap_query_rawRun a raw Overpass QL query for anything the other tools cannot express

Capability reference

The openstreetmap-guide skill covers place resolution, spatial queries, paging, and interpreting coverage and tag results.

Argument aliases are accepted before canonical validation: latitude / longitude for lat / lon on nearby and reverse queries, radius_m for nearby's radius_meters, and q for search's query. Send either spelling, never both. radius, tag, and tags remain invalid; advertised schemas use canonical names.

openstreetmap_search_places tool

  • Free-form query or the structured fields street, city, county, state, country, postalcode, never both; up to 40 results (limit, default 5; a larger limit is served as 40 with a limitNotice), narrowed by countrycodes, layer, featureType, and a viewbox (restricting with bounded: true)
  • Results carry coordinates, structured address, boundingbox, importance, and osm_type + osm_id; extratags adds contact and physical-attribute tags; an empty first page fails as no_results, naming any countrycodes, layer, featureType, or bounded viewbox that was sent
  • Every page with results returns nextExcludeIds to pass back as exclude_place_ids, since a page shorter than limit can still have more; once results run out you get zero results and a notice, not an error, and a walk too long for the instance's URL limit fails as request_too_long

openstreetmap_reverse_geocode tool

  • lat / lon plus zoom from 3 (country) to 18 (building, the default); layer defaults to address,poi
  • Returns the nearest indexed object with structured address, osm_type + osm_id, and boundingbox; coordinates with no OSM data fail as no_coverage

openstreetmap_lookup_objects tool

  • Up to 500 osm_ids entries, each prefixed N, W, or R (["N240109189"]); a malformed ID fails as invalid_id_format
  • The first 50 unique IDs are looked up; the rest come back as deferred_ids for the next call
  • Returns address records for the objects found and lists the rest under not_found (including objects Nominatim does not index, such as street lamps); a notice carries an openstreetmap_query_raw query to check which exist

openstreetmap_query_nearby tool

  • lat / lon with radius_meters up to 50,000 (default 1,000); one primary tag, amenity or tag_key with an optional tag_value, plus up to five ANDed filters; up to 500 features per page (a larger limit is served as 500 with a limitNotice)
  • element_types searches nodes, ways, and relations unless set; ["node", "way"] leaves relations out
  • A value matches exactly by default; list_item mode (tag_value_match, or match on a filter) matches one item of a semicolon list, so cuisine = pizza also finds cuisine=pizza;italian
  • An amenity value that OpenStreetMap tags under another key (amenity: "museum"; museums are tourism=museum) gets a notice naming the key to retry with
  • Features carry osm_type + osm_id, coordinates, distance_meters (to the feature's nearest point), and the full tag set, sorted nearest-first; effectiveTag echoes the filter chain
  • With ways or relations searched, an area containing the point, such as the park or city it lies in, matches at distance_meters 0 whatever the radius, and areasTimestamp says how old the area data is. An endpoint that cannot run the area lookup is asked again without it, and the notice says areas containing the point were not checked

openstreetmap_query_bbox tool

  • One scope per call: the corners south, west, north, east, or within and one R/W boundary ref (R237385) built from a geocoding result's osm_type + osm_id; the same tag filters, list-item matching, stray-amenity notice, and 500-per-page cap as openstreetmap_query_nearby
  • element_types searches nodes, ways, and relations unless set; ["node", "way"] leaves relations out
  • effectiveArea names the boundary within reached by its name, boundary, and admin_level tags, then the Overpass area it mapped to, so a mistyped ref shows; areasTimestamp says how old the area data is; a ref that maps to no area returns an empty page with a notice
  • A west greater than east is a box crossing the antimeridian; south greater than north fails as invalid_bbox

openstreetmap_query_raw tool

  • Any Overpass QL containing [out:json]; [timeout:N] comes from timeout_seconds (up to 180, default 30) and [maxsize:268435456] (256 MiB) is added when the query sets none; up to 500 elements per page (a larger limit is served as 500 with a limitNotice)
  • Returns raw elements (ways carry nodes[], relations members[]), plus total_elements and the effectiveQuery as sent; malformed QL fails as query_error with Overpass's parse error
  • max_element_bytes (default 20,000, minimum 1,000) withholds an over-budget element's members, nodes, or geometry arrays, listed under withheld_keys; withheldElements and withheldNotice say how to fetch them

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

OpenStreetMap-specific:

  • Nominatim requests are spaced 1,050 ms apart to respect its one-request-per-second policy; OSM_USER_AGENT identifies the server to both upstreams
  • Overpass queries are limited per endpoint by OSM_OVERPASS_MAX_CONCURRENCY, with opt-in failover across OSM_OVERPASS_ENDPOINTS (see Overpass endpoint failover)
  • Overpass tools page with limit and offset and report totalFound, truncated, and nextOffset; results are cached for 10 minutes (Nominatim for 60), so re-paging makes no new upstream request
  • An Overpass response over 64 MiB fails as result_too_large
  • OSM_NOMINATIM_BASE_URL and OSM_OVERPASS_BASE_URL point the server at a self-hosted or mirror instance

Agent-friendly output:

  • effectiveQuery and effectiveTag echo what was sent, and effectiveArea names the boundary a within ref reached; Overpass responses add data_timestamp and servingEndpoint, and every response carries the ODbL attribution
  • osm_type + osm_id from any tool feed openstreetmap_lookup_objects, and a geocoded relation or way becomes a within ref for openstreetmap_query_bbox
  • The Nominatim tools never select by tag, and tagSelectionCaveat says so; regex, alternation, and negation go through openstreetmap_query_raw
  • Names and tag values are escaped in the Markdown output; structuredContent keeps the raw text

Getting started

Connect to the hosted instance, no install:

sh
claude mcp add --transport http openstreetmap-mcp-server https://openstreetmap.caseyjhand.com/mcp

Or run it locally:

sh
claude mcp add openstreetmap-mcp-server -- npx -y @cyanheads/openstreetmap-mcp-server

For other clients, add this to the MCP config file:

json
{  "mcpServers": {    "openstreetmap-mcp-server": {      "command": "npx",      "args": ["-y", "@cyanheads/openstreetmap-mcp-server"]    }  }}

No API key is required. For heavy use, point OSM_NOMINATIM_BASE_URL and OSM_OVERPASS_BASE_URL at your own instances. For Docker or a source build, see Running the server.

Configuration

VariableDescriptionDefault
OSM_NOMINATIM_BASE_URLNominatim base URL. A path prefix such as https://maps.example.com/nominatim is supported.https://nominatim.openstreetmap.org
OSM_OVERPASS_BASE_URLPins every query to one Overpass endpoint and disables failover.unset
OSM_OVERPASS_ENDPOINTSComma-separated, ordered Overpass endpoints; more than one enables failover. Ignored when OSM_OVERPASS_BASE_URL is set.https://overpass-api.de/api/interpreter
OSM_OVERPASS_MAX_CONCURRENCYMax Overpass queries in flight per endpoint. Public instances allow one per user.1
OSM_USER_AGENTUser-Agent sent to Nominatim and Overpass. Required by usage policy.openstreetmap-mcp-server/<package version>
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTHTTP server port.3010
MCP_SESSION_MODEHTTP session mode: stateless, stateful, or auto. The server declares stateless in code; an explicit value overrides it.stateless
MCP_AUTH_MODEAuthentication: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (debug, info, warning, error, etc.).info
STORAGE_PROVIDER_TYPEStorage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1.in-memory
OTEL_ENABLEDEnable OpenTelemetry.false

See .env.example for the full list of optional overrides. An invalid value for any OSM_* variable stops the server at startup with a message naming the variable.

Overpass endpoint failover

By default every Overpass query goes to one endpoint, the FOSSGIS-operated main instance. List more in OSM_OVERPASS_ENDPOINTS and a failed call moves to the next entry in order:

sh
OSM_OVERPASS_ENDPOINTS="https://overpass-api.de/api/interpreter,https://overpass.private.coffee/api/interpreter"
  • Endpoints that fail repeatedly are skipped for a while (30 seconds, doubling up to 10 minutes)
  • When every endpoint fails, the call fails with rate_limited, upstream_error, overpass_unavailable, endpoints_rejected, endpoints_exhausted, or endpoints_unavailable, with each endpoint's outcome in the message
  • Endpoints are reported by origin only (https://overpass-api.de) in servingEndpoint, error messages, and logs
  • Extra entries are failover only and never add concurrency. For an instance that allows parallel queries, append |N to its entry (https://mirror.example/api/interpreter|4) for N slots; write a literal | in a URL as %7C. Never size a public instance (the FOSSGIS servers, maps.mail.ru, overpass.private.coffee)
  • Calls waiting for a slot fail with pacer_shed and a retryAfter of at least 30 seconds after 30 seconds in line

Adding an endpoint sends your queries to a third party. Check its usage policy on the OSM wiki instance list, confirm it holds global data (a regional instance answers out-of-extract queries with an empty HTTP 200), and expect mirrors to lag the main instance; servingEndpoint and data_timestamp show which host answered and how fresh its data was.

Running the server

Local development

Requires Bun v1.4.0 or higher (or Node.js v24+).

sh
git clone https://github.com/cyanheads/openstreetmap-mcp-server.gitcd openstreetmap-mcp-server && bun installcp .env.example .env# edit .env to override endpoints or the User-Agent as needed
  • Build and run the production version:

    sh
    # One-time buildbun run rebuild
    # Run the built serverbun run start:http# orbun run start:stdio
  • Run checks and tests:

    sh
    bun run devcheck  # Lints, formats, type-checks, and morebun run test      # Runs the test suite

Docker

sh
docker run --rm -p 3010:3010 ghcr.io/cyanheads/openstreetmap-mcp-server:latest
# or build locallydocker build -t openstreetmap-mcp-server .docker run --rm -p 3010:3010 openstreetmap-mcp-server

The image serves HTTP at http://localhost:3010/mcp in stateless session mode and logs to /var/log/openstreetmap-mcp-server. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them. Runtime telemetry stays off until you pass -e OTEL_ENABLED=true.

Project structure

DirectoryPurpose
src/mcp-server/toolsTool definitions (*.tool.ts) and shared input, formatting, and escaping helpers. Six tools across Nominatim and Overpass.
src/services/nominatimNominatim service: paced API client for search, reverse, and lookup, plus error parsing.
src/services/overpassOverpass service: query builder, endpoint failover and executor, element normalizer, error parsing.
src/configServer-specific environment variable parsing and validation with Zod.
tests/Unit and integration tests for tools, services, and security.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for logging, ctx.state for storage
  • Register new tools in the createApp() arrays in src/index.ts
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

sh
bun run devcheckbun run test

License

Apache-2.0 — see LICENSE for details.

Map data from OpenStreetMap contributors, available under the Open Database License (ODbL).

來源:README.md,提交 02efff6

工具

6

openstreetmap_search_places

Geocode a place name or address

Geocode a place name or address to coordinates and structured place data via Nominatim. Send either a free-form query or the structured address fields (street, city, county, state, country, postalcode), never both; results are the best-ranked matches, not every matching object, and matching never uses an OSM attribute tag, so filter or enumerate by tag with openstreetmap_query_nearby, openstreetmap_query_bbox, or openstreetmap_query_raw.

輸入參數citylayerlimitquerystatecountystreetboundedcountryviewboxlanguageextratags另有 4 個

openstreetmap_reverse_geocode

Reverse geocode coordinates to an address

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.

輸入參數lat必填lon必填zoomlayerlanguageextratags

openstreetmap_lookup_objects

Look up address details for OSM objects by ID

Fetch the Nominatim address record for known OSM objects by ID, 50 per call with any more returned under deferred_ids, each prefixed N (node), W (way), or R (relation), e.g. "N240109189". Use it for IDs already in hand from openstreetmap_query_nearby or openstreetmap_query_bbox; it returns only objects named in osm_ids and lists those with no Nominatim record under not_found (Nominatim skips unnamed and non-place objects, so such an ID may still exist). It cannot select by tag, so discover objects with those tools or openstreetmap_query_raw first.

輸入參數osm_ids必填languageextratags

openstreetmap_query_nearby

Find OSM features near a point

Find OSM features within a radius of a point via the Overpass API, the tool for "what is near X?" questions. Filter with amenity, or with tag_key plus an optional tag_value, ANDing up to five more filters; every feature returns with its full OSM tag set (no extratags flag here), sorted nearest-first by distance_meters. An area containing the point, such as the park or city it lies in, matches at 0 m whatever the radius.

輸入參數lat必填lon必填limitoffsetamenityfilterstag_keytag_valueelement_typesradius_meterstag_value_matchtimeout_seconds

openstreetmap_query_bbox

Find OSM features inside a bounding box or an OSM boundary

Find OSM features inside an area via the Overpass API, for surveys of everything in a region (openstreetmap_query_nearby covers proximity to a point). Scope with the four corner fields south, west, north, east, or with within and a single OSM boundary ref such as a city relation or a park way, which searches the boundary polygon itself instead of an overcovering box; never both. Filter with amenity, or with tag_key plus an optional tag_value, ANDing up to five more filters; every feature returns with its full OSM tag set (no extratags flag here).

輸入參數eastwestlimitnorthsouthoffsetwithinamenityfilterstag_keytag_valueelement_types另有 2 個

openstreetmap_query_raw

Execute a raw Overpass QL query

Run an arbitrary Overpass QL query for anything the convenience tools cannot express: multi-type or union queries, relation membership, historical queries, regex tag matching. The query must include [out:json], e.g. "[out:json][timeout:15];node[\"natural\"=\"peak\"](47.5,-122.5,47.7,-122.2);out body;"; scope to an OSM boundary with rel(<id>);map_to_area->.a; or way(<id>);map_to_area->.a; then (area.a) on each statement (the 2400000000 way-area offset is gone since Overpass 0.7.57; openstreetmap_query_bbox takes the same scope as within, without QL). The response is one page: page with limit and offset, read totalFound and truncated for the whole match, and an element over max_element_bytes arrives with its members, nodes or geometry array withheld whole and withheldNotice saying how to fetch it back. For plain "near X" or "in this area" questions use openstreetmap_query_nearby or openstreetmap_query_bbox.

輸入參數limitquery必填offsettimeout_secondsmax_element_bytes

版本歷史

9
  1. v0.7.1最新Nov 5, 2026
  2. v0.7.0Oct 26, 2026
  3. v0.6.2Oct 25, 2026
  4. v0.6.1Oct 15, 2026
  5. v0.6.0Oct 3, 2026
  6. v0.5.2Sep 22, 2026
  7. v0.5.1Sep 17, 2026
  8. v0.5.0Sep 17, 2026
  9. v0.4.8Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分