|
| 1 | +[English](./README.md) | **繁體中文** |
| 2 | + |
| 3 | +[](https://www.npmjs.com/package/@cablate/mcp-google-map) [](./LICENSE) [](https://www.npmjs.com/package/@cablate/mcp-google-map) |
| 4 | + |
| 5 | +[<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522google-maps%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522-y%2522%252C%2522%2540cablate%252Fmcp-google-map%2540latest%2522%252C%2522--stdio%2522%255D%252C%2522env%2522%253A%257B%2522GOOGLE_MAPS_API_KEY%2522%253A%2522YOUR_API_KEY%2522%257D%257D) [<img alt="Install in VS Code Insiders" src="https://img.shields.io/badge/VS_Code_Insiders-VS_Code_Insiders?style=flat-square&label=Install%20Server&color=24bfa5">](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522google-maps%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522-y%2522%252C%2522%2540cablate%252Fmcp-google-map%2540latest%2522%252C%2522--stdio%2522%255D%252C%2522env%2522%253A%257B%2522GOOGLE_MAPS_API_KEY%2522%253A%2522YOUR_API_KEY%2522%257D%257D) |
| 6 | + |
| 7 | +# MCP Google Map Server |
| 8 | + |
| 9 | +讓你的 AI 代理理解真實世界 — 地理編碼、路線規劃、地點搜尋、空間推理。 |
| 10 | + |
| 11 | +<img src="./assets/demo-grid-zh.png" alt="旅行規劃展示 — 京都二日遊、東京戶外一日、日本五日、曼谷背包客" width="800"> |
| 12 | + |
| 13 | +- **17 個工具** — 14 個原子工具 + 3 個組合工具(explore-area、plan-route、compare-places) |
| 14 | +- **3 種模式** — stdio、StreamableHTTP、獨立 exec CLI |
| 15 | +- **Agent Skill** — 內建技能定義,教 AI 如何串接地理工具([`skills/google-maps/`](./skills/google-maps/)) |
| 16 | + |
| 17 | +### vs Google Grounding Lite |
| 18 | + |
| 19 | +| | 本專案 | [Grounding Lite](https://cloud.google.com/blog/products/ai-machine-learning/announcing-official-mcp-support-for-google-services) | |
| 20 | +|---|---|---| |
| 21 | +| 工具數 | **17** | 3 | |
| 22 | +| 地理編碼 | 有 | 無 | |
| 23 | +| 逐步導航 | 有 | 無 | |
| 24 | +| 海拔查詢 | 有 | 無 | |
| 25 | +| 距離矩陣 | 有 | 無 | |
| 26 | +| 地點詳情 | 有 | 無 | |
| 27 | +| 時區查詢 | 有 | 無 | |
| 28 | +| 天氣查詢 | 有 | 有 | |
| 29 | +| 空氣品質 | 有 | 無 | |
| 30 | +| 地圖圖片 | 有 | 無 | |
| 31 | +| 組合工具(探索、規劃、比較) | 有 | 無 | |
| 32 | +| 開源 | MIT | 否 | |
| 33 | +| 自架部署 | 有 | 僅 Google 託管 | |
| 34 | +| Agent Skill | 有 | 無 | |
| 35 | + |
| 36 | +### 快速開始 |
| 37 | + |
| 38 | +```bash |
| 39 | +# stdio(Claude Desktop、Cursor 等) |
| 40 | +npx @cablate/mcp-google-map --stdio |
| 41 | + |
| 42 | +# exec CLI — 不需啟動 server |
| 43 | +npx @cablate/mcp-google-map exec geocode '{"address":"台北101"}' |
| 44 | + |
| 45 | +# HTTP server |
| 46 | +npx @cablate/mcp-google-map --port 3000 --apikey "YOUR_API_KEY" |
| 47 | +``` |
| 48 | + |
| 49 | +## 特別感謝 |
| 50 | + |
| 51 | +感謝 [@junyinnnn](https://github.com/junyinnnn) 協助實作 `streamablehttp` 支援。 |
| 52 | + |
| 53 | +## 可用工具 |
| 54 | + |
| 55 | +| 工具 | 說明 | |
| 56 | +|------|------| |
| 57 | +| `maps_search_nearby` | 依類型搜尋附近地點(餐廳、咖啡廳、飯店等),支援半徑、評分、營業中篩選 | |
| 58 | +| `maps_search_places` | 自然語言地點搜尋(如「東京拉麵」),支援位置偏好、評分、營業中篩選 | |
| 59 | +| `maps_place_details` | 以 place_id 取得地點完整資訊 — 評論、電話、網站、營業時間、照片 | |
| 60 | +| `maps_geocode` | 將地址或地標名稱轉換為 GPS 座標 | |
| 61 | +| `maps_reverse_geocode` | 將 GPS 座標轉換為街道地址 | |
| 62 | +| `maps_distance_matrix` | 計算多個起點與終點間的旅行距離和時間 | |
| 63 | +| `maps_directions` | 取得兩點間的逐步導航路線 | |
| 64 | +| `maps_elevation` | 查詢地理座標的海拔高度(公尺) | |
| 65 | +| `maps_timezone` | 查詢座標的時區 ID、名稱、UTC/DST 偏移量和當地時間 | |
| 66 | +| `maps_weather` | 查詢當前天氣或預報 — 溫度、濕度、風速、紫外線、降水 | |
| 67 | +| `maps_air_quality` | 查詢空氣品質指數、污染物濃度,以及各族群健康建議 | |
| 68 | +| `maps_static_map` | 產生帶標記、路徑或路線的地圖圖片 — 直接內嵌在對話中 | |
| 69 | +| `maps_batch_geocode` | 一次地理編碼最多 50 個地址 | |
| 70 | +| `maps_search_along_route` | 搜尋兩點間路線沿途的地點 — 依最小繞路時間排序 | |
| 71 | +| **組合工具** | | |
| 72 | +| `maps_explore_area` | 一次呼叫探索某地周邊 — 搜尋多種地點類型並取得詳情 | |
| 73 | +| `maps_plan_route` | 規劃最佳化多站路線 — 地理編碼、最佳順序、回傳導航 | |
| 74 | +| `maps_compare_places` | 並排比較地點 — 搜尋、取得詳情,可選計算距離 | |
| 75 | + |
| 76 | +所有工具標註 `readOnlyHint: true` 和 `destructiveHint: false` — MCP 客戶端可自動核准,無需使用者確認。 |
| 77 | + |
| 78 | +> **前置條件**:使用地點相關工具前,請在 [Google Cloud Console](https://console.cloud.google.com) 啟用 **Places API (New)**。 |
| 79 | +
|
| 80 | +## 安裝 |
| 81 | + |
| 82 | +### 方法一:stdio(大多數客戶端推薦) |
| 83 | + |
| 84 | +適用於 Claude Desktop、Cursor、VS Code 及任何支援 stdio 的 MCP 客戶端: |
| 85 | + |
| 86 | +```json |
| 87 | +{ |
| 88 | + "mcpServers": { |
| 89 | + "google-maps": { |
| 90 | + "command": "npx", |
| 91 | + "args": ["-y", "@cablate/mcp-google-map", "--stdio"], |
| 92 | + "env": { |
| 93 | + "GOOGLE_MAPS_API_KEY": "YOUR_API_KEY" |
| 94 | + } |
| 95 | + } |
| 96 | + } |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +**減少上下文用量** — 如果只需要部分工具,設定 `GOOGLE_MAPS_ENABLED_TOOLS` 限制註冊的工具: |
| 101 | + |
| 102 | +```json |
| 103 | +{ |
| 104 | + "env": { |
| 105 | + "GOOGLE_MAPS_API_KEY": "YOUR_API_KEY", |
| 106 | + "GOOGLE_MAPS_ENABLED_TOOLS": "maps_geocode,maps_directions,maps_search_places" |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +不設定或設為 `*` 即啟用全部 17 個工具(預設)。 |
| 112 | + |
| 113 | +### 方法二:HTTP Server |
| 114 | + |
| 115 | +適用於多 session 部署、per-request API key 隔離或遠端存取: |
| 116 | + |
| 117 | +```bash |
| 118 | +npx @cablate/mcp-google-map --port 3000 --apikey "YOUR_API_KEY" |
| 119 | +``` |
| 120 | + |
| 121 | +然後設定你的 MCP 客戶端: |
| 122 | + |
| 123 | +```json |
| 124 | +{ |
| 125 | + "mcpServers": { |
| 126 | + "google-maps": { |
| 127 | + "type": "http", |
| 128 | + "url": "http://localhost:3000/mcp" |
| 129 | + } |
| 130 | + } |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### Server 資訊 |
| 135 | + |
| 136 | +- **傳輸方式**:stdio(`--stdio`)或 Streamable HTTP(預設) |
| 137 | +- **工具數**:17 個 Google Maps 工具(14 原子 + 3 組合)— 可透過 `GOOGLE_MAPS_ENABLED_TOOLS` 篩選 |
| 138 | + |
| 139 | +### CLI Exec 模式(Agent Skill) |
| 140 | + |
| 141 | +不啟動 MCP server,直接使用工具: |
| 142 | + |
| 143 | +```bash |
| 144 | +npx @cablate/mcp-google-map exec geocode '{"address":"台北101"}' |
| 145 | +npx @cablate/mcp-google-map exec search-places '{"query":"東京拉麵"}' |
| 146 | +``` |
| 147 | + |
| 148 | +全部 17 個工具可用:`geocode`、`reverse-geocode`、`search-nearby`、`search-places`、`place-details`、`directions`、`distance-matrix`、`elevation`、`timezone`、`weather`、`air-quality`、`static-map`、`batch-geocode-tool`、`search-along-route`、`explore-area`、`plan-route`、`compare-places`。完整參數文件見 [`skills/google-maps/`](./skills/google-maps/)。 |
| 149 | + |
| 150 | +### 批次地理編碼 |
| 151 | + |
| 152 | +從檔案批次地理編碼: |
| 153 | + |
| 154 | +```bash |
| 155 | +npx @cablate/mcp-google-map batch-geocode -i addresses.txt -o results.json |
| 156 | +cat addresses.txt | npx @cablate/mcp-google-map batch-geocode -i - |
| 157 | +``` |
| 158 | + |
| 159 | +輸入:每行一個地址。輸出:JSON `{ total, succeeded, failed, results[] }`。預設並行度:20。 |
| 160 | + |
| 161 | +### API Key 設定 |
| 162 | + |
| 163 | +API key 可透過三種方式提供(優先順序): |
| 164 | + |
| 165 | +1. **HTTP Headers**(最高優先) |
| 166 | + |
| 167 | + ```json |
| 168 | + { |
| 169 | + "mcp-google-map": { |
| 170 | + "transport": "streamableHttp", |
| 171 | + "url": "http://localhost:3000/mcp", |
| 172 | + "headers": { |
| 173 | + "X-Google-Maps-API-Key": "YOUR_API_KEY" |
| 174 | + } |
| 175 | + } |
| 176 | + } |
| 177 | + ``` |
| 178 | + |
| 179 | +2. **命令列參數** |
| 180 | + |
| 181 | + ```bash |
| 182 | + mcp-google-map --apikey YOUR_API_KEY |
| 183 | + ``` |
| 184 | + |
| 185 | +3. **環境變數**(.env 檔案或命令列) |
| 186 | + ```env |
| 187 | + GOOGLE_MAPS_API_KEY=your_api_key_here |
| 188 | + MCP_SERVER_PORT=3000 |
| 189 | + ``` |
| 190 | + |
| 191 | +## 開發 |
| 192 | + |
| 193 | +### 本地開發 |
| 194 | + |
| 195 | +```bash |
| 196 | +# 複製專案 |
| 197 | +git clone https://github.com/cablate/mcp-google-map.git |
| 198 | +cd mcp-google-map |
| 199 | + |
| 200 | +# 安裝依賴 |
| 201 | +npm install |
| 202 | + |
| 203 | +# 設定環境變數 |
| 204 | +cp .env.example .env |
| 205 | +# 編輯 .env 填入你的 API key |
| 206 | + |
| 207 | +# 建置專案 |
| 208 | +npm run build |
| 209 | + |
| 210 | +# 啟動 server |
| 211 | +npm start |
| 212 | + |
| 213 | +# 或以開發模式執行 |
| 214 | +npm run dev |
| 215 | +``` |
| 216 | + |
| 217 | +### 測試 |
| 218 | + |
| 219 | +```bash |
| 220 | +# 執行 smoke tests(基本測試不需要 API key) |
| 221 | +npm test |
| 222 | + |
| 223 | +# 執行完整 E2E 測試(需要 GOOGLE_MAPS_API_KEY) |
| 224 | +npm run test:e2e |
| 225 | +``` |
| 226 | + |
| 227 | +### 專案結構 |
| 228 | + |
| 229 | +``` |
| 230 | +src/ |
| 231 | +├── cli.ts # CLI 進入點 |
| 232 | +├── config.ts # 工具註冊與 server 設定 |
| 233 | +├── index.ts # 套件匯出 |
| 234 | +├── core/ |
| 235 | +│ └── BaseMcpServer.ts # MCP server(streamable HTTP 傳輸) |
| 236 | +├── services/ |
| 237 | +│ ├── NewPlacesService.ts # Google Places API (New) 客戶端 |
| 238 | +│ ├── PlacesSearcher.ts # Service facade 層 |
| 239 | +│ └── toolclass.ts # Legacy Google Maps API 客戶端 |
| 240 | +├── tools/ |
| 241 | +│ └── maps/ |
| 242 | +│ ├── searchNearby.ts # maps_search_nearby 工具 |
| 243 | +│ ├── searchPlaces.ts # maps_search_places 工具 |
| 244 | +│ ├── placeDetails.ts # maps_place_details 工具 |
| 245 | +│ ├── geocode.ts # maps_geocode 工具 |
| 246 | +│ ├── reverseGeocode.ts # maps_reverse_geocode 工具 |
| 247 | +│ ├── distanceMatrix.ts # maps_distance_matrix 工具 |
| 248 | +│ ├── directions.ts # maps_directions 工具 |
| 249 | +│ ├── elevation.ts # maps_elevation 工具 |
| 250 | +│ ├── timezone.ts # maps_timezone 工具 |
| 251 | +│ ├── weather.ts # maps_weather 工具 |
| 252 | +│ ├── airQuality.ts # maps_air_quality 工具 |
| 253 | +│ ├── staticMap.ts # maps_static_map 工具 |
| 254 | +│ ├── batchGeocode.ts # maps_batch_geocode 工具 |
| 255 | +│ ├── searchAlongRoute.ts # maps_search_along_route 工具 |
| 256 | +│ ├── exploreArea.ts # maps_explore_area(組合) |
| 257 | +│ ├── planRoute.ts # maps_plan_route(組合) |
| 258 | +│ └── comparePlaces.ts # maps_compare_places(組合) |
| 259 | +└── utils/ |
| 260 | + ├── apiKeyManager.ts # API key 管理 |
| 261 | + └── requestContext.ts # Per-request context(API key 隔離) |
| 262 | +tests/ |
| 263 | +└── smoke.test.ts # Smoke + E2E 測試套件 |
| 264 | +skills/ |
| 265 | +├── google-maps/ # Agent Skill — 如何使用工具 |
| 266 | +│ ├── SKILL.md # 工具對照表、場景食譜、呼叫方式 |
| 267 | +│ └── references/ |
| 268 | +│ ├── tools-api.md # 工具參數 + 場景食譜 |
| 269 | +│ └── travel-planning.md # 旅行規劃方法論 |
| 270 | +└── project-docs/ # Project Skill — 如何開發/維護 |
| 271 | + ├── SKILL.md # 架構概覽 + 入門指南 |
| 272 | + └── references/ |
| 273 | + ├── architecture.md # 系統設計、code map、9 檔案 checklist |
| 274 | + ├── google-maps-api-guide.md # API 端點、定價、注意事項 |
| 275 | + ├── geo-domain-knowledge.md # GIS 基礎、日本場景 |
| 276 | + └── decisions.md # 10 個 ADR(設計決策 + 理由) |
| 277 | +``` |
| 278 | + |
| 279 | +## 技術棧 |
| 280 | + |
| 281 | +- **TypeScript** - 型別安全開發 |
| 282 | +- **Node.js** - 執行環境 |
| 283 | +- **@googlemaps/places** - Google Places API (New) 地點搜尋與詳情 |
| 284 | +- **@googlemaps/google-maps-services-js** - Legacy API 地理編碼、導航、距離矩陣、海拔 |
| 285 | +- **@modelcontextprotocol/sdk** - MCP 協議實作(v1.27+) |
| 286 | +- **Express.js** - HTTP server 框架 |
| 287 | +- **Zod** - Schema 驗證 |
| 288 | + |
| 289 | +## 安全性 |
| 290 | + |
| 291 | +- API key 在 server 端處理 |
| 292 | +- 多租戶部署的 per-session API key 隔離 |
| 293 | +- 正式環境可啟用 DNS rebinding 防護 |
| 294 | +- 使用 Zod schemas 進行輸入驗證 |
| 295 | + |
| 296 | +企業安全審查請參考 [Security Assessment Clarifications](./SECURITY_ASSESSMENT.md) — 涵蓋授權、資料保護、憑證管理、工具污染、AI 代理執行環境驗證的 23 項檢查清單。 |
| 297 | + |
| 298 | +## 路線圖 |
| 299 | + |
| 300 | +### 近期新增 |
| 301 | + |
| 302 | +| 工具 / 功能 | 解鎖場景 | 狀態 | |
| 303 | +|------|----------------|--------| |
| 304 | +| `maps_static_map` | 帶標記/路線的地圖圖片 — 多模態 AI 可「看見」地圖 | **完成** | |
| 305 | +| `maps_air_quality` | AQI、污染物 — 健康出行、戶外規劃 | **完成** | |
| 306 | +| `maps_batch_geocode` | 一次地理編碼最多 50 個地址 — 資料增強 | **完成** | |
| 307 | +| `maps_search_along_route` | 沿路線搜尋地點,依繞路時間排序 — 旅行規劃 | **完成** | |
| 308 | +| `maps_explore_area` | 一次呼叫的社區概覽(組合工具) | **完成** | |
| 309 | +| `maps_plan_route` | 最佳化多站行程(組合工具) | **完成** | |
| 310 | +| `maps_compare_places` | 並排地點比較(組合工具) | **完成** | |
| 311 | +| `GOOGLE_MAPS_ENABLED_TOOLS` | 篩選工具以減少上下文用量 | **完成** | |
| 312 | + |
| 313 | +### 計畫中 |
| 314 | + |
| 315 | +| 功能 | 解鎖場景 | 狀態 | |
| 316 | +|---------|----------------|--------| |
| 317 | +| `maps_place_photo` | 地點照片供多模態 AI 使用 — 「看見」餐廳氛圍 | 計畫中 | |
| 318 | +| 語言參數 | 所有工具支援多語言回應(ISO 639-1) | 計畫中 | |
| 319 | +| MCP Prompt Templates | Claude Desktop 中的 `/travel-planner`、`/neighborhood-scout` 斜線指令 | 計畫中 | |
| 320 | +| Geo-Reasoning Benchmark | 10 場景測試套件,衡量 LLM 地理空間推理準確度 | 研究中 | |
| 321 | + |
| 322 | +### 我們在建構的應用場景 |
| 323 | + |
| 324 | +以下是驅動工具開發方向的真實場景: |
| 325 | + |
| 326 | +- **旅行規劃** — 「規劃東京一日遊」(geocode → search → directions → weather) |
| 327 | +- **房地產分析** — 「分析這個社區:學校、通勤、洪水風險」(search-nearby × N + elevation + distance-matrix) |
| 328 | +- **物流優化** — 「從倉庫出發,最佳化這 12 個配送地址的路線」(plan-route) |
| 329 | +- **外勤銷售** — 「拜訪芝加哥 6 個客戶,最小化車程,找午餐地點」(plan-route + search-nearby) |
| 330 | +- **災害應變** — 「最近有開的醫院?我在洪水區嗎?」(search-nearby + elevation) |
| 331 | +- **內容創作** — 「Austin 前 5 社區的餐廳密度和機場距離」(explore-area + distance-matrix) |
| 332 | +- **無障礙** — 「輪椅可達的餐廳,避開陡坡路線」(search-nearby + place-details + elevation) |
| 333 | + |
| 334 | +## 更新日誌 |
| 335 | + |
| 336 | +見 [CHANGELOG.md](./CHANGELOG.md)。 |
| 337 | + |
| 338 | +## 授權 |
| 339 | + |
| 340 | +MIT |
| 341 | + |
| 342 | +## 貢獻 |
| 343 | + |
| 344 | +歡迎社群參與和貢獻! |
| 345 | + |
| 346 | +- 提交 Issue:回報 bug 或提供建議 |
| 347 | +- 建立 Pull Request:提交程式碼改進 |
| 348 | +- 文件:協助改善文件 |
| 349 | + |
| 350 | +## 聯絡 |
| 351 | + |
| 352 | +- Email: [reahtuoo310109@gmail.com](mailto:reahtuoo310109@gmail.com) |
| 353 | +- GitHub: [CabLate](https://github.com/cablate/) |
| 354 | + |
| 355 | +## Star History |
| 356 | + |
| 357 | +<a href="https://glama.ai/mcp/servers/@cablate/mcp-google-map"> |
| 358 | + <img width="380" height="200" src="https://glama.ai/mcp/servers/@cablate/mcp-google-map/badge" alt="Google Map Server MCP server" /> |
| 359 | +</a> |
| 360 | + |
| 361 | +[](https://www.star-history.com/#cablate/mcp-google-map&Date) |
0 commit comments