osm-mcp-server 完整使用文档

一、包基础概述

1. 核心定义

osm-mcp-server 是面向 OSM(OpenStreetMap,开源街道地图) 的 MCP(Model Context Protocol,模型上下文协议)服务端Python工具包,核心作用:

  1. 搭建本地/远程MCP地图服务,让大模型(Claude、GPT、本地LLM)直接读写、查询、解析OSM地图数据;
  2. 封装OSM底层API、PBF/XML地图文件解析、地理要素检索、路网分析;
  3. 标准化MCP通信协议,提供统一接口给AI模型调用地理空间能力;
  4. 支持矢量地图裁剪、POI检索、道路拓扑提取、坐标转换、OSM数据入库。

2. 核心功能分类

模块 功能说明
MCP服务模块 启动TCP/STDIO MCP服务,管理AI客户端连接、上下文会话、请求路由
OSM解析引擎 解析.osm/.osm.pbf/.osm.gz文件,提取Node/Way/Relation三大要素
地理查询API 按经纬度、边界框、标签(key=value)检索道路、建筑、商店、公交站点
空间计算工具 WGS84/UTM坐标互转、距离计算、多边形面积、路网连通性分析
OSM编辑接口 批量修改OSM标签、导出裁剪地图、生成简化矢量地图
数据持久化 对接SQLite/PostGIS,缓存OSM地图数据,加速重复查询

3. 适用场景

AI地图问答、本地离线OSM数据分析、自动驾驶路网提取、城市POI统计、GIS自动化脚本、LLM地理插件后端。

二、安装教程

环境前置要求

  1. Python ≥3.10(推荐3.11/3.12,低版本会缺失asyncio异步依赖)
  2. 系统依赖:
    • Windows:无需额外系统库
    • Linux:apt install libosmpbf-dev protobuf-compiler
    • MacOS:brew install osmpbf protobuf
  3. 配套依赖:pyosmium(OSM解析核心)、mcp(MCP协议标准库)、shapely(空间几何)、geopy(地理编码)

标准安装命令

方式1:pip正式版
pip install osm-mcp-server
方式2:源码最新开发版
git clone https://github.com/osm-mcp/osm-mcp-server.git
cd osm-mcp-server
pip install -r requirements.txt
pip install .
方式3:离线内网安装
  1. 下载whl包:pip download osm-mcp-server
  2. 内网离线部署:pip install *.whl --no-index

安装校验

import osm_mcp_server
print(osm_mcp_server.__version__)
# 输出版本号即安装成功

三、核心语法、类、参数全解析

3.1 顶层入口类 OSMMCPServer(服务启动核心)

构造函数语法
class OSMMCPServer(Server):
    def __init__(
        self,
        osm_data_path: str | Path,
        backend: Literal["pyosmium", "libosmpbf"] = "pyosmium",
        cache_db: str = ":memory:",
        max_conn: int = 10,
        bbox_limit: tuple[float, float, float, float] | None = None,
        enable_postgis: bool = False,
        log_level: Literal["DEBUG", "INFO", "WARN", "ERROR"] = "INFO"
    )
关键参数详解
参数 类型 默认值 说明
osm_data_path str/Path 必填 OSM地图文件路径,支持pbf/xml/gz,或OSM数据库路径
backend 枚举 pyosmium OSM解析后端;libosmpbf速度更快,适合超大地图
cache_db str :memory: 缓存数据库路径,填文件路径持久化缓存,内存模式重启丢失
max_conn int 10 MCP客户端最大并发连接数
bbox_limit 四元组 None 全局边界框限制 (min_lon, min_lat, max_lon, max_lat),超出范围不加载数据
enable_postgis bool False 是否启用PostGIS空间数据库,开启后支持百万级地图查询
log_level 枚举 INFO 日志输出等级,DEBUG输出完整请求/OSM要素详情
服务启动方法
  1. STDIO模式(对接本地AI客户端,如Claude Desktop)
async def start_stdio(self) -> None
  1. TCP网络模式(远程多AI客户端访问)
async def start_tcp(self, host: str = "127.0.0.1", port: int = 8787) -> None

3.2 内置工具函数(AI可直接调用的MCP工具)

