commit ebaf3252222e0e9971dadbc246bed4a0e8e69ff1 Author: OpenClaw Agent Date: Sat Mar 14 13:28:02 2026 +0800 docs: add MCP debugging summary diff --git a/docs/mcp-debugging-summary.md b/docs/mcp-debugging-summary.md new file mode 100644 index 0000000..66ae11b --- /dev/null +++ b/docs/mcp-debugging-summary.md @@ -0,0 +1,126 @@ +# MCP 调试记录(Tao-Memory-Server / RikkaHub / Lucky) + +> 目标:解决移动端 MCP 客户端(MOMERY‑PRO / RikkaHub)连接异常(-32000 / Connection closed)并完成握手与工具调用。 +> 项目路径:`/root/.openclaw/workspace/tao_mcp_go` +> 反向代理:Lucky +> 服务端口:5001 + +--- + +## 一、现象与症状 + +- 客户端能发起 `GET /mcp/sse` 与 `POST /mcp/message`,但出现: + - `-32000: Connection closed` + - POST 进入后端但 10~30s 超时后断开 + - initialize 反复重试,未进入 tools/list + +--- + +## 二、关键问题定位 & 解决方案 + +### 1) JSON‑RPC initialize 返回格式不被客户端认可 +**现象**:initialize 请求到了,但客户端无后续动作(反复初始化)。 + +**解决**: +- `MCPResponse.Result` 改为 `any`,允许返回 protocolVersion/capabilities 等结构。 +- 增加 initialize 返回: + - `protocolVersion` + - `capabilities.tools/resources/prompts` + - `serverInfo` + +### 2) CORS 预检/响应问题导致移动端丢弃响应 +**现象**:OPTIONS 或 POST 可能被丢弃,客户端视为连接失败。 + +**解决**: +- `requireAuth` 中放行 `OPTIONS`,返回 200 + 允许头 +- `MessageHandler` 每次响应前统一设置: + - `Access-Control-Allow-Origin: *` + - `Access-Control-Allow-Methods: GET, POST, OPTIONS` + - `Access-Control-Allow-Headers: Content-Type, Authorization` + +### 3) SSE 端点返回错误导致路径拼接异常 +**现象**:客户端生成 /mcp/mcp 或 /mcp/https://… + +**解决**: +- 增加 `TAO_ENDPOINT_STYLE=message`,SSE 发送 `event: endpoint` 为 `message?token=...` + +### 4) Lucky 反代缓冲导致 SSE 首包/POST 响应丢失 +**现象**:SSE 未及时下发 endpoint;POST 处理后客户端超时。 + +**解决**: +- SSE 头加入:`X-Accel-Buffering: no` +- SSE 建立后立即 `Flush()` +- 心跳从 15s 调整为 5s + +### 5) 协议版本不匹配导致客户端拒绝 +**现象**:客户端请求协议 2025‑06‑18,服务端返回 2024‑11‑05,握手失败。 + +**解决**: +- initialize 返回 `protocolVersion: 2025-06-18` + +### 6) 识别 notifications/initialized +**现象**:握手成功后仍死循环。 + +**解决**: +- 增加对 `notifications/initialized` 的处理与日志 + +### 7) POST 返回体被 Lucky 缓冲 / Chunked 不一致 +**现象**:POST 返回体被代理吞掉或不及时转发。 + +**尝试**: +- 强制设置 `Content-Length` +- 禁用缓冲 `X-Accel-Buffering: no` +- 取消 `Connection: close` + +> 此阶段仍存在“initialize 循环”问题,最终采用异步 SSE 方案解决。 + +--- + +## 三、终极解决方案:异步 SSE 通道模式(MCP 正式规范) + +**核心思路**: +- POST 只作为“投递箱”,立即返回 `202 Accepted` +- 所有 JSON‑RPC 结果通过 SSE `event: message` 下发 + +**关键实现**: +- `SSEHandler`:建立 `token -> chan` 的映射,并在 `select` 中写入 `event: message` +- `MessageHandler`:读取 JSON 后立即 202,异步 `dispatchMCP()` 处理 +- `dispatchMCP()`:根据 method 生成响应,写入对应 token 的 SSE 通道 + +**日志验证**: +- `[SSE Connect]` → SSE 已连 +- `[MCP POST]` → POST 到达 +- `[MCP Response] sent via SSE` → 回复已通过 SSE 下发 +- `[MCP Notify] initialized` → 客户端确认握手完成 +- `tools/list` 成功返回 + +--- + +## 四、最终生效状态(已验证) + +日志证据显示握手完成: +- initialize → notifications/initialized → tools/list +- 全流程通过 SSE message 传输 + +--- + +## 五、关键配置(供后续复盘) + +- 服务:`tao-mcp-go.service` +- 端口:5001 +- 反代:Lucky +- SSE URL:`https://mcp.good.xx.kg/mcp/sse?token=...` +- Message URL:`https://mcp.good.xx.kg/mcp/message?token=...` + +--- + +## 六、建议后续工作 + +1. 清理调试日志(POST body / SSE connect) +2. 增加 tools/call 执行日志 +3. 在 README 中补充“异步 SSE 模式说明” +4. 如需兼容同步模式,建议单独开新路由避免混用 + +--- + +> 本文档用于存档,建议上传到仓库 `docs/` 目录。