Skip to main content
Glama
liyufengrex

local-maps-mcp

by liyufengrex

local-maps-mcp

用一个小项目,学会开发本地 MCP 服务

一个跑在 macOS 上的本地 MCP 服务。在 AI 工具里配置后说「在地图里搜索西湖景区」,它会打开系统自带的「地图」并搜索这个地点。

源码:https://github.com/liyufengrex/mcp_search_map

MCP 是什么

MCP(Model Context Protocol,模型上下文协议)让 AI 工具调用外部能力。模型负责理解你的话并决定调用哪个工具;MCP 服务把能力登记成工具,执行后把结果交还模型;真正的工作由后面的系统完成,例如打开地图或读取文件。

本地服务由 AI 工具启动,双方用标准输入和标准输出通信,这叫 stdio。日志写到标准错误,标准输出只放协议消息。模型依据工具的名称、说明和参数决定何时调用。

Related MCP server: apple-mcp

本项目做什么

本项目只提供一个工具 search_map。参数 query 是地点或地址。服务检查参数后,调用 macOS 打开系统地图并发起搜索,然后返回「已向系统地图发送搜索请求:……」。搜索结果以地图窗口为准。不需要地图 API Key。

环境:macOS,Node.js 20 或更高。

文件怎么分工

协议入口和地图动作分开:前者向 AI 暴露工具,后者只负责打开地图。

src/index.js           注册 search_map,用 stdio 等待 AI 工具连接
src/maps.js            检查参数、生成地图链接、调用 open
test/maps.test.js      检查链接编码和命令参数
test/server.test.js    用 MCP 客户端检查工具是否能被调用
.cursor/mcp.json       一种客户端的配置示例(例如Cursor)
package.json           依赖、npm start 与 npm test

src/index.js 使用官方 SDK @modelcontextprotocol/server 创建服务,并用 Zod 描述参数。src/maps.js 不处理 MCP 消息。测试用模拟命令代替真正的 open,所以 npm test 不会反复打开地图。

npm install
npm test

平时由 AI 工具启动。单独执行 npm start 时,进程会停住等待连接,用 Ctrl+C 结束。

功能怎么实现

  1. AI 工具启动 src/index.js,StdioServerTransport 开始等待调用。

  2. createServer() 用 registerTool() 登记 search_map。query 是必填字符串,说明里写了「在地图里搜索地点时使用」。

  3. 调用到达后,处理函数把 query 交给 openMapSearch()。成功返回搜索已发送;失败返回 isError: true,例如空查询、非 macOS,或系统命令失败。

  4. normalizeQuery() 去掉首尾空格,空内容会被拒绝。

  5. buildMapSearchUrl() 按 Apple Map Links 的 q 参数生成链接。q 就是搜索框里的文字,并用 encodeURIComponent() 编码中文、空格和 &、#:

https://maps.apple.com/?q=%E8%A5%BF%E6%B9%96%E6%99%AF%E5%8C%BA

q 是系统地图长期支持的搜索参数。macOS 15.4 及更高版本还可以使用 Adopting unified Maps URLs 里的 /search?query=,本项目选择 q,使更早的系统也能打开搜索。

  1. openMapSearch() 用 execFile() 执行下面的命令。参数是数组,搜索词只出现在编码后的链接里,最长等待 10 秒:

/usr/bin/open -b com.apple.Maps <地图链接>

-b com.apple.Maps 指定打开系统「地图」。open 返回表示系统已经收下请求。

在 AI 工具里配置

AI 工具需要一份配置,写明服务名、用来启动的 Node.js,以及入口文件 src/index.js。各工具的配置文件位置不同,本地服务通常都使用 command 和 args。下面以 Cursor 为例。

Cursor 会合并项目级和用户级配置;同名时以项目级为准。市场里的现成 MCP 可以在 Customize → MCPs 里点 Add to Cursor。本项目是本地服务,使用下面的配置文件。

位置

文件

生效范围

项目级

.cursor/mcp.json

打开本项目时

用户级

~/.cursor/mcp.json

这台电脑上的所有项目

本仓库已经写好项目级配置。添加到用户级配置时,保留文件里原有的其他服务。

