Skip to main content
Glama

cc-codex-a2a-shim

把 Claude Code 和 Codex CLI(本机二进制)包装成 MCP 服务器(HTTP 传输),让任何 MCP 客户端(Hermes Agent 等)直接把 cc/codex 当工具调。

它解决什么

  • 会话续接:同一 contextId 的多次调用映射到同一个 cc/codex 会话(cc 用 -r <session_id>,codex 用 exec resume <session_id>),多轮对话不丢上下文;换 contextId = 开新会话

  • 提问抑制:每次调用注入 system 指令,让 cc/codex 按合理假设直接执行并列出假设,不中途等待澄清

  • 超时兜底:子进程超时强杀,返回 state="timeout"(结构化 error,不挂死)

  • Bearer 鉴权:每个 agent(claude/codex)独立 token,请求头 Authorization: Bearer <token> 校验;token 绑 agent,越权调用返回 state=failed, rawError=forbidden_agent

  • Agent Card:每个 agent 暴露 GET /.well-known/agent-card.json(A2A 风格元数据,方便人读和服务发现)

Related MCP server: Claude Code Manager WAN

暴露的 MCP 工具

工具

说明

send_message

发一条消息给 cc 或 codex(agent: claude/codex,text,context_id 可选缺省新建)

list_sessions

列出 contextId → 底层 session 的映射表

reset_session

删除某个 contextId 的映射(下条消息开新会话)

get_agent_card

读取某个 agent 的能力卡

部署(Windows,EPYC 实机为例)

完整版见 docs/DEPLOY_EPIC.md(防火墙、开机自启、排障表、复验命令)。最小路径:

# 1. 装依赖(仓库根目录)
pip install -e .

# 2. 固定 token(必须!不设 = 每次重启随机生成,Hermes 立刻 401)
python -c "import secrets;print('claude:',secrets.token_urlsafe(24));print('codex :',secrets.token_urlsafe(24))"
setx SHIM_CLAUDE_TOKEN "<生成的第 1 个>"
setx SHIM_CODEX_TOKEN  "<生成的第 2 个>"

# 3. 其余配置(setx 只对新开进程生效)
setx SHIM_WORKDIR       "C:\Temp\shim-workspace"        # cc/codex 的工作目录,写绝对路径
setx SHIM_STATE_FILE    "C:\Temp\shim-sessions.json"    # contextId 映射落盘,写绝对路径
setx SHIM_TIMEOUT_S     "600"                           # 单次调用子进程超时(秒)
setx SHIM_CLAUDE_BIN    "C:\Users\Administrator\AppData\Roaming\Claude\claude-code\2.1.299\f0584be0fbaf\claude.exe"
setx SHIM_CODEX_BIN     "C:\Users\Administrator\AppData\Local\OpenAI\Codex\bin\896a0166b774037a\codex.exe"
# codex 的 --skip-git-repo-check 由适配器自动追加,无需配置

# 4. 启动(默认 0.0.0.0:9910,一个进程同时服务 claude/codex)
python -m cc_codex_a2a_shim.server

Hermes 侧接入(~/.hermes/config.yaml)—— 按 agent 拆两条,token 与 agent 一一对应:

mcp_servers:
  cc_shim_claude:
    url: "http://192.168.1.196:9910/mcp"
    headers:
      Authorization: "Bearer ${SHIM_CLAUDE_TOKEN}"
    timeout: 600   # 与 SHIM_TIMEOUT_S 对齐;cc/codex 跑任务可能很慢
  cc_shim_codex:
    url: "http://192.168.1.196:9910/mcp"
    headers:
      Authorization: "Bearer ${SHIM_CODEX_TOKEN}"
    timeout: 600
  • URL 就是 /mcp(streamable-http 端点)。/mcp/mcp 是旧版路径叠一层的绕法,现在 404。

  • 两个 agent 共用同一端点,鉴权头决定身份:claude 的 token 调 agent=codex 会返回 state=failed, rawError=forbidden_agent(目标行为,见 DEPLOY 3.5「授权模型」;旧版本上越权调用会被直接执行,部署后请用 /whoami + 一次跨 agent 调用确认)。

  • timeout 建议 600 秒,与服务端 SHIM_TIMEOUT_S 对齐,可略大(660)以便先收到服务端的结构化超时。

重开会话即可看到 mcp__cc_shim_claude_send_message / mcp__cc_shim_codex_send_message 等工具。

契约说明(客户端要按这个读)

  • send_message 返回 {state, contextId, sessionId, output, rawError, durationS}。

  • state 有三个值:completed、failed,以及 timeout。timeout 是 shim 扩展状态,A2A 的 TaskState 里没有这一档,也不是把失败折了一层——超时就是原样对外返回 state="timeout"(rawError="timeout"),客户端必须单独分支处理。

  • rawError 平时为 null。state=completed 时唯一可能非空的是 rawError=store_error: ...:本轮 CLI 已经跑完并拿到结果,但 contextId → session_id 映射没写进 SHIM_STATE_FILE(磁盘满 / 目录只读)。此时 output 照常可用、进程内续接仍然有效,重启后该 contextId 会退化成新会话。state=failed + store_error 则说明本轮根本没跑(create_new 删不掉旧映射,无法保证"新会话")。

  • Agent Card 里的 protocolVersion(当前 "mcp/1.0")是 shim 自标值,不是 A2A 标准协商结果、也不是 MCP 协议版本;真正的协议版本以 POST /mcp 的 initialize 握手响应为准。这张卡只用于人读与服务发现。

架构

MCP client (Hermes) ──HTTP──> FastAPI :9910
                              ├─ /mcp            (MCP streamable http)
                              ├─ /.well-known/agent-card.json?agent=claude|codex  (免鉴权)
                              ├─ /healthz                                  (免鉴权)
                              ├─ /whoami  → {"agent": "claude"|"codex"}    (token 身份自检)
                              ├─ BearerAuth 中间件(每 agent 独立 token)
                              └─ adapters/
                                  ├─ claude_adapter.py   → claude.exe -p/--append-system-prompt/-r
                                  └─ codex_adapter.py    → codex.exe exec/exec resume
                                     · SessionStore(contextId→session_id, 落盘 sessions.json)
                                     · 超时 kill + 输出解析 + error 包装

开发

pip install -e ".[dev]"
pytest tests/ -q

适配器/存储测试打桩子进程(不需要真实 cc/codex 二进制);HTTP 与 MCP 层测试用 TestClient 在进程内跑完整 ASGI 栈(含 lifespan),不监听端口、不发真实子进程。

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables MCP clients to spawn and control Codex CLI and Claude Code sessions on the host machine, with session management and filesystem access.
    4
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables ISLI agents and MCP clients to dispatch natural-language coding and terminal tasks to a locally-installed Claude Code CLI, supporting both one-shot execution and persistent sessions with workspace and security controls.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables MCP-compatible AI clients to invoke CLI-driven agent tools over Streamable HTTP, including shell execution, file operations, patching, image viewing, web search, and nested agent tasks, with permission modes and real-time progress streaming.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables MCP-compatible coding agents to execute the local Codex CLI as a coding agent, including code reviews, session resume/fork, and CLI diagnostics.
    9
    6 npm
    MIT