关于 mapsql-mcp
mapsql-mcp 是面向使用 PostGIS 或 Oracle Spatial 的 GIS 开发者、分析师和研究人员的 MCP 服务。它提供空间查询工具并将结果呈现为地图,同时通过只读事务、行数上限和超时机制约束查询。
主要功能
- 01支持 PostGIS 和 Oracle Spatial
- 02提供常用空间分析工具
- 03输出地图图像和 Leaflet 交互地图
- 04只读查询并限制行数和时长
- 05支持 SQL 查询与图层发现
适用场景
- 01按米制距离查找附近要素
- 02比较并映射各街区的数量
- 03查找距某坐标最近的医院
MCP 相关
向 MCP 客户端提供空间数据库发现、查询、分析和地图渲染工具。支持 stdio 和 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
14收录的工具列表 · 更新于 4 天前
此工具无需参数。
详细介绍
mapsql-mcp
用自然语言提问 PostGIS 或 Oracle Spatial 数据库,并以地图形式获取答案。
mapsql-mcp 是一个 Model Context Protocol 服务,可让 AI 助手
(Claude Desktop、Claude Code、Cursor 及其他任何 MCP 客户端)安全地探索、查询和分析 PostGIS 或
Oracle Spatial(SDO_GEOMETRY)数据库,并在聊天中直接通过地图呈现答案。

“Kızılay 广场 500 m 内有哪些药店?”——模型会发现图层,调用
within_distance(测地距离,单位为米,不受表的 SRID 影响),然后调用render_map。上方图片就是在捆绑的演示数据库上调用这两个工具后生成的实际输出。