包内置注册20+MCP工具,核心通用函数语法:

1. query_osm_by_bbox 边界框检索要素
async def query_osm_by_bbox(
    min_lon: float,
    min_lat: float,
    max_lon: float,
    max_lat: float,
    tags: dict | None = None,
    element_type: Literal["node", "way", "relation", "all"] = "all"
) -> list[dict]
  • tags:标签过滤,例{"shop":"supermarket"}只返回超市
  • 返回值:标准化JSON数组,包含坐标、标签、OSM ID、几何信息
2. get_road_network 提取路网拓扑
async def get_road_network(bbox: tuple, road_levels: list[str]) -> dict

road_levels可选:motorway/trunk/primary/secondary/residential

3. convert_coordinate 坐标转换
async def convert_coordinate(lon: float, lat: float, target_crs: str) -> tuple[float, float]

target_crs支持:EPSG:4326(WGS84)EPSG:32650(UTM)

4. export_cropped_osm 裁剪导出地图
async def export_cropped_osm(bbox: tuple, out_path: str, fmt: Literal["pbf", "xml"]) -> str

3.3 配置文件参数(osm_mcp_config.yaml)

可通过外部yaml配置替代代码传参,核心配置项:

server:
  mode: stdio # stdio/tcp
  tcp_port: 8787
  max_connections: 15
osm:
  data_file: "./china.pbf"
  global_bbox: [116.3,39.9,116.5,40.1]
cache:
  db_path: "./osm_cache.db"
  expire_hours: 24
postgis:
  enable: false
  dsn: "postgresql://user:pass@127.0.0.1:5432/osm_db"

四、8个完整可运行实际应用案例

案例1:STDIO本地MCP服务(对接Claude桌面)

需求:启动本地OSM MCP服务,让Claude直接查询城市POI

import asyncio
from osm_mcp_server import OSMMCPServer

async def main():
    # 初始化服务,加载北京区域OSM文件
    server = OSMMCPServer(
        osm_data_path="./beijing.pbf",
        cache_db="./cache_beijing.db",
        log_level="DEBUG"
    )
    # STDIO启动,AI客户端直接读取标准输入输出通信
    await server.start_stdio()

if __name__ == "__main__":
    asyncio.run(main())

使用:Claude Desktop配置mcp服务指向该脚本,对话中可直接提问“查询朝阳区所有便利店”。

案例2:TCP远程MCP地图服务(多LLM共享)

需求:局域网部署地图服务,多台机器GPT/本地大模型远程调用

import asyncio
from osm_mcp_server import OSMMCPServer

async def main():
    server = OSMMCPServer(
        osm_data_path="./country_china.pbf",
        backend="libosmpbf",
        max_conn=20
    )
    # 0.0.0.0监听所有局域网设备,端口8787
    await server.start_tcp(host="0.0.0.0", port=8787)

if __name__ == "__main__":
    asyncio.run(main())

客户端连接地址:tcp://192.168.1.100:8787

案例3:边界框批量检索城市所有写字楼POI

需求:代码直接调用内置查询工具,导出区域办公建筑列表

import asyncio
from osm_mcp_server import OSMMCPServer

async def query_office_buildings():
    server = OSMMCPServer(osm_data_path="./shanghai.pbf")
    # 上海静安区边界框
    bbox = (121.43, 31.21, 121.48, 31.24)
    min_lon, min_lat, max_lon, max_lat = bbox
    # 调用查询工具,过滤办公建筑标签
    office_list = await server.query_osm_by_bbox(
        min_lon=min_lon,
        min_lat=min_lat,
        max_lon=max_lon,
        max_lat=max_lat,
        tags={"building": "office"},
        element_type="way"
    )
    print(f"静安区写字楼总数:{len(office_list)}")
    # 打印前5条数据
    for item in office_list[:5]:
        print(f"OSM_ID:{item['id']}, 坐标:{item['center']}, 标签:{item['tags']}")

asyncio.run(query_office_buildings())

案例4:提取城市主干道路网,计算道路长度

需求:导出区域高速、主干道路网,统计总里程

import asyncio
from osm_mcp_server import OSMMCPServer

