背景

在 Claude Code 中通过 /mcp 查看,Anything Analyzer MCP 持续显示 Failed to reconnect to Anything Analyzer.netstat 看到 23816 端口在 LISTENING,应用进程没死,但 Claude Code daemon 进程与 23816 之间反复建立/断开连接。本文记录从现象到根因的完整排查过程,以及最终的修复方法。

案例日期:2026-07-06
应用版本:Anything Analyzer 3.6.50
项目仓库:mouseww/anything-analyzer

一、现象

Failed to reconnect to Anything Analyzer.

应用进程在跑、端口在监听,但 MCP 调用全部 401。

二、排查路径(11 步定位)

步骤 命令 / 证据 结论
1. 看 .claude.json 里的 MCP 配置 ~/.claude.json:596-602 之前没有 headers
2. 看应用是否在跑 tasklist → Anything Analyzer.exe PID 34056 在跑,启动于 12:59:36
3. 端口是否在听 netstat -ano | grep 23816 0.0.0.0:23816 LISTENING
4. 直接 curl 探测 curl http://localhost:23816/mcp HTTP 401 + {"error":"Unauthorized: invalid or missing token"}
5. CORS 头提示可接受的 header 名 Access-Control-Allow-Headers: Content-Type, Authorization, mcp-session-id, mcp-protocol-version 只能是 Authorization
6. 解包 app.asar 看主进程 npx @electron/asar extract app.asar app_extracted 定位到 out/main/index.js:6527-6533
7. 读验证逻辑 authHeader !== \Bearer ${authToken}`` 严格字符串相等比较
8. 找 token 配置位置 getMCPServerConfigPath() 返回 userData/mcp-server-config.json Electron userData
9. 读 token 配置文件 %APPDATA%\anything-analyzer\mcp-server-config.json authToken 与 Claude Code 配置完全一致
10. 关键证据 — 时间戳 配置 mtime = 13:30,应用进程 StartTime = 12:59:36 配置改了,但应用没重启
11. 验证 saveConfig 行为 electron.ipcMain.handle("mcp-server:saveConfig") 只处理 enabled 状态切换,不重启 server

三、根因

改了 mcp-server-config.json 里的 authToken 之后,Anything Analyzer 的 MCP server 不会自动重启

源码 out/main/index.jsmcp-server:saveConfig handler 只在 enabled 状态翻转时 stop+init,token 改了会写盘但运行中的 HTTP server 内存里 authToken 仍是启动时加载的旧值

// out/main/index.js:5816-5828(问题源头)
electron.ipcMain.handle("mcp-server:saveConfig", async (_event, config) => {
  saveMCPServerConfig(config);
  // if (config.enabled && !isMCPServerRunning()) { initMCPServer(...) }
  // else if (!config.enabled && isMCPServerRunning()) { stopMCPServer() }
  // ⚠️ 没有 "token changed → restart" 的分支
});

所以即使配置文件和 .claude.json 两边的 token 完全一致,只要不重启应用,MCP 端点就会一直 401。

四、修复

方式 1:重启整个应用(推荐)

Stop-Process -Name 'Anything Analyzer' -Force
Start-Sleep -Seconds 2
Start-Process -FilePath 'D:\develop\Anything Analyzer\Anything Analyzer.exe'
Start-Sleep -Seconds 8

Git Bash 调 taskkill 会把 /F 当路径处理,要走 cmd /c 或 PowerShell。

方式 2:UI 内关/开 MCP 开关(不退整个应用)

在 AnythingRegister 窗口里:

  1. 把 MCP server 开关关掉 → 触发 stopMCPServer
  2. 等几秒
  3. 打开 → 触发 initMCPServer,重新读 mcp-server-config.json

五、验证

# 1. 端口应回到 LISTENING
netstat -ano | grep 23816

# 2. 初始化 MCP session,200 = 通
curl -i -X POST \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl-test","version":"0.0.1"}}}' \
  http://localhost:23816/mcp

成功响应:

HTTP/1.1 200 OK
mcp-session-id: 4df684ac-4aff-446b-8487-e6610dfc55d9
content-type: text/event-stream

event: message
data: {"result":{"protocolVersion":"2025-03-26",...,"serverInfo":{"name":"anything-analyzer","version":"1.0.0"}},"jsonrpc":"2.0","id":1}

六、关键源码摘录

Token 验证逻辑 — out/main/index.js:6527-6533

if (authEnabled && authToken) {
  const authHeader = req.headers["authorization"];
  if (authHeader !== `Bearer ${authToken}`) {
    res.writeHead(401, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ error: "Unauthorized: invalid or missing token" }));
    return;
  }
}
  • 严格 !== 字符串相等
  • 只有 authEnabled && authToken 都为真时才校验
  • Access-Control-Allow-Headers 显式只放行四个 header

Token 自动生成 — out/main/index.js:6043-6046

if (!config.authToken) {
  config.authToken = node_crypto.randomUUID();  // 首次启动自动生成 UUID
  saveMCPServerConfig(config);
}

七、最终配置示例

Claude Code 端(~/.claude.jsonmcpServers 块)

"Anything Analyzer": {
  "type": "http",
  "url": "http://localhost:23816/mcp",
  "headers": {
    "Authorization": "Bearer 9eff1cdd-70be-422f-891f-4f9ffcd5815a"
  }
}

Anything Analyzer 端(mcp-server-config.json)

{
  "enabled": true,
  "port": 23816,
  "authEnabled": true,
  "authToken": "9eff1cdd-70be-422f-891f-4f9ffcd5815a"
}

八、经验教训

  1. Anything Analyzer 改 MCP token 后必须重启应用 — 这是产品 bug,不是配置问题。
  2. Git Bash 调 Windows taskkill / start 会被转义 — 用 cmd //c 或 PowerShell。
  3. Electron app.asar 解包:npx @electron/asar extract app.asar app_extracted,可读 main 进程 bundle 找问题。
  4. 401 + invalid or missing token 时先 Access-Control-Allow-Headers 反推允许的 header 名,再读服务端源码确认验证规则。
  5. MCP HTTP 类型 + 401 的通用诊断顺序:应用在不在跑 → 端口在不在听 → curl 看错误消息 → CORS 头反推 header 名 → 配置文件 / 用户数据目录找 token → 比对配置 mtime 和进程 StartTime → 锁定「未重启」型问题。
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