此 GIF 由 scripts/make_demo_video.py 根据演示数据库(PostGIS 和 Oracle)上的实际工具输出生成。
土耳其语:使用指南见下文 · 适用对象 / 分步指南:使用方法
为什么还需要另一个 PostGIS / Postgres / Oracle MCP 服务?
通用的 Postgres 或 Oracle MCP 服务不具备空间感知能力:模型必须手动编写 PostGIS / SDO_* SQL,容易在 SRID、geography 类型转换、单位以及 ST_DWithin / SDO_WITHIN_DISTANCE 参数上出错,而且无法展示结果。mapsql-mcp 围绕三个理念构建:
- 从设计上确保安全。 每个查询都会经过解析(PostgreSQL 使用真正的 PostgreSQL 解析器;Oracle 使用 Oracle 模式下的
sqlglot),并在带有超时和行数上限的READ ONLY事务中运行;机密信息绝不会传给模型。除非你提出要求,否则写入功能默认关闭(仅限 PostGIS)。 - 使用空间工具,而不是猜测 SQL。
within_distance、nearest、buffer、spatial_filter、spatial_join、aggregate、bbox_of……会处理 SRID、度量单位和索引问题;两个数据库提供相同的 14 种工具。普通的run_sql也仍然可用。 - 答案以地图呈现。
render_map会以 MCP 图像内容的形式返回 PNG(OpenStreetMap 底图、分级统计图、标签),也可以生成交互式 Leaflet HTML 文件。
此外,模型会被告知要先询问,而不是猜测:服务说明、提示词和工具本身都会拒绝处理“附近有哪些药店”(附近什么地方?)这类问题,或与十个地理要素都匹配的地名。
快速入门
需要 Python 3.10+ 和一个 PostGIS 或 Oracle Spatial 数据库。请使用只读数据库角色 / 用户(参见 SECURITY.md)。系统会根据连接字符串选择后端。
pip install mapsql-mcp # or: pipx install mapsql-mcp | uvx mapsql-mcp
export DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis
mapsql-mcp --check # prints PostgreSQL/PostGIS versions and exits
# Oracle Spatial instead (python-oracledb thin mode: no Oracle Client install needed) - see "Oracle Spatial" below
pip install "mapsql-mcp[oracle]"
export DATABASE_URL="oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1"
mapsql-mcp --check
Claude Desktop
编辑 claude_desktop_config.json(macOS:~/Library/Application Support/Claude/;Windows:%APPDATA%\Claude\):
{
"mcpServers": {
"postgis": {
"command": "uvx",
"args": ["mapsql-mcp"],
"env": { "DATABASE_URL": "postgresql://readonly:secret@localhost:5432/gis" }
}
}
}
Claude Code
claude mcp add postgis -e DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis -- uvx mapsql-mcp
Cursor(.cursor/mcp.json)/ Windsurf
{
"mcpServers": {
"postgis": {
"command": "uvx",
"args": ["mapsql-mcp", "--schemas", "public,osm"],
"env": { "DATABASE_URL": "postgresql://readonly:secret@localhost:5432/gis" }
}
}
}
VS Code(.vscode/mcp.json,Agent 模式下的 Copilot Chat)
VS Code 使用 servers 键,并且可以提示输入密码,而不是将密码存储在文件中:
{
"inputs": [
{ "id": "pg-url", "type": "promptString", "description": "PostGIS connection URL", "password": true }
],
"servers": {
"postgis": {
"type": "stdio",
"command": "uvx",
"args": ["mapsql-mcp", "--schemas", "public,osm"],
"env": { "DATABASE_URL": "${input:pg-url}" }
}
}
}
其他 MCP 客户端(兼容 ChatGPT,远程)
运行 streamable-HTTP 传输,并将客户端指向 http://127.0.0.1:8000/mcp:
mapsql-mcp --transport streamable-http --host 127.0.0.1 --port 8000
HTTP 传输没有身份验证:请将其限制在回环地址,或置于你自己的身份验证反向代理/隧道之后。如果你是从克隆的仓库安装,请使用 "command": "python", "args": ["-m", "mapsql_mcp"]。
使用步骤
适用对象。 已经在使用 AI 助手(Claude Code、Claude Desktop、Cursor、VS Code + Copilot),并在 PostGIS 或 Oracle Spatial 中存有空间数据的 GIS 开发者、数据库从业者、分析师和研究人员。它是构建助手的基础组件,而非面向最终用户的应用:它没有自己的 Web UI,聊天窗口就是 UI。
1. 安装:
pipx install "mapsql-mcp[oracle]" # or: pip install "mapsql-mcp[oracle]"
2. 使用只读用户连接数据库并检查连接:
export DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis # or oracle://USER:PASS@host:1521/service
mapsql-mcp --check
手头没有数据库?只需两分钟即可构建随附的演示数据库(Natural Earth + OpenStreetMap Ankara),请参见下一节。
3. 在助手中注册。 将 快速入门中的一个 JSON 配置块放入客户端配置文件
(Claude Code 使用 .mcp.json,VS Code 使用 .vscode/mcp.json,Cursor 使用 .cursor/mcp.json,Claude Desktop 使用 claude_desktop_config.json)。在 VS Code 中,点击服务条目上方的 Start;在 Claude Code 中,运行 /mcp 并确认其显示为已连接。你应该能看到 14 个工具。
4. 用自然语言提问。 例如:
- “有哪些图层?请总结一下。”
- “距离 Kızılay(39.9208, 32.8541)500 m 范围内有哪些药店?请在地图上显示。”
- “哪个街区的咖啡馆最多?请按数量为街区着色。”
- “距离这个点最近的 5 家医院,并显示距离。”
- “查找附近的药店。”——好的助手会询问附近什么位置?,而不是自行猜测。
5. 查看地图。 render_map 会将 PNG 返回给助手并保存到 ~/mapsql-mcp-output 下(也可选择生成交互式 Leaflet HTML)。有些客户端(例如 VS Code 中的 Claude Code 面板)不会向你显示工具生成的图片;将 MAPSQL_OPEN_MAPS=1(或 --open-maps)添加到服务的 env 中,即可在默认查看器中打开每张地图。
须知。 助手所用的服务提供商(Anthropic、OpenAI 等)会接收工具返回的行数据,因此请勿连接内容不得离开组织的数据库;使用 --schemas / --layers 仅公开所需数据,并确保数据库用户为只读。
使用演示数据库试用(2 分钟)
演示数据包括 Natural Earth(世界各国、各省、城市、河流和湖泊,属于公有领域),以及 OpenStreetMap 的安卡拉市中心提取数据(兴趣点、道路、公园、105 个街区,遵循 ODbL)。demo/data 中附带了固定版本的快照(2.8 MB),因此可离线构建。
docker run -d --name pg -p 55432:5432 -e POSTGRES_PASSWORD=pw postgis/postgis:16-3.4
pip install -e .
python demo/build_demo_db.py --database-url postgresql://postgres:pw@localhost:55432/postgres
export DATABASE_URL=postgresql://postgres:pw@localhost:55432/postgres
然后向助手提问,例如:
- “有哪些图层?请总结一下安卡拉的数据。”
- “哪个街区的药店最多?请用地图显示。”
- “Kızılay(纬度 39.9208,经度 32.8541)300 m 范围内的咖啡馆,请在地图上显示。”
- “查找附近的药店。” → 它应该先询问位置。
各街区咖啡馆数量(spatial_join + 分级统计地图) | 最近的 5 家医院(nearest) |
|---|---|
![]() | ![]() |
地图数据 © OpenStreetMap 贡献者(ODbL)。 其中两个地图的交互版本:docs/images/*.html(在浏览器中打开)。
Oracle Spatial
v0.2 新增:在 Oracle Database with Spatial(19c、21c、23ai /
26ai、Autonomous Database 等)上也能使用相同的工具、相同的安全模型和相同的地图,通过 thin 模式下的 python-oracledb 实现(无需 Oracle Client 库)。

与 PostGIS 上的问题相同,答案也相同(20 家药店)——这次通过 Autonomous Database 上的 SDO_WITHIN_DISTANCE(... 'distance=500 unit=M') 查询得出。地图数据 (c) OpenStreetMap contributors (ODbL)。
安装和连接
pip install "mapsql-mcp[oracle]" # adds oracledb + sqlglot
| 变量 | 含义 |
|---|---|
DATABASE_URL=oracle://USER:PASS@host:1521/service_name | 简便格式。密码中的特殊字符需进行百分号编码(@ -> %40)。TLS 连接请添加 ?protocol=tcps(或 ?tls=true);其他 ?key=value 参数会作为 Easy Connect 参数传递(例如 ssl_server_dn_match=yes)。 |
MAPSQL_ORACLE_DSN + MAPSQL_ORACLE_USER + MAPSQL_ORACLE_PASSWORD | 用于较长的 TNS 描述符、tcps://host:1522/service 字符串或 tnsnames.ora 别名(需使用 TNS_ADMIN)。DSN 会覆盖 oracle:// URL 中的主机部分;此处提供的用户名和密码会覆盖 URL 中的用户名和密码。将密码从 URL 中移出可避免引号问题。 |
MAPSQL_ORACLE_WALLET_DIR、MAPSQL_ORACLE_WALLET_PASSWORD | 仅用于双向 TLS(wallet)连接,例如要求使用“mTLS”的 Autonomous Database。 |
MAPSQL_BACKEND=postgis|oracle / --backend | 强制指定后端。默认值:根据 DATABASE_URL 的方案检测,或仅设置 MAPSQL_ORACLE_DSN 时使用 Oracle。 |
其他所有设置(MAPSQL_SCHEMAS、MAPSQL_LAYERS、MAPSQL_STATEMENT_TIMEOUT_MS、MAPSQL_MAX_ROWS 等)均保持不变;
超时会作为连接的 call_timeout 应用,架构对应 Oracle 的所有者。
Autonomous Database(TLS,无 wallet)。 在控制台中打开 Database connection,选择 TLS authentication: TLS(而不是 mTLS;需要为你的地址设置访问控制列表/允许的 IP),然后复制 Low/Medium 连接字符串。描述符如下所示:(description=(address=(protocol=tcps)(port=1522)(host=...))(connect_data=(service_name=...))(security=(ssl_server_dn_match=yes)));
将其放入 MAPSQL_ORACLE_DSN(描述符很长且包含括号,不适合放入 URL)。服务器证书会根据操作系统的信任存储进行验证。请使用专用的只读用户,切勿使用 ADMIN。
export MAPSQL_ORACLE_DSN='(description=(retry_count=3)(address=(protocol=tcps)(port=1522)(host=adb.<region>.oraclecloud.com))(connect_data=(service_name=xxxx_mydb_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))'
export MAPSQL_ORACLE_USER=MAPSQL_RO MAPSQL_ORACLE_PASSWORD='...'
mapsql-mcp --check
只读用户
scripts/oracle_readonly_user.sql 是 Oracle 版的 readonly_role.sql:该用户仅具有 CREATE SESSION,以及对助手可访问表的 SELECT 权限。空间元数据视图、MDSYS.CS_SRS 和 SDO_* 运算符对所有用户均可用,因此无需其他权限。
Claude Desktop / Claude Code / Cursor / VS Code
{
"mcpServers": {
"oracle-spatial": {
"command": "uvx",
"args": ["--from", "mapsql-mcp[oracle]", "mapsql-mcp", "--schemas", "GIS"],
"env": { "DATABASE_URL": "oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1" }
}
}
}
claude mcp add oracle-spatial -e DATABASE_URL=oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1 -- uvx --from "mapsql-mcp[oracle]" mapsql-mcp --schemas GIS
VS Code(.vscode/mcp.json)——密码会在提示时输入,不会存储在文件中;TNS 描述符放入 MAPSQL_ORACLE_DSN:
{
"inputs": [
{ "id": "ora-pw", "type": "promptString", "description": "Oracle password for MAPSQL_RO", "password": true }
],
"servers": {
"oracle-spatial": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "mapsql-mcp[oracle]", "mapsql-mcp", "--schemas", "GIS", "--no-basemap"],
"env": {
"MAPSQL_ORACLE_DSN": "dbhost:1521/ORCLPDB1",
"MAPSQL_ORACLE_USER": "MAPSQL_RO",
"MAPSQL_ORACLE_PASSWORD": "${input:ora-pw}"
}
}
}
}
Oracle 演示架构(3 分钟)
scripts/oracle_demo_db.py 会将与 PostGIS 演示相同的 Natural Earth + OpenStreetMap-Ankara 数据加载到架构
MAPSQL_DEMO(WORLD_COUNTRIES、WORLD_CITIES、ANKARA_POIS、ANKARA_NEIGHBOURHOODS 等——Oracle 没有类似 world.countries 的数据库内架构约定,
因此 PostGIS 架构会变成表名前缀),注册 USER_SDO_GEOM_METADATA,构建空间索引,
添加两个 Ankara 图层的 **TUREF TM30(EPSG:5254,米)**副本,以演示投影坐标系,并创建
只读用户 MAPSQL_RO。它需要在被 git 忽略的 ini 文件中配置管理员登录信息:
; oracle-test.ini
[oracle]
user = ADMIN
password = ...
dsn = (description=...) ; or host:1521/service
python scripts/oracle_demo_db.py # creates MAPSQL_DEMO + MAPSQL_RO (random passwords are written to the same ini file)
python scripts/make_oracle_demo_maps.py --ini oracle-test.ini # the maps in docs/images/oracle_*.png
各街区的咖啡馆数量(spatial_join + 分级统计图) | 投影图层:TUREF TM30,SRID 5254 |
|---|---|
![]() | ![]() |
各工具与 Oracle Spatial 的对应关系
| 工具 | Oracle 实现 |
|---|---|
list_layers / describe_layer | ALL_SDO_GEOM_METADATA(以及可访问表/视图中未注册的 SDO_GEOMETRY 列)、SRID、容差、来自 SDO_GTYPE 的几何类型、来自 ALL_INDEXES 的空间索引是否存在/有效、来自 MDSYS.SDO_COORD_REF_SYS / CS_SRS 的 CRS 类型/名称 |
within_distance | SDO_WITHIN_DISTANCE(geom, ref, 'distance=N unit=M'),距离通过 SDO_GEOM.SDO_DISTANCE(..., 'unit=M') 计算 |
nearest | SDO_NN + SDO_NN_DISTANCE(存在属性筛选条件时使用 sdo_batch_size,以便在邻居流出时应用筛选条件) |
buffer | SDO_GEOM.SDO_BUFFER(..., 'unit=M arc_tolerance=...'),使用 SDO_AGGR_UNION 融合,使用 SDO_AREA(..., 'unit=SQ_KM') 计算面积 |
spatial_filter / spatial_join | SDO_RELATE 掩码(ANYINTERACT、INSIDE+COVEREDBY+EQUAL、CONTAINS+COVERS+EQUAL、TOUCH、OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT),dwithin 使用 SDO_WITHIN_DISTANCE;连接以基于集合的空间连接方式执行,并按 ROWID 分组 |
bbox_of | 对经过 SDO_CS.TRANSFORM(geom, 4326) 转换的几何使用 SDO_AGGR_MBR |
aggregate | SDO_GEOM.SDO_AREA(... 'unit=SQ_KM') / SDO_LENGTH(... 'unit=KM') |
| GeoJSON | 对经过 SDO_CS.TRANSFORM(geom, 4326) 转换的几何调用 SDO_UTIL.TO_GEOJSON;在 Python 中进行简化/取整 |
run_sql | 受保护的 Oracle SQL;每个 SDO_GEOMETRY 列都会以 GeoJSON(WGS84)形式返回 |
对于大地测量图层(EPSG:4326 和 Oracle 旧版 SRID 8307:基于椭球体测地线计算)以及投影图层
(在投影坐标系中进行平面计算,并使用 unit=M 转换),米制距离都准确无误。值始终使用绑定变量;标识符取自目录。
与 PostGIS 的差异须知
SDO_*运算符需要空间索引。 没有有效空间索引的图层会通过不使用索引的SDO_GEOM.*函数进行查询(响应中会标明,且describe_layer会发出警告)。创建索引(CREATE INDEX ... INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2),并在USER_SDO_GEOM_METADATA中注册图层,以提升速度。crosses没有与之完全对应的 Oracle 掩码:spatial_filter会拒绝处理并说明原因,而不是返回可能错误的结果(可改用intersects/touches/overlaps,或使用run_sql配合自定义的SDO_RELATE掩码)。within/contains包含边界接触(COVEREDBY/COVERS)和EQUAL;overlaps对应OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT。- 此版本的 Oracle 不支持写入模式(启动时会拒绝
--allow-write)。 - 对于普通的大写 Oracle 名称,标识符会以小写形式显示(
mapsql_demo.ankara_pois,列name);在 SQL 中无需加引号即可使用。带引号的混合大小写名称会按原样显示,并且在run_sql中必须加引号。 - Oracle 会将空字符串存储为
NULL。EQ ''筛选条件会转换为IS NULL。 - 与 PostGIS 相比,存在细微的数值差异(在演示数据上进行过检查):大地测量图层的距离差异在 0.1 m 以内;面积/长度差异约在 0.01 % 以内;多边形上的
dwithin连接结果在边界处可能相差一个要素;缓冲区的面积会因多边形近似而有所不同。投影图层上的距离是在该投影下计算的平面距离(在中央子午线附近,TM30 与测地距离每公里相差约 1 m 以内)。 - GeoJSON 转换不支持圆弧/复合曲线(投影数据的缓冲区会先进行加密);如果 Oracle 无法序列化某种几何体,工具会因明确的数据库错误而失败。
list_layers使用SDO_AGGR_MBR报告范围(超过 500 000 行的图层会跳过);SDO_TUNE.EXTENT_OF无法在READ ONLY事务中运行。
工具
| 工具 | 功能 |
|---|---|
server_info | 数据库 / PostGIS 或 Oracle Spatial 版本、后端、模式、限制、允许列表 |
list_layers | 空间图层及其几何类型、SRID、行数估算、范围、列(可搜索) |
describe_layer | 列 / 类型、精确行数和范围、文本列的常见值、数值范围 |
sample_features | 若干真实要素 |
find_features | 属性筛选(= != < > like ilike contains in between is_null 等)、排序、列选择 |
within_distance | 距离某个经纬度坐标或其他要素 N 米范围内的要素;经纬度数据使用大地测量距离,公制 CRS 使用平面距离,英尺等单位会进行换算;添加 distance_m |
nearest | k 个最近邻,包含 distance_m(大型表使用 GiST KNN 预选) |
buffer | 对点或(经筛选的)图层创建大地测量缓冲区,可选溶解,并包含 area_km2 |
spatial_filter | 与另一个图层、bbox 或 GeoJSON 几何执行相交 / 位于内部 / 包含 / 接触 / 交叉 / 重叠 / 不相交筛选 |
aggregate | 计数、去重计数、求和、平均值、最小值、最大值、大地测量 area_km2 / length_km,支持分组 |
spatial_join | 对每个左侧要素,统计 / 求和 / 求平均 / 附加相关右侧要素(intersects、within、contains、dwithin) |
bbox_of | 图层或子集的边界框和中心点 |
run_sql | 受限的只读 SQL(PostgreSQL 或 Oracle 方言);几何列以 GeoJSON 格式返回 |
render_map | PNG 地图,作为 MCP 图像内容返回(并保存文件);可选 Leaflet HTML;图层来自 result_id、GeoJSON 或 SQL;支持标签和分级统计图(value_property) |
execute_sql | 仅限使用 --allow-write 时,且仅支持 PostGIS:一条 INSERT / UPDATE / DELETE(必须有 WHERE)/ CREATE TABLE|INDEX|VIEW / ALTER TABLE ADD COLUMN |
所有坐标均为 WGS84 经纬度;距离单位为米;面积单位为 km²。每个返回几何的工具都会将完整(简化后)结果存储在服务端,并返回一个 result_id,因此 render_map(result_ids=[...]) 无需模型来回传大型 GeoJSON。响应会保持精简:顶点数超过预算的几何会以代表点返回(并附带说明),除非你请求 geometry="full"。
提示词:gis_assistant、spatial_question、explore_database。资源:mapsql://guide、mapsql://layers。
有疑问就问,不要猜测
如果 within_distance 未提供点或参考要素,它不会猜测位置;而是报错:"Missing reference: near WHAT? ... ask them"。如果某个参考对象匹配多个要素,则会返回候选项并询问你指的是哪一个。缺少距离、图层名称不明确、数值筛选条件却给了文本、经纬度颠倒等情况也一样。连接时发送的服务端指令会告知模型先提出一个简短的澄清问题。这项设计源于作者的 TR-CBS-Komut 基准测试:在识别信息缺失方面,不同模型的表现从 0% 到 98% 不等。
安全模型
纵深防御——不信任任何单一层(完整威胁模型请参阅 SECURITY.md):
| 层 | 功能 |
|---|---|
| SQL 解析 | PostgreSQL:使用 pglast(实际的 PostgreSQL 解析器)。Oracle:使用 sqlglot(Oracle 方言)和独立的令牌扫描——只允许恰好一条语句,且只能是普通的 SELECT/WITH/集合运算;拒绝 DML/DDL/MERGE、PL/SQL 块、EXECUTE IMMEDIATE、FOR UPDATE、数据库链接(@)、DBMS_*/UTL_*/CTX_* 包、SYS/DBA_*/V$* 对象、序列、URL/XML 函数;无法解析的内容一律拒绝(参阅 SECURITY.md)。PostgreSQL 详情:只允许恰好一条语句,且必须是普通的 SELECT(CTE/UNION/VALUES 均可)。拒绝 DDL/DML/COPY/DO/SET/事务控制、SELECT INTO、FOR UPDATE、修改数据的 CTE、pg_read_file、lo_*、dblink*、pg_sleep、set_config、nextval、query_to_xml、除少量无害函数外的所有 pg_* 函数,以及凭据/活动相关关系(pg_authid、pg_shadow、pg_stat_activity、pg_settings 等)。540 多个测试用例。 |
| 只读事务 | PostgreSQL:每条查询都在 BEGIN READ ONLY 事务中运行,并设置 statement_timeout 和 lock_timeout,最后始终回滚;如果 SELECT my_volatile_function() 尝试执行 INSERT,PostgreSQL 会阻止它(已测试)。Oracle:使用 SET TRANSACTION READ ONLY 和 call_timeout,最后始终回滚(写入会触发 ORA-01456,已使用具备写入权限的用户测试)。 |
| 行数上限 | 服务端游标 / FETCH FIRST 加硬性上限(MAPSQL_MAX_ROWS,默认值为 5000);服务端绝不会将庞大的结果集全部载入内存。 |
| 允许列表 | --schemas public,osm 和/或 --layers 'osm.*,public.cities':在所有位置(目录工具、SQL 防护、search_path)中隐藏未允许的内容。 |
| 输出中不包含机密信息 | 错误信息会改写为主要消息;DSN、密码和主机信息会被清除;绝不会返回连接字符串。 |
| 默认禁用写入 | --allow-write 会添加一个独立工具,并采用范围窄得多的防护(禁止 DROP/TRUNCATE/GRANT,且不允许不带 WHERE 的 UPDATE/DELETE)。 |
| 数据库角色 | 最强的一层:使用仅对助手可见内容拥有 SELECT 权限的角色/用户连接(scripts/readonly_role.sql、scripts/oracle_readonly_user.sql)。 |
配置
| 环境变量 | CLI 标志 | 默认值 | 含义 |
|---|---|---|---|
DATABASE_URL | (--database-url,请避免使用) | 必填 | postgresql://... 或 oracle://USER:PASS@host:1521/service_name |
MAPSQL_ORACLE_DSN、MAPSQL_ORACLE_USER、MAPSQL_ORACLE_PASSWORD | Oracle:DSN / TNS 描述符和凭据(URL 的替代方案) | ||
MAPSQL_ORACLE_WALLET_DIR、MAPSQL_ORACLE_WALLET_PASSWORD | Oracle:mTLS wallet(可选) | ||
MAPSQL_BACKEND | --backend | auto | postgis 或 oracle |
MAPSQL_SCHEMAS | --schemas | all | 以逗号分隔的架构允许列表(Oracle:所有者) |
MAPSQL_LAYERS | --layers | all | 以逗号分隔的表 / 图层模式(schema.table、schema.*、table) |
MAPSQL_STATEMENT_TIMEOUT_MS | --statement-timeout-ms | 15000 | 每次查询的超时时间 |
MAPSQL_MAX_ROWS / MAPSQL_DEFAULT_LIMIT | --max-rows | 5000 / 100 | 行数上限 / 默认 limit |
MAPSQL_ALLOW_WRITE | --allow-write | off | 启用 execute_sql(仅限 PostGIS) |
MAPSQL_BASEMAP | --no-basemap | osm | osm、none,或包含 {z}/{x}/{y} 的瓦片 URL 模板 |
MAPSQL_OUTPUT_DIR | --output-dir | ~/mapsql-mcp-output | render_map 保存 PNG/HTML 的位置(含瓦片缓存) |
MAPSQL_OPEN_MAPS | --open-maps | off | 在默认查看器中打开每张渲染出的地图(本地使用;适用于 Claude Code VS Code 面板等不显示工具图像的客户端) |
MAPSQL_LOG_LEVEL | WARNING | 日志仅输出到 stderr |
底图瓦片来自 tile.openstreetmap.org,并带有署名、描述性 User-Agent、每张地图最多 16 块瓦片的限制,以及磁盘缓存。请遵守 OSM 瓦片使用政策;如需大量使用,请将 MAPSQL_BASEMAP 指向自己的瓦片服务,或使用 none(完全离线可用)。
基准测试:mapsql-bench
bench/ 提供针对演示数据库的 60 个英文 GIS 问题(52 个可回答问题 + 8 个必须以澄清问题作答的问题),分为 8 个类别(属性、距离、空间、聚合、联接、缓冲区、边界框、歧义);答案由手写 SQL 计算得出。它还附带一个运行器,可在 Agent 循环中评估任意兼容 OpenAI 的模型(OpenAI、OpenRouter、vLLM、Ollama、LM Studio……);该循环通过 stdio 调用此服务的工具:
python bench/run_bench.py --oracle # no LLM: replays one reference tool call per question
python bench/run_bench.py --validate-gold # re-checks gold answers against the database
python bench/run_bench.py --model gpt-4o-mini --api-key-env OPENAI_API_KEY
python bench/run_bench.py --model qwen2.5:7b --base-url http://localhost:11434/v1
评分方式:数值允许在容差范围内,名称按不区分大小写和重音符号的集合进行比较;对于歧义问题,模型必须以 CLARIFY: 而非 ANSWER: 结尾。目前的验证结果(v0.1):标准答案与数据库一致(52/52),且工具集能够表达所有可回答问题(oracle 52/52)。目前尚未公布任何 LLM 结果——测试框架已就绪;非常欢迎提交 PR,将模型结果添加到 bench/RESULTS.md。
限制(v0.2)
- 支持 PostGIS 或 Oracle Spatial(每个服务使用一个数据库);支持表、视图、物化视图和外部表中的
geometry/geography列(PostGIS)或SDO_GEOMETRY列(Oracle)。Oracle 特殊说明:请参阅与 PostGIS 的差异(仅只读、不支持crosses,无索引时回退处理)。 - 结构化工具不支持栅格、拓扑或 3D(
run_sql仍可查询这些数据)。 - 底图需要联网(无法获取时会优雅回退为纯色背景),且仅支持 OSM 风格的栅格瓦片。
render_map为每个图层绘制一种纯色,并支持单变量分级设色图;暂不支持自定义样式。- HTTP 传输没有身份验证;
execute_sql有意仅提供范围很小的写入功能。 - 跨 CRS 联接会转换左侧几何;非常大型的跨 SRID
dwithin联接可能会很慢。 - 已使用 PostgreSQL 18 / PostGIS 3.6 和 Oracle Database 26ai(23.26、Spatial 23.7、Autonomous Database Always Free),以及
mcp1.30 和 2.3 进行测试(代码同时支持两个 SDK 版本);CI 使用 PostGIS 3.4 / PostgreSQL 16 运行测试,并运行 Oracle 防护测试(未提供凭据时,依赖数据库的 Oracle 测试会跳过)。
路线图
- v0.3:Oracle 写入模式(严格防护),Oracle
SDO_JOIN/Spatial Studio 扩展,HTTP 身份验证(Bearer 令牌),逐工具允许列表,矢量瓦片/PMTiles 底图,栅格/H3 汇总,一个explain工具,路由辅助工具(pgRouting),结果导出(GeoJSON/GeoPackage),更丰富的地图样式 - v0.4:多数据库配置,使用 MCP elicitation 澄清问题(而非纯文本提问),目录缓存选项
- 发布热门模型的基准测试结果 + 公共排行榜
开发
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
# a throwaway PostGIS (never point the tests at a database you care about):
docker run -d -p 55432:5432 -e POSTGRES_PASSWORD=pw -e POSTGRES_DB=mapsql_test postgis/postgis:16-3.4
export MAPSQL_TEST_DATABASE_URL=postgresql://postgres:pw@localhost:55432/mapsql_test
pytest # guard tests need no database; the rest recreate schemas `mt` and `mt_other`
当 oracle-test.ini([oracle_ro],见上文)或 MAPSQL_TEST_ORACLE_URL /
MAPSQL_TEST_ORACLE_DSN+_USER+_PASSWORD 可用,且已运行 scripts/oracle_demo_db.py 时,Oracle 测试(pytest -m oracle)会运行;否则会跳过。Oracle SQL 防护测试不需要数据库。
请参阅 CONTRIBUTING.md。用于本地集群的 Windows 辅助脚本:scripts/dev_cluster.ps1。
土耳其语
mapsql-mcp 是一款开源 MCP 服务,可让 AI 助手(Claude Desktop/Code、Cursor、兼容 ChatGPT 的 MCP 客户端)安全地查询 PostGIS 或 Oracle Spatial(v0.2)数据库、执行空间分析,并在聊天中将结果显示为地图。
- **安全优先:**每条查询都通过真正的 PostgreSQL 解析器(
pglast)验证;仅允许单条SELECT、READ ONLY事务,并设置超时和行数限制。禁止使用pg_read_file、COPY、dblink、lo_*等。默认禁用写入(--allow-write)。支持架构/图层允许列表(--schemas、--layers);密码和连接字符串不会泄露到输出中。 - 空间工具:
list_layers、describe_layer、within_distance(以米为单位,不受 SRID 影响)、nearest、buffer、spatial_filter、aggregate、spatial_join、bbox_of、run_sql和render_map(带 OSM 底图的 PNG + 可选交互式 Leaflet HTML、分级设色地图)。 - **遇到歧义时会提问:**对于“附近的药店”这类信息不完整的问题,模型不会自行猜测,而会询问“靠近什么?”(工具也会拒绝缺少必要输入的请求)。这是作者从 TR-CBS-Komut 基准测试中总结出的经验。
- 基准测试:
bench/目录下包含针对演示数据库的 60 个英文 GIS 问题(其中 8 个属于“应该提问”类型)、标准答案,以及可测试任何 OpenAI 兼容模型的运行器。
**Oracle Spatial:**运行 pip install "mapsql-mcp[oracle]",并设置 DATABASE_URL=oracle://KULLANICI:SIFRE@sunucu:1521/servis_adi(对于较长的 TNS 描述符,使用 MAPSQL_ORACLE_DSN + MAPSQL_ORACLE_USER + MAPSQL_ORACLE_PASSWORD)。提供相同的 14 个工具;在地理坐标(4326)和投影坐标图层(例如 TUREF TM30、EPSG:5254)中,使用 unit=M 可获得以米为单位的准确距离。查询通过 sqlglot(Oracle 方言)验证,建议使用 SET TRANSACTION READ ONLY 和只读用户(scripts/oracle_readonly_user.sql)。
详情:见上文 Oracle Spatial 部分。
适用对象?使用 AI 助手(Claude Code、Claude Desktop、Cursor、VS Code + Copilot),且空间数据存储在 PostGIS 或 Oracle Spatial 中的GIS 开发人员、数据库专家、分析师和研究人员。这不是面向终端用户的应用;它没有自己的界面,聊天窗口就是它的界面。
分步使用
1. 安装:
pipx install "mapsql-mcp[oracle]" # ya da: pip install "mapsql-mcp[oracle]"
2. 使用只读用户连接数据库并测试连接:
export DATABASE_URL=postgresql://salt_okunur:sifre@localhost:5432/cbs # ya da oracle://KULLANICI:SIFRE@sunucu:1521/servis
mapsql-mcp --check
只读用户脚本:scripts/readonly_role.sql(PostGIS)、scripts/oracle_readonly_user.sql(Oracle)。
如果您没有数据库,可通过上文的 Try it with the demo database 部分,在两分钟内搭建演示数据库
(Natural Earth + OpenStreetMap Ankara)。
3. 介绍给助手。 将 Quickstart 部分中的一个 JSON 示例放入客户端的设置文件:Claude Code
使用 .mcp.json,VS Code 使用 .vscode/mcp.json,Cursor 使用 .cursor/mcp.json,Claude Desktop 使用
claude_desktop_config.json。在 VS Code 中,点击服务上方的 Start;在 Claude Code 中,输入 /mcp 并
确认状态为 connected。应列出 14 个工具。
4. 用土耳其语提问。 示例:
- "有哪些图层?请概述。"
- "在地图上显示 Kızılay(39.9208, 32.8541)500 m 范围内的药店。"
- "哪个街区的咖啡馆最多?按咖啡馆数量给街区着色。"
- "列出距离此点最近的 5 家医院及其距离。"
- "查找附近的药店。" ——好的助手不会猜测,而是会询问 "靠近什么?"
5. 查看地图。 render_map 会将地图以 PNG 格式返回给助手,并保存到 ~/mapsql-mcp-output 文件夹
(也可选择生成交互式 Leaflet HTML)。有些客户端(例如 VS Code 中的 Claude Code 面板)不会向您显示工具生成的图片;在服务的 env 部分添加 MAPSQL_OPEN_MAPS=1(或 --open-maps),每张地图就会在默认查看器中打开。
请注意。 助手的提供商(Anthropic、OpenAI 等)可以看到工具返回的行。请勿连接包含不得离开机构的数据的数据库;使用 --schemas / --layers 仅启用所需图层,并确保数据库用户为只读。演示数据:Natural Earth(公有领域)和 OpenStreetMap(ODbL),详情见:
demo/ATTRIBUTION.md。
作者:Mehmet Veysel Delibaş,GIS 软件工程师(土耳其)。
许可与署名
代码:MIT © 2026 Mehmet Veysel Delibaş。演示数据:Natural Earth(公有领域)和 OpenStreetMap
(© OpenStreetMap 贡献者,ODbL);请参阅 demo/ATTRIBUTION.md。
使用 OSM 底图渲染的地图会包含所需的署名信息。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。



