你在 Cursor 里加了一个 MCP server——filesystem、GitHub、或自定义的——状态点一直红。或者变绿了,可聊天里就是没工具出现。或者刚启动连上了,几分钟后又掉。Cursor 的 MCP 层很薄:拉起一个进程,走 stdio(或远程 HTTP/SSE 端点)讲 JSON-RPC,然后把 server 声明的工具注册进来。出问题几乎都集中在四处:spawn(路径不对、runtime 不在)、配置文件(一个 JSON typo 让整个文件作废)、handshake(server 把文本漏到了 stdout)、或 transport(远程 URL 用了 stdio 格式,或反过来)。
能解决大多数情况的最快一招: 打开最新的 MCP 日志(Output 面板,Cmd/Ctrl + Shift + U,再从下拉里选 MCP Logs),读第一行报错,然后(a)给 command 用绝对路径,(b)把 mcp.json 丢给 python3 -m json.tool 查有没有多余逗号。截至 2026 年 6 月,这两步能覆盖绝大部分断连。
各项东西在哪(2026 年 6 月)
2026 年初 Cursor 把面板改了名。当前路径如下:
- 设置面板:
Cmd/Ctrl + Shift + J打开 Cursor Settings,对应区块现在叫 Tools & MCP(旧版本叫 Features → MCP)。还有一个总开关 Enable MCP servers,在某些安装里默认是关的——先确认它开着。 - 用 UI 加 server: Tools & MCP → + Add New MCP Server,弹出三个字段:Name、Transport Type(
stdio/SSE/Streamable HTTP)、Command or URL。它会替你写进mcp.json。 - 配置文件(全局):
~/.cursor/mcp.json,对所有项目生效。 - 配置文件(项目): 仓库根目录的
.cursor/mcp.json,可随团队共享。两个都存在时两个都加载。 - 日志: Output 面板(
Cmd/Ctrl + Shift + U)→ MCP Logs 频道。真正的错误字符串(ENOENT、JSON parse error、鉴权失败、崩溃)都在这里。
常见原因
按命中率从高到低。
1. 一个 JSON typo 让整个文件作废
一个多余的逗号、漏掉的引号、或不配对的花括号,会让 Cursor 直接忽略整个 mcp.json——没有弹窗,所有 server 一起消失。这是”什么都不出现”最常见的原因。
怎么判断: 别靠肉眼,用解析器跑:
python3 -m json.tool ~/.cursor/mcp.json # 或:jq . ~/.cursor/mcp.json
报错并给出行号,就是它。如果能把文件格式化打印出来,说明 JSON 没问题,bug 在别处。
2. 命令不在 PATH 上(spawn ENOENT)
你配了 "command": "npx" 或 "command": "uvx",但从 Dock / 开始菜单启动的 Cursor 不会加载你的 shell rc,于是 nvm/fnm/asdf/Homebrew 加的 PATH 不在里面。哪怕同样的命令在终端能跑,server 也起不来。
怎么判断: 在 MCP Logs 里找 spawn npx ENOENT、spawn uvx ENOENT、或 command not found。出现这串字符,每次都是这个 bug。
3. Stdio server 把日志打到了 stdout
MCP stdio server 的 stdout 必须只走 JSON-RPC 帧。banner、log、warning 一旦出现在 stdout 上,Cursor 读到非法 JSON 就断开。
怎么判断: 在终端手动跑一遍 server 命令。stdout 上有任何非 JSON 内容就是这个 bug。所有诊断信息都该走 stderr。
4. mcp.json 里 transport 格式写错
远程 server 要 url(外加 headers);本地 server 要 command + args。混着写——stdio 格式里塞 url,或远程条目里写 command——会静默失败。
怎么判断: 打开 mcp.json。Stdio 条目用 command / args / env;远程条目用 url / headers,transport 是 streamable-http 或 sse。UI 里的 Transport Type 必须和这些 key 对得上。
5. server 需要的环境变量 Cursor 没传
GitHub 本地 server 要 GITHUB_PERSONAL_ACCESS_TOKEN,自定义 server 要 API key。只在 shell rc 里设没用——spawn 出来的进程只看得到 env 里的(或 envFile 指向的文件里的)。
怎么判断: 用同一份环境变量在 Cursor 外手跑 server 命令。外面能跑、Cursor 里不行——就是 env 没传。
6. 工具加载了但在聊天里被禁用
Tools & MCP 显示绿、工具数也对,可模型从不调用工具。Cursor 在聊天面板顶部的工具列表里给每个工具单独留了开关,新工具可能默认是关的。
怎么判断: 打开聊天面板顶部的工具列表。你的 server 工具在列表里但开关是关的——把它打开。
7. Cursor 缓存了一次失败的 handshake
底层问题修好后,Cursor 有时还把 server 卡在 failed 状态,必须手动 toggle。
怎么判断: Tools & MCP → 把 server 关掉,等约 3 秒,再开。这下连上了,就是缓存的锅。
你属于哪一类?
| UI 里的症状 | 最可能的原因 | 跳到 |
|---|---|---|
| 一个 server 都不出现 | JSON typo 让文件作废,或总开关关了 | 原因 1、面板开关 |
某个 server 红,日志里 spawn ... ENOENT | 命令不在 PATH | 原因 2、Step 2 |
| 绿点过一会就掉 | server 崩了(常是 stdout 漏日志) | 原因 3、Step 4 |
| 绿点但工具数 = 0 | handshake 失败 / transport 写错 | 原因 4、Step 4 |
| 绿点、有工具、从不被调用 | 工具在聊天里被禁用 | 原因 6、Step 7 |
| 远程 URL 返回 HTML/401/404 | URL 或鉴权 header 不对 | 原因 4、Step 5 |
开始前
- 弄清楚你的 server 是 stdio(本地进程)还是远程(HTTP/SSE),两者配置完全不同。
- 把 server 的 README 放手边,照着写
command、args、env 变量、或url。 - 一次只调一个 server,两个一起调痛苦翻倍。
一步一步修复
Step 1:先验 JSON,再在 Cursor 外把 server 跑起来
先解析文件(python3 -m json.tool ~/.cursor/mcp.json)。然后把 command 和 args 复制到终端跑。健康的 stdio server 应该 stdout 空(或只有 JSON),然后挂着等输入。立刻崩——bug 在 server 自己身上,跟 Cursor 无关。
Step 2:command 用绝对路径
把 "npx" 换成全路径。用 which npx(Windows 上 where npx)查到后粘进去。uvx、python、node 同理。这是修 spawn ENOENT 最稳的一招。
{
"mcpServers": {
"filesystem": {
"command": "/Users/you/.nvm/versions/node/v22.14.0/bin/npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
}
}
}
Step 3:env 显式传(或用 envFile)
server 需要的所有东西都要写在条目的 env 里,或用 envFile 从文件读。Cursor 给 spawn 出来的 MCP 进程不会继承你 shell 的环境。
{
"mcpServers": {
"github-local": {
"command": "/usr/local/bin/docker",
"args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_..." }
}
}
}
注意环境变量名是 GITHUB_PERSONAL_ACCESS_TOKEN。旧的 @modelcontextprotocol/server-github npm 包已弃用;GitHub 现在提供官方 server(上面的 Docker 镜像,或 Step 5 的托管远程版)。
Step 4:去 MCP 日志里看 handshake
Output 面板(Cmd/Ctrl + Shift + U)→ MCP Logs,搜 server 名。你想看到 initialize 请求和成功的响应。常见失败:
Failed to parse JSON/Unexpected token——server 把文本漏到 stdout 了(把日志改成只走 stderr)。spawn ... ENOENT——回 Step 2。0 tools或No tools or prompts——handshake 完成了但 server 没声明任何工具;检查 server 自己的启动参数。
Step 5:远程 server 优先用托管端点,并先验一下
GitHub 的托管 server 最省事——不用 runtime、不用 Docker。用 url 格式加 bearer header:
{
"mcpServers": {
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"headers": { "Authorization": "Bearer github_pat_..." }
}
}
}
在怪 Cursor 之前先独立验证端点:
curl -X POST https://api.githubcopilot.com/mcp/ \
-H "Authorization: Bearer github_pat_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
健康的响应是一个含 serverInfo 和 capabilities 的 JSON。返回 HTML、401/403、或 404,说明 URL 或 token 不对(重新生成带正确 scope 的 PAT)。如果 server 用 OAuth 而非静态 token,Cursor 会处理浏览器授权流程,并注册回调地址 cursor://anysphere.cursor-mcp/oauth/callback。
Step 6:toggle,然后完全重启
Tools & MCP → 把 server 关再开。还不生效就完全退出 Cursor(Cmd+Q / 从托盘退出——不是只关窗口),重新打开。MCP server 只在启动和 toggle 时 re-spawn,存盘不会。
Step 7:在聊天里把工具打开
打开聊天面板顶部的工具列表,找到你的 server,把 server 级和工具级开关全部打开。某些 Cursor 版本新工具默认是关的,看起来和 server 坏了一模一样。
怎么验证修好了
- Tools & MCP 显示绿点、工具数大于 0。
- MCP Logs 里
initialize成功,后面没有 parse 报错。 - 在聊天里发一个该触发工具的 prompt(比如「List my GitHub repos」),看有没有工具调用卡片执行并返回结果。
- 退出再重启 Cursor,确认 server 自动重连、工具数一致。
长期预防
- 给 server 钉死版本(如
@modelcontextprotocol/server-filesystem@2026.1.0),别用浮动 tag,免得上游一次坏发布把你的环境拖垮。 - 把
mcp.json纳入版本管理但不含 secret;token 用envFile或 shell wrapper 加载。 - CI 加一步
python3 -m json.tool .cursor/mcp.json,typo 进不来。 - 把需要的 env 变量和 scope 写到 README 的 MCP 配置块旁边。
- 厂商有托管/远程版就优先用——比本地 runtime 少很多变数。
容易踩的坑
- Cursor 开着改
mcp.json还指望它 hot reload。它只在启动和 toggle 时读。 - 把 user 级
~/.cursor/mcp.json和 workspace 级.cursor/mcp.json搞混——两个都存在时两个都加载,过时的全局条目还会盖掉你的项目条目。 - stdio server 在 stdout 上打了一行「Server started on port 3000」就把协议破坏了。
- GitHub server 要
GITHUB_PERSONAL_ACCESS_TOKEN,你却用了GITHUB_TOKEN。 - 以为 Cursor 会发现启动后新加的工具——不会,重启。
常见问答
- mcp.json 在哪里? 全局是
~/.cursor/mcp.json,项目里是.cursor/mcp.json。两个都在就两个都加载。 - Stdio 还是远程选哪个? 本地进程(filesystem、git)用 stdio。托管或团队共享 server 用远程(HTTP/SSE),比如 GitHub 的
https://api.githubcopilot.com/mcp/。远程能绕开 PATH 和 runtime 的麻烦。 - 改完文件整个列表空了,为什么? 几乎都是 JSON 语法错误让文件作废。跑
python3 -m json.tool ~/.cursor/mcp.json,再确认总开关 Enable MCP servers 是开着的。 - 为什么几分钟后状态点变红? server 进程退出了。开 MCP Logs 或手跑命令,在 stderr 上看崩溃原因。
- 在终端能跑、Cursor 里不行。 典型 PATH 缺失——从 Dock 启动的 Cursor 不加载 shell rc。给
command用绝对路径(Step 2)。 - MCP 配置能和团队共享吗? 能——提交
.cursor/mcp.json,secret 留外面(用envFile),把需要的 env 变量和 scope 在 README 里写清楚。