背景在 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之前没有 headers2. 看应用是否在跑tasklist→ Anything Analyzer.exe PID 34056在跑,启动于 12:59:363. 端口是否在听netstat -ano | grep 238160.0.0.0:23816 LISTENING4. 直接 curl 探测curl http://localhost:23816/mcpHTTP 401 {error:Unauthorized: invalid or missing token}5. CORS 头提示可接受的 header 名Access-Control-Allow-Headers: Content-Type, Authorization, mcp-session-id, mcp-protocol-version只能是Authorization6. 解包 app.asar 看主进程npx electron/asar extract app.asar app_extracted定位到out/main/index.js:6527-65337. 读验证逻辑authHeader ! \Bearer ${authToken}严格字符串相等比较8. 找 token 配置位置getMCPServerConfigPath()返回userData/mcp-server-config.jsonElectron userData9. 读 token 配置文件%APPDATA%\anything-analyzer\mcp-server-config.jsonauthToken与 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.js的mcp-server:saveConfighandler 只在enabled状态翻转时 stopinit,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 8Git Bash 调taskkill会把/F当路径处理,要走cmd /c或 PowerShell。方式 2:UI 内关/开 MCP 开关(不退整个应用)在 AnythingRegister 窗口里:把 MCP server 开关关掉→ 触发stopMCPServer等几秒再打开→ 触发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-6533if (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显式只放行四个 headerToken 自动生成 —out/main/index.js:6043-6046if (!config.authToken) { config.authToken node_crypto.randomUUID(); // 首次启动自动生成 UUID saveMCPServerConfig(config); }七、最终配置示例Claude Code 端(~/.claude.json的mcpServers块)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 }八、经验教训Anything Analyzer 改 MCP token 后必须重启应用— 这是产品 bug,不是配置问题。Git Bash 调 Windowstaskkill/start会被转义— 用cmd //c或 PowerShell。Electronapp.asar解包:npx electron/asar extract app.asar app_extracted,可读 main 进程 bundle 找问题。401 invalid or missing token时先Access-Control-Allow-Headers反推允许的 header 名,再读服务端源码确认验证规则。MCP HTTP 类型 401 的通用诊断顺序:应用在不在跑 → 端口在不在听 → curl 看错误消息 → CORS 头反推 header 名 → 配置文件 / 用户数据目录找 token → 比对配置 mtime 和进程 StartTime → 锁定「未重启」型问题。