Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

GeoOntology

БесплатноНе проверен

A geographic ontology layer MCP server that exposes hierarchical relations, topological adjacency, toponym disambiguation, spatial operations, and geo-constrain

GitHubEmbed

Описание

A geographic ontology layer MCP server that exposes hierarchical relations, topological adjacency, toponym disambiguation, spatial operations, and geo-constraint verification, enabling LLMs to reason with geographic structures instead of raw SQL.

README

地理本体层 MCP 服务器——让 LLM 用地理结构推理,而非裸 SQL。

为什么需要这个项目

现有 PostGIS MCP 服务器只暴露原始 SQL 查询能力。LLM 拿到的是行和列,不是"南京属于江苏"或"苏州与上海相邻"这样的地理结构知识。

GeoOntology-MCP 暴露的是地理本体层——层级关系、拓扑邻接、语义消歧、空间运算、属性对比,以及核心创新:地理约束校验。LLM 生成地理断言后,MCP 可以校验真伪并返回结构化纠错,驱动 LLM 自我修正。

LLM: "苏州与上海不相邻"
  → check_adjacency("320500", "310000")
  ← { valid: false, correction: "苏州市 与 上海市 相邻,共享边界 42.3km",
       evidence: { shared_boundary_length_km: 42.3 } }
LLM: "我修正之前的说法,苏州与上海实际上是相邻的……"

架构

LLM Client ──MCP Protocol──► GeoOntology-MCP (TypeScript)
                                    │
                          ┌─────────┴─────────┐
                          │  Ontology Engine    │
                          │  - 层级遍历 (KG)    │
                          │  - 拓扑查询 (PostGIS)│
                          │  - 约束校验 (两层)  │
                          │  - 空间运算 (PostGIS)│
                          │  - 路径搜索 (BFS)   │
                          └─────────┬─────────┘
                                    │
                      ┌─────────────┴─────────────┐
                      │                           │
              Knowledge Graph (内存)        PostGIS (持久化)
              - 46,413 节点               - boundary geometries
              - 44,956 BELONGS_TO 边      - admin_adjacency (预计算)
              - 地名/拼音/英文索引         - admin_containment (预计算)
                                          - admin_attributes (属性数据)

数据策略:知识图谱 JSON 在启动时加载到内存,处理所有层级关系和地名消歧(纯图遍历,O(depth));邻接关系通过 PostGIS ST_Touches 预计算后存入 admin_adjacency 表,查询时 O(1)。

工具一览(10 个)

查询类

工具 参数 说明
resolve_place name, context? 地名消歧,支持中文、拼音、英文。返回候选列表(ID、层级位置、坐标),按相关性排序取 top-5
get_ancestors id 向上遍历层级链(县→市→省),返回从直接父到顶级的有序数组
get_neighbors id 查询同层级邻接区域,含共享边界长度
describe_region id, include_geometry?, geometry_tolerance_km? 区域全景:层级位置、邻居、面积、类型、子区数量,可选返回简化 GeoJSON

校验类(核心差异化)

工具 参数 说明
check_containment child_id, parent_id 验证包含关系,KG 层级检查 + PostGIS 空间回退
check_adjacency id_a, id_b 验证邻接关系,预计算表 + 实时空间回退

空间运算类

工具 参数 说明
find_path id_a, id_b, max_hops? BFS 搜索两区域间的邻接路径(如 江苏→浙江)
measure_distance id_a, id_b 两区域质心间距离 (km)
find_within id, radius_km 查找半径内的同层级区域

属性对比类

工具 参数 说明
compare_regions ids[], metric 多区域属性排名对比(人口/GDP/面积)

校验返回格式

校验通过:

{
  "valid": true,
  "claim": "南京市 属于 江苏省",
  "explanation": "层级关系确认: 南京市(city) → 江苏省(province)"
}

校验失败 + 纠错:

{
  "valid": false,
  "claim": "南京市 属于 浙江省",
  "explanation": "南京市 不属于 浙江省,实际属于 江苏省(province)",
  "correction": "实际归属: 南京市 属于 江苏省(province)",
  "evidence": {
    "actual_parent_id": "320000",
    "actual_parent_name": "江苏省",
    "actual_parent_level": "province"
  }
}

这种结构化返回使 LLM 能理解错误原因并自我修正——这就是地理约束驱动的推理精炼环

地名消歧(多语言)

resolve_place 支持三级匹配:

  1. 中文精确/模糊匹配 — "南京"、"南京市"、"江宁"
  2. 拼音匹配 — "nanjing"、"jss"(首字母)、"jiangsusheng"
  3. 英文别名匹配 — "Nanjing"、"Jiangsu"、"Canton"

拼音索引使用 pinyin-pro 库在启动时构建,英文别名覆盖所有省和主要地级市(~60 个)。

Skills

GeoRiddle(地理谜题推理)

skills/geo-riddle/SKILL.md 定义地理谜题推理工作流。LLM 解谜时自动调用 MCP 工具逐步缩小候选范围:

谜题: "我是江苏省面积最小的与安徽接壤的地级市"
→ get_children("320000")        → 获取江苏所有地级市
→ describe_region(每个市)        → 获取面积
→ check_adjacency(每个市, "340000") → 筛选与安徽相邻的
→ 综合约束得出答案: 南京市

5 道示例谜题(1-5 分难度),每道附带完整 solution trace。

GeoFactCheck(地理断言校验)

skills/geo-fact-check/SKILL.md 定义 LLM 输出中的地理断言自动扫描与校验:

  1. 扫描 — 识别包含/邻接/否定断言模式
  2. 提取 — 解析为 (subject, relation, object) 三元组
  3. 校验 — 调用 check_containment / check_adjacency
  4. 报告 — verified / falsified / unverifiable 三类

支持中英文断言模式:

模式 示例 三元组
X属于Y "南京属于江苏" (南京, BELONGS_TO, 江苏)
X与Y相邻 "江苏与浙江相邻" (江苏, ADJACENT_TO, 浙江)
X不属于Y "南京不属于浙江" (南京, NOT_BELONGS_TO, 浙江)

MCP Resources

mapping_knowledge/mapping_resources/ 目录下的 JSON 文件自动注册为 MCP Resource,LLM 可按需读取制图知识:

  • projection-advice.json — 中国地图投影选择指南(Albers / Lambert / Web Mercator)
  • admin-level-guide.json — 行政区划层级体系及编码规则

添加新 JSON 文件即可扩展,无需代码改动。

校验机制(双层)

  1. 层级检查(KG 内存遍历):遍历 parentOf 链,O(depth) ≈ 最多 4 次查找。无需数据库查询。
  2. 空间回退(PostGIS ST_Contains / ST_Touches):当 ID 不在 KG 中或需要空间验证时使用。单次查询约 16-23ms。