async def calc_road_total_length():
    server = OSMMCPServer(osm_data_path="./guangzhou.pbf")
    bbox = (113.2,23.0,113.4,23.2)
    road_data = await server.get_road_network(
        bbox=bbox,
        road_levels=["motorway", "trunk", "primary"]
    )
    total_km = road_data["total_length_km"]
    print(f"广州核心区主干道总长度:{total_km:.2f} km")
    # 输出单条道路明细
    for road in road_data["roads"][:3]:
        print(f"道路名称:{road['tags'].get('name','无名道路')},长度{road['length_km']:.2f}km")

asyncio.run(calc_road_total_length())

案例5:WGS84经纬度转UTM投影坐标(测绘场景)

需求:GIS测绘,转换OSM原始GPS坐标为平面UTM坐标用于距离测量

import asyncio
from osm_mcp_server import OSMMCPServer

async def coord_transform():
    server = OSMMCPServer(osm_data_path="./test.pbf")
    # 北京天安门经纬度
    lon, lat = 116.403874, 39.914885
    # 转换为UTM 50N投影
    x, y = await server.convert_coordinate(lon, lat, target_crs="EPSG:32650")
    print(f"UTM X:{x:.2f}, UTM Y:{y:.2f}")
    # 反向转回WGS84
    lon2, lat2 = await server.convert_coordinate(x, y, target_crs="EPSG:4326")
    print(f"还原经纬度:{lon2:.6f}, {lat2:.6f}")

asyncio.run(coord_transform())

案例6:裁剪局部地图导出独立pbf文件

需求:从全国大地图中裁剪城市片区,生成轻量化离线地图

import asyncio
from osm_mcp_server import OSMMCPServer
from pathlib import Path

async def crop_osm_file():
    server = OSMMCPServer(osm_data_path="./china_large.pbf")
    out_path = Path("./hangzhou_suburb.pbf")
    bbox = (120.0,30.2,120.3,30.4)
    # 裁剪并导出pbf格式地图
    result = await server.export_cropped_osm(
        bbox=bbox,
        out_path=str(out_path),
        fmt="pbf"
    )
    print(f"裁剪完成,文件路径:{result}")

asyncio.run(crop_osm_file())

案例7:对接PostGIS数据库,百万级OSM数据持久查询

需求:大规模城市规划分析,将OSM要素存入空间数据库加速查询

import asyncio
from osm_mcp_server import OSMMCPServer

async def postgis_osm_query():
    # 开启PostGIS后端
    server = OSMMCPServer(
        osm_data_path="./shenzhen_full.pbf",
        enable_postgis=True,
        cache_db="postgresql://postgres:123456@127.0.0.1:5432/osm_db"
    )
    # 查询所有地铁站点
    subway_stations = await server.query_osm_by_bbox(
        113.8,22.4,114.2,22.6,
        tags={"railway": "station", "subway": "yes"}
    )
    print(f"深圳地铁站数量:{len(subway_stations)}")

asyncio.run(postgis_osm_query())

案例8:AI自动化脚本,批量统计各类生活配套POI

需求:循环查询超市、学校、医院、停车场,生成城市配套统计表

import asyncio
from osm_mcp_server import OSMMCPServer

async def stat_city_facility():
    server = OSMMCPServer(osm_data_path="./chengdu.pbf")
    city_bbox = (104.05,30.55,104.12,30.62)
    min_lon,min_lat,max_lon,max_lat = city_bbox
    # 定义需要统计的设施标签
    facility_tags = [
        ("超市", {"shop":"supermarket"}),
        ("小学", {"amenity":"school", "school:type":"primary"}),
        ("医院", {"amenity":"hospital"}),
        ("停车场", {"amenity":"parking"})
    ]
    stat_result = {}
    for name, tag in facility_tags:
        data = await server.query_osm_by_bbox(min_lon,min_lat,max_lon,max_lat,tags=tag)
        stat_result[name] = len(data)
    # 输出统计报表
    print("成都主城区配套设施统计:")
    for k,v in stat_result.items():
        print(f"{k}{v}个")

asyncio.run(stat_city_facility())

五、常见错误、报错解决方案

1. 安装阶段报错

报错1:ModuleNotFoundError: No module named 'pyosmium'

