--- name: stdio↔TCP 桥(MCP 标准化) description: mcp_bridge 包——把标准 MCP 客户端的 stdio 桥接到 CAD 基座裸 TCP;含基座协议缺口、设计决策与用 MCP Inspector 验证的方法 type: project --- # stdio ↔ TCP 桥(`mcp_bridge/`) **状态:已实现并验证通过**(2026-10-14)。这是「MCP 标准化」路线的第二步 (第一步是基座 B 最小集,见 `project_review_agent_impl.md`)。 ## 为什么需要它(非显而易见) 基座是**裸 TCP 自定义传输**,标准 MCP 客户端(Claude Desktop / CodeBuddy / MCP Inspector) 只实现 **stdio** 与 **Streamable HTTP**,因此**无法直连基座**。桥在客户端与基座之间做协议适配, **CAD 侧零改动**。 ## 基座的协议缺口(实测,决定桥要补什么) | 项 | 事实 | | --- | --- | | 连接模型 | 一个连接**只处理一帧**,响应后立即 `closesocket`(`TaskData` 析构)→ 桥每次请求新建连接 | | 支持方法 | **只有** `tools/list` / `tools/call`;其余回 `-32601` | | 生命周期 | **没有** `initialize` / `initialized` / `ping` → **必须由桥合成** | | 通知 | 无 `id` 即不回包 | | `tools/list` | 26 个工具,`name`/`description`/`inputSchema(type=object)` 已是标准 MCP 形状 → **可原样转发** | | 未知工具 | 回**顶层** `error:-32602`(`"Unknown tool: "`)→ 桥忠实透传 | ## 关键设计决策 1. **位置**:顶层包 `mcp_bridge/`;TCP 复用 `dwg_review.mcp_client` 的 `raw_rpc()` (新增:`_rpc(normalize=False)` 返回基座**原始响应 dict**,不做 error/isError 归一化, 这样桥才能把 `result` 与顶层 `error` 原样透传)。桥调用时 `retries=0`: "发完即超时"语义有歧义,重试可能**重复执行写类工具**。 2. **并发**:**读线程 + 单工作线程队列**。`initialize`/`ping` 在读线程即时应答, 不会被慢工具阻塞;`tools/list`/`tools/call` 由单工作线程**串行**转发,保证调用顺序。 3. **stdout 纯净性**:只用 `sys.stdout.buffer.write(... + b"\n")` + `flush()`(加锁)。 用 `buffer` 而非文本流,**规避 Windows 的 `\n`→`\r\n` 翻译**;所有日志只走 stderr。 4. **CAD 未启动**:桥照常启动,`initialize`/`ping` 正常,`tools/list` 回 `-32603`(可重试)。 5. **不擅自改写语义**:桥只做忠实透传,错误码一律由基座决定。 (**2026-10-14 修正**:基座原先对未知工具回 `-32601`,语义偏 JSON-RPC 方法层; 按 MCP 规范「未知工具属于**协议错误**,示例码 `-32602`」已改为 `-32602` + `"Unknown tool: "`。改动点:`mcp_configParser.cpp: mcp_Tools::Call` —— 只需改码值,`mcp_server.cpp: HandleToolsCall` 的协议错误白名单 `{-32700,-32600,-32601,-32602}` 已含 `-32602`,分类逻辑无需动。) ## 验证方法(重要,含踩坑) - `verify_stdio_bridge.py`(仓库根):子进程拉起桥,24 项断言全绿(版本协商、通知不回包、 ping、`tools/list` 与基座**等价**、`tools/call`、错误透传、`-32700`、string id、 stdout 纯净性、死端口降级)。 - **用真实标准客户端(MCP Inspector)验证**——这是"标准化"的终极证明: ```bash npx --yes @modelcontextprotocol/inspector --cli \ --config <配置文件> --server cad-autocad --method tools/list --strict ``` - 实测:`tools/list` 拿到 26 个工具;`--strict` 退出码 **0**(无 schema 可移植性问题); `--method tools/call --tool-name get_drawing_info` 返回标准 `content` + `isError:false`。 - **踩坑**:Inspector CLI 在 Windows 上**参数解析很别扭**——用 `-- python -m mcp_bridge` 会把 `--method` 一起当成 target 传给 python(argparse 报错 → "Connection closed"); 不用 `--` 又报 "Target is required"。 **可靠做法:写一个 `{"mcpServers":{...}}` 配置文件,用 `--config` + `--server`**。 这也顺带验证了用户实际要粘贴的配置格式。 - `python -m mcp_bridge --print-config` 可直接生成该配置片段(`PYTHONPATH` 用绝对路径, 避免依赖客户端的工作目录)。