关于 openstreetmap-mcp-server
openstreetmap-mcp-server 通过 Nominatim 和 Overpass API 提供 OpenStreetMap 地理编码与空间查询,适合需要在 MCP 客户端中检索地点和地图要素的场景。支持按坐标、边界框或 OSM 边界筛选,也可执行原始 Overpass QL。
主要功能
- 01地点与地址地理编码
- 02坐标反向地理编码
- 03按 OSM ID 查询对象
- 04附近及区域要素筛选
- 05执行原始 Overpass QL
适用场景
- 01将地址转换为坐标
- 02查找坐标对应的地点
- 03按标签查找附近设施
- 04在城市边界内筛选地图要素
MCP 相关
它是 MCP 服务,向 MCP 客户端提供 6 个 OpenStreetMap 查询工具,支持 stdio 和 Streamable HTTP。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://openstreetmap.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-openstreetmap https://openstreetmap.caseyjhand.com/mcp{"mcpServers":{"cyanheads-openstreetmap":{"type":"http","url":"https://openstreetmap.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-openstreetmap":{"type":"http","url":"https://openstreetmap.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-openstreetmap":{"type":"http","url":"https://openstreetmap.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-openstreetmap":{"serverUrl":"https://openstreetmap.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
6| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| city | string | 否 | 城市名称(结构化查询)。 |
| layer | any | 否 | 按数据图层筛选:可选 address、poi、railway、natural、manmade 中的一项,或以逗号分隔的列表,大小写不限。此处会拒绝其他名称,而不会将其传递给上游;空值视为未提供。默认值:不限制。 |
| limit | integer | 否 | 最多返回 40 条结果(Nominatim 自身的上限);若设置更大的值,实际按 40 条处理,且 limitNotice 会说明这一点。当其他结果匹配度不足时,Nominatim 返回的结果可能更少。 |
| query | string | 否 | 自由格式搜索字符串,例如 "Space Needle Seattle" 或 "1600 Pennsylvania Ave NW, Washington DC"。不能与结构化地址字段组合使用。Nominatim 会将逗号视为地址层级,因此请仅提供名称及其所在城市或地区,不要在中间插入其他内容:"Beinecke Library, New Haven" 可以匹配,而 "Beinecke Library, Yale University, New Haven" 不会返回结果。 |
| state | string | 否 | 州或省(结构化查询)。 |
| county | string | 否 | 县或区(结构化查询)。 |
| street | string | 否 | 门牌号和街道名称(结构化查询)。与 city/state/country 字段搭配使用。不能与 query 组合。 |
| bounded | boolean | 否 | 将结果限制在 viewbox 范围内,而不仅仅是提高该范围内结果的优先级。需要同时设置 viewbox;单独设置此项会被拒绝,而不会忽略。设置后,即使范围外的匹配得分更高,也会被剔除。 |
| country | string | 否 | 国家/地区名称或 ISO 3166-1 alpha-2 代码(结构化查询)。 |
| viewbox | object | 否 | 用于提高指定区域内结果优先级的矩形范围,可消除全球各地重复名称的歧义(例如同一流域中的小溪、同一市镇内的街道)。范围应小于 countrycodes。默认仅提高优先级:范围外的更佳匹配仍会返回。设置 bounded 可强制限制范围。与 openstreetmap_query_bbox 不同,此范围不能跨越国际日期变更线;必须满足西界小于东界且南界小于北界,否则调用将被拒绝。 |
| viewbox.east | number | 是 | 东侧边界经度。必须严格大于西侧边界。 |
| viewbox.west | number | 是 | 西侧边界经度。必须严格小于东侧边界。 |
| viewbox.north | number | 是 | 北侧边界纬度。必须严格大于南侧边界。 |
| viewbox.south | number | 是 | 南侧边界纬度。必须严格小于北侧边界。 |
| language | string | 否 | 结果名称的首选语言(BCP 47 代码或 Accept-Language 字符串,例如 "en"、"de"、"fr,en")。默认使用当地 OSM 语言。 |
| extratags | boolean | 否 | 包含匹配对象的额外 OSM 标签,包括联系信息和元数据(phone、website、opening_hours、wikidata)以及物理属性(surface、tracktype、sac_scale、ele、access)。缺少标签描述的是该对象,而不是 OpenStreetMap。会增大响应。 |
| postalcode | string | 否 | 邮政编码(结构化查询)。 |
| featureType | enum | 否 | 将结果限制为某种地理要素类型。这会自动包含 address 图层。country | state | city | settlement |
| countrycodes | any | 否 | 将结果限制为一个或多个国家/地区:使用逗号分隔的 ISO 3166-1 alpha-2 代码(例如 "us,ca"),大小写不限,逗号两侧可有空格。其他格式——alpha-3、分号分隔列表、国家/地区名称——会在此处被拒绝,而不会由上游静默丢弃。格式正确但不存在的国家/地区代码不会匹配任何结果。空值视为未提供。筛选时优先使用此参数,而不是结构化 country 字段。 |
| exclude_place_ids | array | 否 | 从结果中排除 OSM 引用(N/W/R + ID)或 Nominatim place_ids;其他形式的标记会在此处被拒绝,而不是由 Nominatim 拒绝。条目会去除首尾空格,小写的引用前缀会转为大写,空白条目视为未提供。若要继续查找更多匹配项,请传回上一整页的 nextExcludeIds;该参数优先使用稳定的 OSM 引用,而非易变的 place_ids。当某页返回零个结果并显示耗尽提示时,遍历结束——这是成功,不是错误。此方法尽力而为,并非游标:Nominatim 的排序可能在调用间变化,因此已查看的结果可能移位。 |
详细介绍
@cyanheads/openstreetmap-mcp-server
通过 MCP 对 OpenStreetMap 数据进行地理编码、反向地理编码和 Overpass 空间查询。支持 STDIO 或 Streamable HTTP。
概述
通过 Nominatim 和 Overpass API 使用 OpenStreetMap 数据。对地点和地址进行地理编码,将坐标解析为最近的地址,查询已知 OSM 对象,并按标签查询点周围、边界框内或 OSM 边界内的要素。
工具
| 工具 | 描述 |
|---|---|
openstreetmap_search_places | 将地点名称或地址转换为坐标和结构化地点数据 |
openstreetmap_reverse_geocode | 将纬度/经度转换为最近的地址或地点名称 |
openstreetmap_lookup_objects | 按 ID 获取已知 OSM 对象的地址记录 |
openstreetmap_query_nearby | 查找指定点一定半径范围内的 OSM 要素 |
openstreetmap_query_bbox | 查找边界框内或 OSM 边界(如城市、公园或地区)内的 OSM 要素 |
openstreetmap_query_raw | 运行原始 Overpass QL 查询,以实现其他工具无法表达的查询 |
功能参考
openstreetmap-guide 技能介绍地点解析、空间查询、分页,以及如何解读覆盖范围和标签结果。
在规范校验前会接受参数别名:附近查询和反向查询中,latitude / longitude 可代替 lat / lon;附近查询中,radius_m 可代替 radius_meters;搜索中,q 可代替 query。请任选一种写法,不要同时使用两种。radius、tag 和 tags 仍为无效参数;公布的模式使用规范名称。
openstreetmap_search_places 工具
- 使用自由格式的
query或结构化字段street、city、county、state、country、postalcode,两者不能同时使用;最多返回 40 条结果(limit默认值为 5;若limit更大,则按 40 处理,并返回limitNotice),可通过countrycodes、layer、featureType和viewbox缩小范围(使用bounded: true进行限制) - 结果包含坐标、结构化的
address、boundingbox、importance以及osm_type+osm_id;extratags会添加联系信息和物理属性标签;若第一页无结果,则以no_results失败 - 返回整页结果时会提供
nextExcludeIds,供后续请求作为exclude_place_ids传回;结果耗尽后会返回零条结果和提示,而不是错误
openstreetmap_reverse_geocode 工具
- 使用
lat/lon,并通过zoom指定缩放级别,范围为 3(国家)到 18(建筑,默认值);layer默认为address,poi - 返回最近的已编入索引的对象,包含结构化的
address、osm_type+osm_id和boundingbox;没有 OSM 数据的坐标会以no_coverage失败
openstreetmap_lookup_objects 工具
- 最多接受 500 个
osm_ids条目,每个条目必须以N、W或R开头(["N240109189"]);格式错误的 ID 会以invalid_id_format失败 - 查询前 50 个不重复的 ID;其余 ID 会作为
deferred_ids返回,供下次调用使用 - 返回找到的对象的地址记录,并将其余对象列在
not_found下(包括 Nominatim 未编入索引的对象,例如路灯);notice中包含一条openstreetmap_query_raw查询,可用于检查哪些对象存在
openstreetmap_query_nearby 工具
- 使用
lat/lon和radius_meters,半径上限为 50,000(默认值为 1,000);指定一个主标签amenity,或指定tag_key和可选的tag_value,并可添加最多五个以 AND 连接的filters;每页最多返回 500 个要素(若limit更大,则按 500 处理,并返回limitNotice) - 默认情况下,值必须完全匹配;
list_item模式(通过tag_value_match指定,或在过滤条件中使用match)会匹配分号分隔列表中的单个项目,因此cuisine=pizza也会找到cuisine=pizza;italian - 如果某个
amenity值在 OpenStreetMap 中使用其他键标记(amenity: "museum";博物馆使用tourism=museum),则会返回notice,指出应改用的键 - 要素包含
osm_type+osm_id、坐标、distance_meters(到要素最近点的距离)以及完整标签集,并按距离从近到远排序;effectiveTag会回显过滤链
openstreetmap_query_bbox 工具
- 每次调用只能指定一个范围:角点
south、west、north、east,或within加一个R/W边界引用(R237385),该引用由地理编码结果中的osm_type+osm_id构成;标签过滤、列表项匹配、无效amenity提示以及每页最多 500 条的限制均与openstreetmap_query_nearby相同 effectiveArea会回显within的解析结果,areasTimestamp会显示区域数据的时效;未映射到区域的引用会返回空页和提示west大于east表示边界框跨越国际日期变更线;south大于north会以invalid_bbox失败
openstreetmap_query_raw 工具
- 可使用任何包含
[out:json]的 Overpass QL;[timeout:N]根据timeout_seconds设置(上限为 180,默认值为 30);如果查询未设置[maxsize:268435456](256 MiB),则会自动添加;每页最多返回 500 个元素(若limit更大,则按 500 处理,并返回limitNotice) - 返回原始元素(way 包含
nodes[],relation 包含members[]),以及total_elements和实际发送的effectiveQuery;格式错误的 QL 会以query_error失败,并附上 Overpass 的解析错误 max_element_bytes(默认值为 20,000,最小值为 1,000)会省略超出预算的元素的members、nodes或geometry数组,并在withheld_keys下列出这些字段;withheldElements和withheldNotice会说明如何获取它们
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志。
OpenStreetMap 专属功能:
- Nominatim 请求间隔为 1,050 ms,以遵守每秒一次请求的策略;
OSM_USER_AGENT会向两个上游标识此服务 - Overpass 查询受
OSM_OVERPASS_MAX_CONCURRENCY限制,可选择启用跨OSM_OVERPASS_ENDPOINTS的故障转移(参见 Overpass 端点故障转移) - Overpass 工具支持使用
limit和offset分页,并返回totalFound、truncated和nextOffset;结果会缓存 10 分钟(Nominatim 结果缓存 60 分钟),因此翻页不会产生新的上游请求 - 超过 64 MiB 的 Overpass 响应会以
result_too_large错误终止 OSM_NOMINATIM_BASE_URL和OSM_OVERPASS_BASE_URL可将服务指向自托管或镜像实例
适合 Agent 使用的输出:
effectiveQuery、effectiveTag和effectiveArea会回显实际发送的内容;Overpass 响应会添加data_timestamp和servingEndpoint,且每个响应都会包含 ODbLattribution- 任意工具返回的
osm_type+osm_id都可传给openstreetmap_lookup_objects;地理编码得到的 relation 或 way 可转换为within引用,供openstreetmap_query_bbox使用 - Nominatim 工具不会按标签筛选,并会通过
tagSelectionCaveat明确说明;正则表达式、交替匹配和否定筛选需使用openstreetmap_query_raw - Markdown 输出中的名称和标签值会进行转义;
structuredContent保留原始文本
快速开始
连接到托管实例,无需安装:
claude mcp add --transport http openstreetmap-mcp-server https://openstreetmap.caseyjhand.com/mcp
或者在本地运行:
claude mcp add openstreetmap-mcp-server -- npx -y @cyanheads/openstreetmap-mcp-server
对于其他客户端,请将以下内容添加到 MCP 配置文件:
{
"mcpServers": {
"openstreetmap-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/openstreetmap-mcp-server"]
}
}
}
无需 API 密钥。若需大量使用,请将 OSM_NOMINATIM_BASE_URL 和 OSM_OVERPASS_BASE_URL 指向你自己的实例。Docker 部署或从源码构建,请参阅运行服务。
配置
| 变量 | 说明 | 默认值 |
|---|---|---|
OSM_NOMINATIM_BASE_URL | Nominatim 基础 URL。支持使用路径前缀,例如 https://maps.example.com/nominatim。 | https://nominatim.openstreetmap.org |
OSM_OVERPASS_BASE_URL | 将所有查询固定到一个 Overpass 端点,并禁用故障转移。 | 未设置 |
OSM_OVERPASS_ENDPOINTS | 以逗号分隔、按顺序排列的 Overpass 端点;多于一个端点时会启用故障转移。设置 OSM_OVERPASS_BASE_URL 时会忽略此项。 | https://overpass-api.de/api/interpreter |
OSM_OVERPASS_MAX_CONCURRENCY | 每个端点允许同时执行的 Overpass 查询数上限。公共实例允许每位用户同时执行一个查询。 | 1 |
OSM_USER_AGENT | 发送给 Nominatim 和 Overpass 的 User-Agent。使用策略要求必须设置。 | openstreetmap-mcp-server/<package version> |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_SESSION_MODE | HTTP 会话模式:stateless、stateful 或 auto。代码中声明服务为 stateless;显式设置的值会覆盖该声明。 | stateless |
MCP_AUTH_MODE | 身份验证方式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、warning、error 等)。 | info |
STORAGE_PROVIDER_TYPE | 存储后端:in-memory、filesystem、supabase、cloudflare-kv/r2/d1。 | in-memory |
OTEL_ENABLED | 启用 OpenTelemetry。 | false |
完整的可选覆盖项列表请参阅 .env.example。任何 OSM_* 变量的值无效时,服务会在启动时停止,并显示相应变量名。
Overpass 端点故障转移
默认情况下,每个 Overpass 查询都会发送到同一个端点,即由 FOSSGIS 运营的主实例。在 OSM_OVERPASS_ENDPOINTS 中列出更多端点,调用失败时会按顺序切换到下一个端点:
OSM_OVERPASS_ENDPOINTS="https://overpass-api.de/api/interpreter,https://overpass.private.coffee/api/interpreter"
- 反复失败的端点会暂时跳过(30 秒,之后逐步加倍,最长 10 分钟)
- 所有端点均失败时,调用会返回
rate_limited、upstream_error、overpass_unavailable、endpoints_rejected、endpoints_exhausted或endpoints_unavailable;消息中会说明每个端点的结果 servingEndpoint、错误消息和日志中仅报告端点的来源地址(https://overpass-api.de)- 额外条目仅用于故障转移,不会增加并发数。对于允许并行查询的实例,在条目后附加
|N,表示 N 个槽位(https://mirror.example/api/interpreter|4);URL 中的字面|请写作%7C。切勿为公共 FOSSGIS 服务器设置并发数 - 等待槽位的调用若排队满 30 秒,会以
pacer_shed失败,且retryAfter至少为 30 秒
添加端点意味着将查询发送给第三方。请在 OSM wiki 实例列表中查看其使用政策,确认它持有全球数据(区域实例对查询范围外的数据会返回空的 HTTP 200),并注意镜像可能落后于主实例;servingEndpoint 和 data_timestamp 会显示响应的主机以及其数据的新鲜程度。
运行服务器
本地开发
需要 Bun v1.4.0 或更高版本(或 Node.js v24+)。
git clone https://github.com/cyanheads/openstreetmap-mcp-server.git
cd openstreetmap-mcp-server && bun install
cp .env.example .env
# edit .env to override endpoints or the User-Agent as needed
-
构建并运行生产版本:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
运行检查和测试:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Docker
docker run --rm -p 3010:3010 ghcr.io/cyanheads/openstreetmap-mcp-server:latest
# or build locally
docker build -t openstreetmap-mcp-server .
docker run --rm -p 3010:3010 openstreetmap-mcp-server
此镜像以无状态会话模式在 http://localhost:3010/mcp 提供 HTTP 服务,并将日志写入 /var/log/openstreetmap-mcp-server。默认会安装 OpenTelemetry 对等依赖;若要省略这些依赖,请使用 --build-arg OTEL_ENABLED=false 构建。只有传入 -e OTEL_ENABLED=true 后,运行时遥测才会启用。
项目结构
| 目录 | 用途 |
|---|---|
src/mcp-server/tools | 工具定义(*.tool.ts)以及共用的输入、格式化和转义辅助函数。涵盖 Nominatim 和 Overpass 的六个工具。 |
src/services/nominatim | Nominatim 服务:用于搜索、反向查询和查找的限速 API 客户端,以及错误解析。 |
src/services/overpass | Overpass 服务:查询构建器、端点故障转移和执行器、元素规范化、错误解析。 |
src/config | 使用 Zod 解析和验证服务器专用的环境变量。 |
tests/ | 针对工具、服务和安全性的单元测试与集成测试。 |
开发指南
开发指南和架构规则见 CLAUDE.md。简要说明:
- 处理器抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log记录日志,使用ctx.state存储数据 - 在
src/index.ts的createApp()数组中注册新工具 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出架构;绝不捏造缺失字段
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0——详情请参阅 LICENSE。
地图数据由 OpenStreetMap 贡献者提供,采用 Open Database License(ODbL)。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。