GitHub 已開源:民政部官方的國家地名資訊庫 MCP & Skill 實作

前言

--

不知道你有沒有過這種經歷——跟 AI 說「幫我查一下武漢在哪個省」,結果它一本正經地胡說八道,給你編出一個根本不存在的行政區劃代碼。

又或者,做一個地址自動填入的功能,發現手裡的區劃資料要嘛是三五年前的老黃曆,要嘛缺斤少兩,東城區給你標到河北省去了。

這些問題折磨了我很久,直到我發現了國家地名資訊庫(dmfw.mca.gov.cn)——民政部出品的官方資料來源。從 2026 年起,這玩意兒就要正式取代統計局那套統計用區劃代碼了,可以說是「根正苗藍」的官方資料。

我就琢磨,能不能讓 AI 直接調這個 API 來查地名?於是根據官方提供的 API 文件,實作了對應的 MCP 和 Skill,已經開源在 GitHub,地址在文章結尾,需要自取。

一、資料來源是個「大家伙」——先了解清楚再下手

1.1 平台背景

先給不了解的同學做個簡介:

  • 資料來源:中國·國家地名資訊庫(民政部出品)
  • 基礎 URLdmfw.mca.gov.cn
  • 座標系:CGCS2000(2000 國家大地座標系)——不是常見的 WGS84,別搞混了
  • 資料截止日期:2025 年 12 月 31 日

這個平台的資料是按年度更新的,所以查詢的時候注意帶上年份參數,不然可能查到的不是你想的那個版本。

1.2 資料結構

行政區劃這玩意兒,全國不統一,有的地方只有兩級,有的地方四級全齊:

層級示例說明第一级北京市、湖北省省級行政區第二级武漢市、北京市市轄區第三級武昌區、東城區區縣級第四級街道/鄉鎮街道辦、鄉鎮幾個容易踩坑的地方

  • 直轄市(北京、天津、上海、重慶)比較特殊,只有兩級——市直接到區,沒有「市」這一級。比如你查北京,不會查到「北京市」這個層級,而是直接是「東城區」「西城區」。
  • 不設區的市:東莞、中山、儋州、嘉峪關這些,直接到鎮/街道,沒有中間的區級。
  • 省直轄縣級行政單位:濟源、仙桃、瓊海這些「小不點」,也是只有兩級。

所以如果你要做全國通用的地址選擇器,這幾種情況一定要特殊處理。

二、7 個介面

國家地名資訊庫提供了 7 個核心 API,我用了一段時間之後,覺得大部分場景前兩個就夠用了:

序號介面名稱URL方法用途1行政區劃搜尋/xzqh/getListGET查詢行政區劃層級結構2地名搜尋/stname/listPubGET按名稱搜尋地名3地名詳情取得/stname/detailsPubPOST取得地名詳細資訊4同名區劃統計/datastatis/GroupCountNameByCodeGET統計同名地名按區劃分布5同名類別統計/datastatis/GroupCountNameByTypeGET統計同名地名按類別分布6同音區劃統計/datastatis/GroupCountPinyinByCodeGET統計同音地名按區劃分布7同音類別統計/datastatis/GroupCountPinyinByTypeGET統計同音地名按類別分布說實話,同名/同音統計這幾個介面我目前還沒用上,但留著備用總沒錯——萬一哪天產品說「我們要做一個全國有多少個『張村』的統計」,直接調它就完了。

三、MCP 伺服器——讓 AI 直接「開口問」地名

3.1 先說說什麼是 MCP

MCP(Model Context Protocol)這玩意兒,你可以理解為 AI 工具的「USB 介面」。以前 AI 想調個外部 API,你得寫一堆 Prompt 來描述怎麼調、調什麼參數。現在有了 MCP,直接定義好工具,AI 就能像呼叫本地函式一樣調遠端 API,爽得很。

3.2 專案結構

bash 体验AI代码助手 代码解读复制代码mcp-china-geonames-server/
├── server.py          # MCP 伺服器主檔案
├── requirements.txt   # Python 依賴
└── README.md          # 專案文件

就三個檔案,簡單明瞭。

3.3 核心程式碼——直接抄就行

我直接上程式碼,註解寫得比較詳細:

python 体验AI代码助手 代码解读复制代码from mcp.server.fastmcp import FastMCP
import requests
from typing import Optional

mcp = FastMCP("China GeoNames MCP Server")

BASE_URL = "https://dmfw.mca.gov.cn/9095"

@mcp.tool()
def search_administrative_division(
    year: Optional[int] = None,
    code: Optional[str] = None,
    maxLevel: int = 1
) -> dict:
    """行政區劃搜尋——查某個地區的下級區劃"""
    params = {"maxLevel": maxLevel}
    if year:
        params["year"] = year
    if code:
        params["code"] = code
    response = requests.get(f"{BASE_URL}/xzqh/getList", params=params)
    return response.json()

@mcp.tool()
def search_place_name(
    stName: str,
    placeTypeCode: Optional[str] = None,
    year: Optional[int] = None,
    searchType: str = "模糊",
    code: Optional[str] = None,
    page: int = 1,
    size: int = 10
) -> dict:
    """地名搜尋——按名字查地點,支援模糊比對"""
    params = {
        "stName": stName,
        "searchType": searchType,
        "page": page,
        "size": size
    }
    if placeTypeCode:
        params["placeTypeCode"] = placeTypeCode
    if year:
        params["year"] = year
    if code:
        params["code"] = code
    response = requests.get(f"{BASE_URL}/stname/listPub", params=params)
    return response.json()