前置条件

  • Node.js 18+
  • PostgreSQL + PostGIS 扩展
  • 本地 PostGIS 数据库包含中国行政区划表(province, city, county, village
  • 知识图谱 JSON 文件(admin_knowledge_graph.json

数据库表结构

项目连接的 PostGIS 数据表:

表名 名称列 区划码列 几何列
province 省级码 geom
city 地名 区划码 geom
county 地名 区划码 geom
village name area_code geom

预计算表(npm run materialize 创建):

表名 说明
admin_adjacency 邻接关系(70 + 963 + 8134 对)
admin_containment 包含关系闭包(预留)
admin_attributes 区域属性(人口/GDP/面积)

安装与运行

# 安装依赖
npm install

# 首次运行:预计算邻接表(约 30 秒)
npm run materialize

# 导入属性数据(人口/GDP/面积)
npx tsx scripts/materialize-attributes.ts

# 启动 MCP 服务器
npm run dev

启动后输出:

Loading knowledge graph...
Loaded 46413 nodes, 44956 edges
Connecting to PostGIS...
PostGIS connected
Registered 2 mapping resources
GeoOntology-MCP server running

配置

环境变量

变量 默认值 说明
KG_PATH (required) 知识图谱 JSON 路径
MAPPING_RESOURCES_DIR mapping_knowledge/mapping_resources 制图知识资源目录
PGHOST 127.0.0.1 PostgreSQL 主机
PGPORT 5432 PostgreSQL 端口
PGDATABASE (required) 数据库名
PGUSER (required) 数据库用户
PGPASSWORD (required) 数据库密码

Claude Desktop / Claude Code 配置

{
  "mcpServers": {
    "geo-ontology": {
      "command": "npx",
      "args": ["tsx", "/path/to/GeoOntology-MCP/src/index.ts"],
      "env": {
        "KG_PATH": "/path/to/admin_knowledge_graph.json",
        "PGHOST": "127.0.0.1",
        "PGPORT": "5432",
        "PGDATABASE": "your_database",
        "PGUSER": "your_user",
        "PGPASSWORD": "your_password"
      }
    }
  }
}

使用示例

典型工作流:先消歧,再查询,最后校验

→ resolve_place(name="南京")
← [{ id: "320100", name: "南京市", level: "city", parentName: "江苏省", score: 104 }]

→ get_ancestors(id="320100")
← [{ id: "320000", name: "江苏省", level: "province", type: "省" }]

→ check_containment(child_id="320102", parent_id="320000")
← { valid: true, claim: "玄武区 属于 江苏省",
     explanation: "层级关系确认: 玄武区(county) → 南京市(city) → 江苏省(province)" }

拼音/英文搜索

→ resolve_place(name="Nanjing")
← [{ id: "320100", name: "南京市", level: "city", score: 90 }]

→ resolve_place(name="jss")
← [{ id: "320000", name: "江苏省", level: "province", score: 40 }]

路径搜索

→ find_path(id_a="320000", id_b="330000")
← { found: true, path: ["320000", "330000"], pathNames: ["江苏省", "浙江省"],
     hops: 1, totalBoundaryKm: 152.7 }

距离与范围查询

→ measure_distance(id_a="320100", id_b="330100")
← { idA: "320100", nameA: "南京市", idB: "330100", nameB: "杭州市",
     distanceKm: 267.4, method: "centroid-to-centroid" }

→ find_within(id="320100", radius_km=200)
← [{ id: "330100", name: "杭州市", distanceKm: 267.4, ... }, ...]

属性对比

→ compare_regions(ids=["110000", "310000", "320000"], metric="population")
← { metric: "population", regions: [
     { id: "320000", name: "江苏省", value: 85054000, rank: 1 },
     { id: "110000", name: "北京市", value: 21893095, rank: 2 },
     { id: "310000", name: "上海市", value: 24870895, rank: 3 }
   ] }

几何数据

→ describe_region(id="110000", include_geometry=true, geometry_tolerance_km=0.5)
← { id: "110000", name: "北京市", ..., geometry: { type: "Polygon", coordinates: [...] },
     geometryToleranceKm: 0.5 }

项目结构

src/
  index.ts                        # MCP 服务器入口
  data-source/
    interface.ts                  # GeoDataSource 接口 + 所有类型定义
    postgis-adapter.ts            # PostGIS 实现(核心适配器)
    column-map.ts                 # 表名/列名映射 + inferLevel()
  knowledge-graph/
    types.ts                      # KG 节点/边类型(含拼音/别名字段)
    loader.ts                     # KG JSON 加载 + 拼音索引 + 别名合并
    english-aliases.ts            # 省市英文名映射 (~60个)
  ontology/
    hierarchy.ts                  # 层级遍历(getAncestors, getChildren)
    resolver.ts                   # 地名消歧(中文/拼音/英文四级匹配)
    verifier.ts                   # 包含关系校验(KG 层级检查)
    pathfinder.ts                 # BFS 路径搜索(纯函数)
  tools/
    registration.ts               # 10 个工具注册到 McpServer
  resources/
    registration.ts               # MCP Resource 注册(mapping_knowledge)
scripts/
  materialize-adjacency.ts        # 邻接预计算脚本
  materialize-attributes.ts       # 属性数据导入脚本
skills/
  geo-riddle/SKILL.md             # GeoRiddle 谜题推理 skill
  geo-fact-check/SKILL.md         # GeoFactCheck 断言校验 skill
mapping_knowledge/
  mapping_resources/              # MCP Resource JSON 文件
    projection-advice.json        # 投影选择指南
    admin-level-guide.json        # 行政区划编码规则
data/
  admin-attributes.csv            # 省级属性数据(人口/GDP/面积)
tests/
  knowledge-graph.test.ts         # KG 加载器测试
  hierarchy.test.ts               # 层级遍历测试
  resolver.test.ts                # 地名消歧测试
  verifier.test.ts                # 校验逻辑测试
  column-map.test.ts              # 列映射测试
  pinyin-resolver.test.ts         # 拼音消歧测试
  path.test.ts                    # BFS 路径搜索测试
  fixtures/
    sample-kg.json                # 测试用样本 KG

可插拔数据源

所有工具通过 GeoDataSource 接口访问数据,PostGIS 只是默认实现:

interface GeoDataSource {
  connect(): Promise<void>;
  close(): Promise<void>;
  getRegionInfo(id: string): Promise<RegionInfo | null>;
  getAncestors(id: string): Promise<HierarchyNode[]>;
  getChildren(id: string): Promise<HierarchyNode[]>;
  getNeighbors(id: string): Promise<AdjacencyResult[]>;
  checkContainment(childId: string, parentId: string): Promise<VerificationResult>;
  checkAdjacency(idA: string, idB: string): Promise<VerificationResult>;
  resolvePlace(name: string, context?: string): Promise<PlaceCandidate[]>;
  findPath(idA: string, idB: string, maxHops?: number): Promise<PathResult>;
  getRegionGeometry(id: string, toleranceKm?: number): Promise<RegionGeometry | null>;
  measureDistance(idA: string, idB: string): Promise<DistanceResult | null>;
  findWithin(id: string, radiusKm: number): Promise<WithinResult[]>;
  getAttributes(id: string): Promise<RegionAttributes | null>;
  compareRegions(ids: string[], metric: 'population' | 'gdp' | 'areaSqKm'): Promise<CompareResult>;
}

测试

npm test

50 个单元测试覆盖:KG 加载器、层级遍历、地名消歧(中文+拼音)、校验逻辑、列映射、BFS 路径搜索。测试使用 tests/fixtures/sample-kg.json 样本数据,无需连接数据库。

技术栈

  • TypeScript + ESM (@modelcontextprotocol/sdk)
  • pg — PostgreSQL/PostGIS 客户端
  • pinyin-pro — 拼音转换
  • zod — 工具参数校验
  • Vitest — 单元测试

License

MIT

from github.com/kevics1/GeoOntology-MCP

Установить GeoOntology в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install geoontology-mcp

Ставит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.

Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh

Или настроить вручную

Выполни в терминале:

claude mcp add geoontology-mcp -- npx -y github:kevics1/GeoOntology-MCP

FAQ

GeoOntology MCP бесплатный?

Да, GeoOntology MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для GeoOntology?

Нет, GeoOntology работает без API-ключей и переменных окружения.

GeoOntology — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить GeoOntology в Claude Desktop, Claude Code или Cursor?

Открой GeoOntology на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare GeoOntology with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории data