跳转到内容

05 — 多协议服务架构:MCP / HTTP-SSE / ACP

多协议服务架构:MCP / HTTP-SSE / ACP

学习目标

理解 CodeWhale 的三种服务模式:MCP stdio 服务器、HTTP/SSE 运行时 API、ACP 编辑器适配器,以及它们的复用基础与隔离边界。

前置知识

下文假设你已理解上述概念,直接聚焦 CodeWhale 的具体实现。

项目实践

三种模式对比

维度serve --mcpserve --httpserve --acp
协议MCP stdioHTTP/SSE JSON-RPCACP stdio
用例供其他 MCP 客户端调用的工具服务器应用直接消费的运行时 APIZed/自定义编辑器的 Agent
配置~/.codewhale/mcp.json 条目直接 URL 连接编辑器 agent_servers 自定义命令
生命周期每客户端会话生成子进程长期守护进程每编辑器 Agent 会话生成
入口点codewhale-tui serve --mcpcodewhale mcp-servercodewhale serve --httpcodewhale serve --acp

复用基础

三种模式共享同一个 TUI 运行时引擎:

每种协议模式将外部请求映射为内部引擎操作,将引擎响应映射为协议特定的响应格式。

MCP stdio 服务器

启动方式

Terminal window
codewhale-tui serve --mcp
# 或等价的调度器入口
codewhale mcp-server

自注册为 MCP 服务器

Terminal window
codewhale-tui mcp add-self

这解析当前二进制路径,生成运行 codewhale-tui serve --mcp 的配置条目,写入 MCP 配置文件。这样其他 MCP 客户端(包括其他 CodeWhale 会话)可以调用本实例的工具。

工具命名:遵循 mcp_<server>_<tool> 约定。自注册服务器名为 codewhale,所以 shell 工具变为 mcp_codewhale_shell

HTTP/SSE 运行时 API

启动方式

Terminal window
codewhale serve --http # HTTP/SSE API 服务器
codewhale serve --mobile # LAN 移动端控制页(默认 token 门控)

端点结构

  • /v1/threads — 线程管理(创建/列出)
  • /v1/threads/{id}/turns — turn 管理(开始/停止)
  • /v1/threads/{id}/events?since_seq=<n> — 事件回放(客户端重放历史)
  • /v1/tasks — 后台任务管理

安全边界

  • 绑定 localhost——仅供可信本地访问
  • EdgeOne 不用于暴露 /v1/*(即使配置了公共 HTTPS 边缘)
  • 移动端模式使用 token 门控

运行时线程时间线

  1. API/TUI 创建或恢复线程
  2. Turn 在线程上启动
  3. 引擎事件映射为 item 生命周期事件(item.started / item.delta / item.completed
  4. 中断/转向操作仅应用于活跃 turn
  5. 压缩/清除作为特殊 item 生命周期发出
  6. 客户端通过 since_seq 参数回放历史并恢复

ACP 编辑器适配器

启动方式

Terminal window
codewhale serve --acp

Zed 集成

{
"agent_servers": {
"DeepSeek": {
"type": "custom",
"command": "codewhale",
"args": ["serve", "--acp"],
"env": {}
}
}
}

当前功能限制

  • 第一个 ACP 切片支持新会话和提示响应
  • 通过现有的 DeepSeek 配置/API 密钥
  • 工具支持的编辑检查点回放尚未通过 ACP 暴露

社区适配器acp-codewhale-adapter 桥接 codewhale exec --autocc-connect,用于需要在内置 Zed 切片之外使用工具支持 ACP 工作流的用户。

问题与规避

陷阱:HTTP API 暴露到公网

HTTP/SSE API 设计为 localhost 访问。如果通过反向代理暴露到公网,没有额外的认证层会很危险。

规避

  • --mobile 模式有 token 门控
  • 文档明确说 “EdgeOne is not used to expose /v1/*
  • 生产部署应在反向代理后添加认证层

陷阱:MCP 自注册导致循环调用

A 会话将 B 会话注册为 MCP 服务器,B 又调用 A——可能导致循环。

规避:每个 MCP 会话是独立的子进程,有自己的配置和 API 密钥。循环调用在实际中不太可能自然发生,但用户应避免手动配置相互调用。

陷阱:ACP 功能不完整

ACP 适配器当前仅支持基本会话和提示响应,不支持工具编辑和检查点回放。

规避:对于需要完整 ACP 工作流的用户,使用社区维护的 acp-codewhale-adapter

设计取舍

为什么三种模式共享同一引擎

  • 代码复用:核心 Agent 循环、工具系统、会话管理不需要为每个协议重写
  • 一致性:无论通过哪个协议访问,行为一致
  • 维护成本:只需维护一个引擎实现

代价

  • 引擎与协议层的耦合可能导致某协议的变更影响其他协议
  • 引擎的启动路径需要适配三种不同的生命周期(子进程/守护进程/编辑器会话)

为什么 ACP 功能受限

ACP 适配器是后加的集成层,核心引擎最初只为 TUI 和 CLI 设计。工具编辑和检查点回放需要:

  • 编辑器特定的 UI 协议(如 diff 展示、接受/拒绝变更)
  • 检查点状态在编辑器与 Agent 之间的同步

这些需要额外的工作,不在第一个 ACP 切片的范围内。

参考来源

  • docs/MCP.md — MCP 集成文档
  • docs/RUNTIME_API.md — HTTP/SSE API 文档
  • crates/tui/src/runtime_api.rs — HTTP/SSE 运行时 API 实现(~4368 行)
  • crates/tui/src/acp_server.rs — ACP 适配器实现
  • crates/mcp/ — MCP 客户端和 stdio 服务器