@mcp.tool()
def get_place_details(id: str) -> dict:
    """地名詳情——拿到 ID 之後查詳細資訊"""
    response = requests.post(f"{BASE_URL}/stname/detailsPub", json={"id": id})
    return response.json()

幾個小提示:

  • maxLevel=1 就是只查下一級,maxLevel=3 就是查三級。建議先試試 maxLevel=1,不然資料量會讓你懷疑人生(全國三級資料大概 300KB 左右)。
  • code 參數傳空字串代表從根開始查,傳具體代碼查該節點下的子級。

3.4 安裝與執行

bash 体验AI代码助手 代码解读复制代码# 安裝依賴
pip install -r requirements.txt

# 執行伺服器
python server.py

就這些,沒有了。跑起來之後,設定到你的 AI 用戶端(Claude Desktop、Cline 之類的),就可以開聊了。

四、Skill

4.1 為什麼要有 Skill

MCP 是讓 AI「會調」API,Skill 則是讓 AI「懂」API。

舉個例子,沒有 Skill 的時候,你讓 AI 幫你查「武漢屬於哪個省」,它可能得試好幾次才能蒙對。有了 Skill,AI 直接就知道:這個介面回傳的 data[].code 是行政區劃代碼,data[].name 是名稱,應該怎麼組合查詢。

4.2 格式範例

我把官方 API 的合約用結構化的方式描述出來,AI 看了就知道怎麼用:

markdown 体验AI代码助手 代码解读复制代码## 1. 行政區劃搜尋

**URL:** `https://dmfw.mca.gov.cn/9095/xzqh/getList`

**請求方式:** GET

**請求參數:**

| 參數名 | 類型 | 必填 | 預設值 | 說明 |
|--------|------|------|--------|------|
| year | int | 否 | 最新年版 | 年份 |
| code | String | 否 | - | 行政區劃代碼 |
| maxLevel | int | 是 | - | 查詢深度 |

**回應參數:**

| 參數名 | 類型 | 說明 |
|--------|------|------|
| data | Object[] | 回傳結果集 |
| data[].code | String | 行政區劃代碼 |
| data[].name | String | 標準名稱 |

格式其實很直接,就是參數說明 + 回應說明。關鍵是寫清楚類型、是否必填、預設值這些,AI 才能準確地生成呼叫程式碼。

五、瀏覽器主控台除錯——不用裝任何東西

如果你只是想快速試試這個 API 能不能跑通,最方便的方法是直接打開瀏覽器主控台。

按 F12 → 切換到 Console 標籤 → 貼上下面的程式碼按 Enter:

javascript 体验AI代码助手 代码解读复制代码// 取得全國省市區三級資料(資料量較大,約300KB)
var response = await fetch("https://dmfw.mca.gov.cn/9095/xzqh/getList?code=&maxLevel=3");
var data = await response.json();
console.log(data);

// 只取得省級資料(建議初次使用)
var response = await fetch("https://dmfw.mca.gov.cn/9095/xzqh/getList?code=&maxLevel=1");
var data = await response.json();
console.log(data);

// 取得湖北省 省、市、區三級
var response = await fetch("https://dmfw.mca.gov.cn/9095/xzqh/getList?code=420000000000&maxLevel=3");
var data = await response.json();
console.log(data);

// 取得武漢市 市、區縣、鄉鎮街道三級
var response = await fetch("https://dmfw.mca.gov.cn/9095/xzqh/getList?code=420100000000&maxLevel=3");
var data = await response.json();
console.log(data);

這個方法的好處是所見即所得——回傳什麼資料你立刻就能看到,比 Postman 還快,而且不用裝任何軟體。除錯介面的時候超方便,誰用誰知道。

六、社群輪子——不要重複造

說實話,自己處理這套四級行政區劃資料還挺麻煩的。好在社群裡已經有大佬做了更易用的封裝:

xiangyuecn/area-javascript-sql(GitHub)

這個專案把國家地名資訊庫的四級資料整合到單個 CSV 檔案裡,還附帶了:

  • 拼音標註(媽媽再也不用擔心我讀錯「監利」了)
  • 座標和四級邊界範圍
  • 支援匯出為 MySQL、MSSQL、PgSQL、Oracle 等資料庫格式
  • 多級聯動資料和代碼生成工具

如果你不打算折騰 API,直接用這個也挺好。

七、專案倉庫

我自己實作的 MCP 伺服器和 Skill 規範都開源了,有需要自取:

項目倉庫地址說明MCP 伺服器github.com/linyshdhhcb…基於 FastMCP 實作,開箱即用Skill 規範github.com/linyshdhhcb…完整的 API 規範文件覺得有用的話,給個 Star 呗!

結語

花了點時間把國家地名資訊庫的 API 跑通了,說實話比我想像中順利——主要踩的坑都在行政區劃的特殊情況上(直轄市、省直轄縣這些),真正調介面的部分反而沒遇到什麼問題。

最後一個小建議:線上用一定要加快取。這個 API 回傳的資料量不小,頻繁呼叫既慢又浪費頻寬。把常用的省市區資料緩存在本地或 Redis 裡,體驗會好很多。


參考資料


原文出處:https://juejin.cn/post/7638298153040707627


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝16   💬11   ❤️2
543
🥈
alicec
📝1   ❤️2
77
🥉
我愛JS
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登