你在 Cursor 里新加了一个 MCP server——filesystem、GitHub、或自定义的——状态点一直红。或者显示绿了,可 Composer 里就是没工具出现。或者刚启动时连上了,几分钟后又掉。Cursor 的 MCP 集成本身很薄:拉起一个进程,走 stdio(或 HTTP)讲 JSON-RPC,然后把 server 声明的工具注册上来。出问题几乎都是:spawn 失败(路径不对、runtime 不在)、handshake 出错(JSON 不对、schema 不对)、或者 transport 选错(stdio 和 HTTP 混了)。自底向上一层层排,肯定找得到。
常见原因
按命中率从高到低。
1. 命令或路径不在 PATH 上
你配的是 "command": "npx" 或 "command": "uvx",但 Cursor 在 macOS 上继承的 PATH 被裁剪过,找不到命令。server 根本起不来。
怎么判断:打开 ~/.cursor/logs/ 最新日志,grep spawn ENOENT 或 command not found,就是它。
2. Stdio server 把日志打到 stdout
MCP stdio server 的 stdout 必须只走 JSON-RPC 帧。server 如果在 stdout 上输出 banner、log、warning,Cursor 看到的是非法 JSON,直接断开。
怎么判断:在终端手动跑一遍 server 命令。stdout 上出现任何非 JSON 内容,就是这个 bug。日志全部应该走 stderr。
3. mcp.json 里 transport 写错
写的是 HTTP URL,但用了 stdio 的格式(或反过来)。Cursor 0.46+ 两种都支持,但 JSON key 不一样——stdio 用 command/args,HTTP 用 url。
怎么判断:打开 ~/.cursor/mcp.json。Stdio 要 command + args,HTTP 要 url(一般还要 type: "http")。两种混着写就静默失败。
4. Server 需要的环境变量 Cursor 没传
GitHub MCP 要 GITHUB_TOKEN,自定义 server 经常要 API key。你只在 shell rc 里设了,没在 mcp.json 的 env 里加,spawn 出来的进程看不到。
怎么判断:用同一份环境变量在 Cursor 外手跑 server 命令。外面能跑、Cursor 里不行——就是 env 没传。
5. 工具加载了但 Composer 里被禁用
设置 → MCP 显示绿、工具数也对,可 Composer 从不调用。Composer 里每个 MCP server 都有一个对话级开关藏着。
怎么判断:Composer 里点底部工具图标。MCP server 在列表里但开关是关的——就是它。
6. Cursor 缓存了一次失败的 handshake
底层问题修好了,但 Cursor 还把 server 卡在 failed 状态里,必须手动 off 再 on。
怎么判断:设置 → MCP → 把 server 关 3 秒、再开。这下能用了,就是缓存的锅。
开始前
- 弄清楚你的 server 是 stdio 还是 HTTP,配置完全不同。
- 把 server 的 README 放手边,照着写
command、args、env 变量。 - 一次只调一个 server,两个一起调痛苦翻倍。
需要收集的信息
- Cursor 版本(Help → About),MCP 在 0.45+ 才稳。
- OS 和 shell。
mcp.json路径(全局是~/.cursor/mcp.json,项目级是工作区里的.cursor/mcp.json)。~/.cursor/logs/里最新那条日志(按 mtime 排)。- Server 命令和 args,照
mcp.json原样。 - 在新终端里手跑那条命令的输出。
- HTTP server 的话,用
curl打一次initialize请求看响应。
一步一步修复
Step 1:先在 Cursor 外把 server 跑起来
把 mcp.json 里的 command 和 args 复制到终端跑。Server 应该 stdout 空(或只有 JSON),然后挂着等输入。直接崩——bug 在 server 自己身上,跟 Cursor 没关系。
Step 2:command 用绝对路径
把 "npx" 换成全路径:/Users/you/.nvm/versions/node/v20.11.0/bin/npx。uvx、python、node 同理。绕开 PATH 问题。
{
"mcpServers": {
"github": {
"command": "/usr/local/bin/npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "ghp_..." }
}
}
}
Step 3:env 显式传
Server 需要的所有东西都要写在 mcp.json 的 env 里。Cursor 给 spawn 出来的 MCP 进程不会继承你 shell 的环境。
Step 4:去日志里看 handshake
打开 ~/.cursor/logs/ 最新文件,搜 server 名。应该看到 initialize 请求和响应。如果看到 Failed to parse JSON 或 Unexpected token,就是 server 把垃圾打到 stdout 了——把日志改成只输出到 stderr。
Step 5:HTTP server 先 curl 验一下
curl -X POST https://your-server.example.com/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
应该回一个带 serverInfo 和 capabilities 的 JSON。回 HTML、404、CORS 错——URL 或鉴权不对。
Step 6:toggle + reload
设置 → MCP → 把 server off 再 on。还是不行就 Cmd+Q 完全退出 Cursor(不是只关窗口),重新打开。MCP server 只在启动时 spawn。
Step 7:Composer 里把工具打开
打开 Composer,点工具图标,滑到你的 server,把 server 级和工具级开关全部打开。某些 Cursor 版本里新工具默认是关的。
怎么验证修好了
- 设置 → MCP 显示绿点、工具数 > 0。
- 在 Composer 里发一个该触发工具的 prompt,比如「List my GitHub repos」。
- 看聊天记录里有工具调用卡片,执行并返回结果就健康。
- 重启 Cursor,确认 server 自动重连。
长期预防
args里给 server 版本钉死:用@modelcontextprotocol/server-github@1.0.4,别用浮动版本。- 把
mcp.json(不含 secret)纳入版本管理,团队成员就有一致的 server 列表。 - 用
.env文件 + wrapper 脚本(load env 后 exec server),比把 secret 写进mcp.json干净。 - CI 加一步 JSON-parse
mcp.json,typo 进不来。 - 把需要的 env 变量写到项目 README 的 MCP 配置块旁边。
容易踩的坑
- Cursor 开着改
mcp.json还指望它 hot reload。它只在启动和 toggle 时读。 - 把 user 级
~/.cursor/mcp.json和 workspace 级.cursor/mcp.json搞混——两个都存在的话两个都加载。 - Server 在 stdout 上打了一行「Server started on port 3000」就把协议破坏了。
- HTTP 用 transport 时忘了写
type: "http",默认成 stdio、URL key 被忽略。 - 以为 Cursor 启动后新加的工具会自动出现——不会,重启。
常见问答
- mcp.json 在哪里? 全局是
~/.cursor/mcp.json,项目里是.cursor/mcp.json。两个都在就两个都加载。 - Stdio 还是 HTTP 选哪个? 本地进程(filesystem、git)用 stdio。托管或团队共享 server 用 HTTP。
- 为什么几分钟后状态点变红? 多半 server 进程静默退出了。看 stderr 或手跑一遍找崩溃原因。
- MCP 配置能和团队共享吗? 能,把
.cursor/mcp.json提交到仓库,secret 留外面,env 变量在 README 里说清楚。 - Cursor 支持完整 MCP 规范吗? 大致支持。0.46 起 tools 和 resources 覆盖到位,prompts 和 sampling 还不够成熟。