{
  "mcpServers": {
    "local-maps-mcp": {
      "command": "node",
      "args": ["${workspaceFolder}/src/index.js"]
    }
  }
}

${workspaceFolder} 是当前项目目录。如果 Cursor 从图形界面启动时找不到 node,把 command 改成终端里 nvm which current 打印出的绝对路径。切换 Node 版本后同步修改,再刷新 MCP。

安装发布后的 npm 包时,入口不再是项目里的源文件:

{
  "mcpServers": {
    "local-maps-mcp": {
      "command": "npx",
      "args": ["-y", "local-maps-mcp"]
    }
  }
}

用 Cursor 打开本项目,进入 Customize → MCPs。local-maps-mcp 已连接时,工具列表里有 search_map。改完配置或代码后,在这里刷新该服务。

示例:在地图里搜索西湖景区

例如在 Cursor 的 Agent 对话里输入:

在地图里搜索西湖景区

模型会调用 search_map,参数为 { "query": "西湖景区" }。系统地图来到前台并接收这次搜索,对话里出现:

已向系统地图发送搜索请求:西湖景区

补充:发布与安装

发布和安装都指定官方源 https://registry.npmjs.org。登录时 npm 会要求输入动态验证码,发布时可能还会再要一次。

在项目目录发布:

npm login --registry https://registry.npmjs.org
npm publish --registry https://registry.npmjs.org

看到 + local-maps-mcp@1.0.0 表示发布成功。

发布成功后可进行全局安装:

npm install -g local-maps-mcp --registry https://registry.npmjs.org

检查是否安装完成:

command -v local-maps-mcp

这条命令打印出可执行文件路径,就表示当前终端可以找到它。随后在 AI 工具的配置里把启动命令写成 local-maps-mcp。

Available Tools

1 tool
search_map在系统地图中搜索A

在这台 Mac 的系统地图(Apple 地图)中搜索地点或地址。当用户要求在地图里搜索、查找或打开某个地点时使用。此工具只打开系统地图并发起搜索,不会读取搜索结果,也不能确认地点是否存在或地图是否已经显示完成。

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes要搜索的地点名称或地址,例如“杭州西湖”。去掉首尾空格后不能为空。

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

在没有 annotations 的情况下,它说明了一个关键的行为事实:该工具只打开系统地图并发起搜索,不会读取搜索结果,也不能确认地点是否存在,或地图是否已经显示完成。这在有副作用的操作中,是很有价值的预期管理。但它没有说明所需的 macOS 自动化权限,也没有说明地图应用无法启动时会发生什么。

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

三句话,先说明用途,再说明何时使用,最后说明限制,没有一句多余的废话。关键限制部分放在末尾,前面的说明已经足够清楚。

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

只有一个参数,没有 annotations,也没有 output schema,description 已经说明了主要风险:无法确认搜索结果。对于一个打开应用并执行搜索的工具,还缺少 macOS 自动化权限,以及地图未安装或未运行时的失败行为。

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

schema 的说明覆盖率是 100%,而且 query 的 schema 已经写明了“地点名称或地址”以及“去掉首尾空格后不能为空”的约束。description 没有给 query 增加任何语义,因此适用基线 3 分。

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

用具体的动词和资源说明了动作:在“这台 Mac 的系统地图(Apple 地图)”中搜索地点或地址。正文还点出了工具名的范围,明确这不是一个通用的网络搜索工具。

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

明确给出了触发条件:当用户要求“在地图里搜索、查找或打开某个地点”时使用。由于不存在同类工具,所以不需要排除其他替代选项;不过它既没有说明要避开的近似场景(例如“获取路线”),也没有说明前置条件。

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev1.0.0
    • First observedsearch_map

TDQS

A4.1/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so there is no possibility of confusing it with another tool. Its purpose—opening Apple Maps and initiating a place/address search—is clearly distinct.

Naming Consistency5/5

The single tool name `search_map` follows a clear verb_noun convention. With only one tool, there is no inconsistency across the set.

Tool Count3/5

A one-tool server is borderline thin for a local maps integration. It is narrowly scoped but leaves little surface for common map-related operations.

Completeness2/5

The server can only open the system map and initiate a search; it cannot read results, confirm place existence, get details, or provide directions. These are significant gaps for an agent relying on map search.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers