Files
tao-memory-mcp/docs/mcp-debugging-summary.md
2026-03-14 13:28:02 +08:00

127 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MCP 调试记录Tao-Memory-Server / RikkaHub / Lucky
> 目标:解决移动端 MCP 客户端MOMERYPRO / 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) JSONRPC 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 未及时下发 endpointPOST 处理后客户端超时。
**解决**
- SSE 头加入:`X-Accel-Buffering: no`
- SSE 建立后立即 `Flush()`
- 心跳从 15s 调整为 5s
### 5) 协议版本不匹配导致客户端拒绝
**现象**:客户端请求协议 20250618服务端返回 20241105握手失败。
**解决**
- 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`
- 所有 JSONRPC 结果通过 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/` 目录。