原因:依赖未自动安装,网络缺失编译包
解决:

# Linux/Mac
apt install libosmpbf-dev && pip install pyosmium
# Windows
pip install pyosmium-bin
报错2:protobuf编译失败 error: protobuf compiler not found

解决:安装系统protobuf工具,再重装包

# Ubuntu
apt install protobuf-compiler
# Mac
brew install protobuf
pip install osm-mcp-server --force-reinstall

2. 服务启动运行时错误

报错3:OSMFileLoadError: Failed to parse .pbf file

原因1:地图文件损坏、下载不完整;原因2:文件路径含中文/空格
解决:

  1. 重新下载OSM pbf地图;
  2. 修改文件路径为纯英文无空格;
  3. 切换backend="libosmpbf"解析大文件。
报错4:OSError: address already in use port 8787

原因:TCP端口被占用
解决:更换端口 start_tcp(port=8788),或杀死占用端口进程。

报错5:MaxConnectionError: reach max_conn limit 10

原因:并发MCP客户端超过最大连接数
解决:初始化服务时调高max_conn=30

3. 查询工具调用报错

报错6:BBoxRangeError: longitude out of [-180,180]

原因:传入的经纬度数值非法(超出全球坐标范围)
解决:校验边界框参数,经度-180180,纬度-9090。

报错7:PostGISConnectError: could not connect to postgres

原因:PostGIS地址、账号密码错误,数据库未创建
解决:检查dsn连接字符串,提前创建osm数据库并启用postgis扩展。

报错8:TagFilterWarning: empty tags dict returns all elements

非崩溃警告:未传入tags参数会返回区域全部要素,数据量大卡顿
解决:查询时必须指定业务标签过滤,缩小返回数据量。

4. 异步运行报错

报错9:RuntimeError: asyncio.run() cannot be called from a running event loop

原因:嵌套异步循环(Jupyter/异步web框架中直接运行脚本)
解决:Jupyter使用await main(),不要套asyncio.run()。

六、使用注意事项与性能优化

1. 地图文件性能规范

  1. 超大地图(>5GB全国pbf)必须使用backend="libosmpbf",解析速度提升3~5倍;
  2. 生产环境不要使用:memory:缓存,配置本地sqlite持久缓存cache_db="./osm_cache.db"
  3. 全局限定bbox_limit,避免加载全球全部要素造成内存溢出。

2. MCP服务部署规范

  1. 本地AI客户端(Claude Desktop/Ollama)使用stdio模式,轻量化无端口占用;
  2. 多客户端共享地图数据使用tcp模式,设置合理max_conn
  3. 公网暴露TCP服务时增加鉴权(包支持token参数,生产环境必须开启)。

3. 内存与资源管控

  1. 单次query_osm_by_bbox不要跨超大区域(如全省),会一次性加载数十万要素;
  2. 批量统计场景拆分小边界框循环查询,降低单次内存占用;
  3. 长期运行服务定时调用内置server.clear_cache()释放缓存内存。

4. 兼容性注意

  1. Python3.9及以下不支持异步MCP协议,必须3.10+;
  2. Windows下libosmpbf后端兼容性差,Windows优先使用pyosmium;
  3. OSM旧版.osmxml文件解析效率远低于pbf,生产统一使用pbf格式。

5. 业务使用避坑

  1. OSM道路way要素是线段集合,获取中心点使用工具内置center字段,不要手动计算;
  2. 标签key/value区分大小写,shop=Supermarketshop=supermarket是两种标签;
  3. 离线地图无实时更新,如需最新OSM数据需每日重新下载pbf文件。

《动手学PyTorch建模与应用:从深度学习到大模型》是一本从零基础上手深度学习和大模型的PyTorch实战指南。全书共11章,前6章涵盖深度学习基础,包括张量运算、神经网络原理、数据预处理及卷积神经网络等;后5章进阶探讨图像、文本、音频建模技术,并结合Transformer架构解析大语言模型的开发实践。书中通过房价预测、图像分类等案例讲解模型构建方法,每章附有动手练习题,帮助读者巩固实战能力。内容兼顾数学原理与工程实现,适配PyTorch框架最新技术发展趋势。
在这里插入图片描述

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