配完 MCP,客户端里那一行配置看着没问题,但跟 Agent 说"用 XX 工具",它回你一句"我没有这个工具"。
这种情况我遇到过不止一次,而且每次的原因都不一样。它麻烦的地方在于:失败是静默的——配置文件不会报错,客户端也不会弹窗,只是那个工具凭空消失了。
下面 6 步是按"从最可能到最不可能"排的,每步都给了可以直接复制的自查命令。前 5 步是排查,第 6 步才是真正该做的验证。
说明:不同客户端的配置文件位置不一样(Cursor、Claude Code、其他支持 MCP 的客户端各有各的约定),
具体路径以你所用客户端的官方文档为准。这篇只讲跟客户端无关的那部分——也就是换任何客户端都会踩的坑。
一、先确认它是"没起来",还是"起来了但没注册"
MCP server 是客户端的子进程:客户端启动时拉起它,退出时带走它。所以你不能像查后台服务那样去查它——客户端没开,它就不存在。
自查:
# 客户端正在运行时,看看有没有对应的 node 进程psaux|grep-i"mcp"|grep-vgrep如果客户端开着但这里什么都没有,说明根本没拉起来,直接跳到第三步看 Node 版本。
如果有进程,说明它起来了,问题在注册环节(第二步)。
二、改完配置,客户端重启了吗
这是最蠢也最常见的一条。MCP server 在客户端启动时才被加载,配置文件改完不重启,改动不会生效——而且同样没有任何提示。
关掉客户端,完整退出(macOS 上注意是 Cmd+Q 而不是关窗口),重开,再看工具列表。
三、Node 版本够不够
很多 MCP server 是用npx -y <包名>拉的,跑在你本机的 Node上。包的engines字段要求多少,你本机就得是多少。
自查:
node-v以 ai-browser 为例,package.json里写的是engines: { node: ">=18" },低于 18 时 npm 会报 EBADENGINE(默认是警告,开了engine-strict就是直接装不上)。
如果你用 nvm / fnm 之类的版本管理器,还要注意一件事:GUI 客户端读到的node可能和你在终端里看到的不一样。图形界面应用不加载 shell 的 rc 文件,PATH是系统默认的——终端里node -v是 20,客户端拉起来的可能是另一个版本,或者干脆找不到 node。
要绕开这个差异,三条路选一条:
command写npx 的绝对路径(which npx的输出),args原样不动;command写node 的绝对路径(which node的输出),args换成 MCP server 脚本的绝对路径:["<仓库绝对路径>/src/main/mcp_server.js"];- 不动
command,在配置里补env:{ "PATH": "<which node 的输出去掉末尾 /node>:/usr/bin:/bin" }。
⚠️别把 node 的绝对路径和 npx 的 args 混着用:-y是 npx 的参数,node 不认,会直接报bad option: -y。
四、npx -y的缓存:第二次跑的和你以为的不是同一份
npx -y <包名>不带版本号时会优先用本地缓存。缓存里是旧版,你以为装的是新版——这类问题在"昨天还好好的,今天突然不行"的场景里特别常见。
自查:
# 看最新发布版是哪一版npmview<包名>version# 强制拉最新npx-y<包名>@latest--version要锁版本就在配置里写死:@glittering0717/ai-browser@2.1.1。
要清缓存:npm cache clean --force。
五、端口被占了(只针对自带服务端口的 MCP server)
有些 MCP server 不只是 stdio 管道,它还会在本机开一个端口做别的通信。以 ai-browser 为例,它默认监听9223,而且只绑 127.0.0.1——因为那个 JSON-RPC 端口本身没有鉴权,绑 0.0.0.0 等于把你的浏览器和登录态开放给局域网里的所有人。
端口被别的进程占了,server 会起不来,但报错常被吞掉。
自查:
lsof-nP-iTCP:9223-sTCP:LISTEN有输出不等于有问题——先看COMMAND那一列:
- 如果是
Electron/ ai-browser,说明它本来就在跑,这是正常状态,MCP server 会直接复用它,别杀(杀了会连登录态一起丢); - 如果是别的进程占了,才需要停掉它,或者换端口。
换端口用AI_BROWSER_PORT这个环境变量,而且应用和客户端配置两边要设成同一个值——只设一边会连不上。
六、最后一步:别问"它在不在",让它干一件真事
前面五步走完,工具列表里能看到它了——但这不等于它真的能用。
"工具列表里有它"只说明注册成功。真正要验的是:它能不能打开页面、能不能读懂结构、点了之后有没有真的生效。这三件事任何一件断了,它都是个摆设。
所以我用的验证不是 hello world,而是一个有约束的目标:要登录、点了之后状态会变、结果肉眼可见。
用 ai-browser 打开 https://github.com/Glittering/ai-browser,
在语义树里找到 role 是 button、label 是 Star 的那条节点,拿到它的data-ai-id(形如e:button-12),
用browse_act点它,再用browse_diff看 verdict 是不是changed。
注意:没登录 GitHub 的话这步会失败——这是设计的一部分,不是 bug。
这里有个容易踩的点:target收的是data-ai-id,不是按钮上的可见文字——直接把 “Star” 填进 target 会点空。顺序必须是"先读树拿到 id → 再用 id 行动"。
它一次回答三个问题:
| 验证点 | 如果失败说明什么 |
|---|---|
| 没登录就真的点不动 | 登录态没有接管——它起的是一个全新的空浏览器,不是你那个 |
| 能从语义树里按 role + label 找到目标 | 语义定位有效,不是靠坐标盲点 |
| diff 的 verdict 显式给出 changed / unchanged | 生效是有证据的,不是"我以为点了" |
不想给我点 star 也完全可以——把网址换成任何一个需要登录的页面、任何一个会改变状态的按钮,效果一模一样。这步的价值是那个"变化",不是那颗星。
换成你自己的目标,模板只有一句:
打开 <你的页面>,在语义树里找到 <某个点了之后状态会变的按钮>,拿到它的>三个值得单独说的坑
坑 1:工具说 success,页面什么都没变。
这是最贵的一类故障——Agent 信了继续往下走,错误在第三步之后才暴露。所以"生效没有"必须是工具原语(前后快照 diff),不能靠事后自查。坑 2:session 到底存哪儿。
需要复用登录态的 MCP server,一定会落一个 userData 目录。ai-browser 存在~/.ai-browser,也可以靠AI_BROWSER_USER_DATA环境变量改。不知道这个路径,你就没法判断"为什么上次登录的没了"。坑 3:工具快照是会话开始时拍的。
有些客户端在启动 MCP server 时就缓存了工具列表,运行中 server 侧新增或改名的工具不会出现在这一轮对话里。表现是"配置明明改对了,Agent 还是说没有"——第二步的重启就是解这个。最后
这套排查是通用的,跟具体哪个 MCP server 无关。我用来举例的是自己的项目ai-browser(一个把已登录的真实浏览器暴露给 Agent 的 MCP server,输入走语义树而不是截图):
- 仓库:https://github.com/Glittering/ai-browser(MIT)
- 一行装:
npx -y @glittering0717/ai-browser mcp平台边界先说清楚:桌面 App 的 dmg 只发了 macOS arm64;走上面那条
npx命令的话 Electron 按系统现拉,macOS 和 Linux 都实测过;Windows 标的是 experimental——纯 Electron + CDP,应该能跑,但没人验过,真跑通了麻烦回来说一声。排查清单里哪一步没覆盖到你的情况,把现象贴到 GitHub Discussions,我补齐。