克劳德↔ Codex MCP中继(带日志+web UI)
这运行a 单个Python MCP服务器 两者都 克劳德代码 和 Codex(VS代码聊天/CLI) 可以连接到。
它提供:
- MCP工具:
post_message,fetch_messages,list_channels - 旋转日志文件(工具使用+频道消息存档)
- 一个微小的web UI,可以呈现对话,突出显示围栏代码块,并可以发布消息
1) 安装程序
需求
- Python 3.10+
pip
安装
python -m venv .venv
source .venv/bin/activate # (Windows: .venv\Scripts\activate)
pip install -r requirements.txt2) 运行服务器
python claude_codex.py这将从以下位置读取主机/端口 config.json (或env变量,或默认为 127.0.0.1:8010).
或者,直接指定主机/端口:
uvicorn claude_codex:app --host 127.0.0.1 --port 8010打开:
- Web用户界面:http://127.0.0.1:8010/
- MCP端点:http://127.0.0.1:8010/mcp
日志:
log/claude_codex.log(轮换,默认值:25MB×10次备份)log/channel_messages.log(轮换,默认值:25MB×10次备份)
3) 配置
配置从加载 config.json (如果存在),然后是环境变量,然后是默认值。
选项A:config.json(推荐)
创建一个 config.json 在项目根目录中:
{
"host": "127.0.0.1",
"port": 8010,
"log_path": "log/claude_codex.log",
"log_max_mb": 25,
"log_backup_count": 10,
"channel_log_path": "log/channel_messages.log",
"channel_log_max_mb": 25,
"channel_log_backup_count": 10,
"channels": ["proj-x", "codex", "claude"],
"allowed_hosts": []
}选项B:环境变量
| 变量 | 默认值 | 含义 |
|---|---|---|
CLAUDE_CODEX_HOST | 127.0.0.1 | 服务器主机 |
CLAUDE_CODEX_PORT | 8010 | 服务器端口 |
CLAUDE_CODEX_LOG_PATH | log/claude_codex.log | 日志文件路径 |
CLAUDE_CODEX_LOG_MAX_MB | 25 | N MB后旋转 |
CLAUDE_CODEX_LOG_BACKUP_COUNT | 10 | 保留N个备份 |
CLAUDE_CODEX_CHANNEL_LOG_PATH | log/channel_messages.log | 通道消息存档日志路径 |
CLAUDE_CODEX_CHANNEL_LOG_MAX_MB | 25 | N MB后旋转通道日志 |
CLAUDE_CODEX_CHANNEL_LOG_BACKUP_COUNT | 10 | 保留N通道日志备份 |
CLAUDE_CODEX_CHANNELS | proj-x,codex,claude | 频道种子列表 |
CLAUDE_CODEX_ALLOWED_HOSTS | *(空)* | 用于MCP DNS重新绑定保护的额外主机(逗号分隔) |
传统兼容性: log_max_bytes / channel_log_max_bytes (和env ..._MAX_BYTES)仍然被接受。
例子:
CLAUDE_CODEX_LOG_PATH=/tmp/relay.log uvicorn claude_codex:app --host 127.0.0.1 --port 8010局域网/远程访问
默认情况下,MCP端点只接受以下请求 Host: localhost 或 Host: 127.0.0.1 (DNS重新绑定保护)。要允许来自网络上其他机器的连接,请将它们的IP添加到 allowed_hosts:
config.json:
{
"host": "0.0.0.0",
"allowed_hosts": ["192.168.2.3"]
}或者通过env变量:
CLAUDE_CODEX_HOST=0.0.0.0 CLAUDE_CODEX_ALLOWED_HOSTS=192.168.2.3 python claude_codex.py端口通配符会自动添加-- 192.168.2.3 成为 192.168.2.3:*。您还可以指定显式的主机:端口模式,如 192.168.2.3:8010.
4) 配置克劳德代码+Codex
请参阅:
docs/claude.mddocs/codex.md
5) 建议的工作流程
使用共享频道,如 proj-x 所以两个代理读/写同一个线程。
- Claude进行更改,然后发布一个评论包:
- 总结 - 统一diff(在diff围栏块中) - 问题/焦点
- Codex获取、审查并发布反馈:
- 裁决 - 重大/次要问题 - 要添加/运行的测试
- Claude应用修复程序并发布更新的数据包。
6) 轮询脚本
scripts/review-poll.sh 是一个轻量级的bash轮询器,用于监视频道中的新消息。使用 curl 和 jq 击中 /api/messages 端点,并打印自上次轮询以来任何新消息的单行摘要。
必需的环境变量:
| 变量 | 目的 |
|---|---|
BASE_URL | 服务器URL,例如。 http://127.0.0.1:8010 |
LASTFILE | 保存上次看到的消息ID的文件的路径 |
可选环境变量:
| 变量 | 默认值 | 用途 |
|---|---|---|
TARGET | propiese | 投票渠道 |
INTERVAL | 20 | 投票间隔秒数 |
WATCH_SENDER | claude | 仅显示来自此发件人的邮件(忽略自己的邮件) |
例子:
BASE_URL=http://127.0.0.1:8010 LASTFILE=/tmp/last_id TARGET=proj-x INTERVAL=10 bash scripts/review-poll.sh7) 自动轮询:让Codex检查消息
Codex不会自行投票,它只会在收到提示时采取行动。以下选项A-C需要 人在回路 向食品法典委员会传递信息。仅 选项D 完全自动化。
选项A:食品法典定制说明(需要人工)
增添 .github/copilot-instructions.md 或您的VS代码副本说明:
After completing any task, call the fetch_messages MCP tool on the "proj-x" channel
to check for new review feedback before going idle.食品法典委员会将在每项任务后进行检查,但 空闲时不会轮询。您仍然需要手动提示Codex开始新的任务周期。
选项B:在VS Code终端中运行轮询脚本(需要人工)
BASE_URL=http://127.0.0.1:8010 LASTFILE=/tmp/last_id TARGET=proj-x INTERVAL=10 \
bash scripts/review-poll.sh终端中出现新消息。 你 需要阅读输出并告诉Codex对其采取行动(例如“检查proj-x通道”或粘贴摘要)。
选项C:VS代码任务(需要人工)
打开工作区时自动启动轮询脚本,因此您不必手动启动它。但Codex仍然 无法自行读取终端输出 --当你看到新消息时,你需要提示它。
增添 .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "MCP Poller",
"type": "shell",
"command": "bash",
"args": [".codex/reviewer-poller.sh"],
"options": {
"env": {
"BASE_URL": "http://127.0.0.1:8010",
"LASTFILE": "${workspaceFolder}/.codex/reviewer-poller.last_id",
"TARGET": "proj-x",
"INTERVAL": "15"
}
},
"isBackground": true,
"runOptions": { "runOn": "folderOpen" }
}
]
}提示: 通过启用自动启动Ctrl+Shift+P→Tasks: Manage Automatic Tasks in Folder→ 允许.
选项D:Codex CLI自动循环(全自动)
这是 唯一的全自动选项。它使用 Codex CLI --OpenAI的基于终端的编码代理——在没有人为干预的情况下自动对新消息做出反应。
先决条件
- 安装Codex CLI:
npm i -g @openai/codex- 配置MCP连接 所以Codex可以打电话
fetch_messages/post_message直接。
添加到您的项目 .codex/config.toml:
[mcp.claudecodex]
transport = "sse"
url = "http://127.0.0.1:8010/mcp"- 确保
curl和jq已安装 (由轮询循环使用)。
自动循环脚本
创建脚本(例如。 .codex/auto-review-loop.sh):
脚本使用 codex exec (非交互式/无头模式),以便Codex 自动退出 在完成每次审查后。常规 codex 和 codex resume 命令打开一个将阻止循环的交互式会话。
#!/usr/bin/env bash
set -u
BASE_URL="${BASE_URL:-http://127.0.0.1:8010}"
TARGET="${TARGET:-proj-x}"
INTERVAL="${INTERVAL:-20}"
LASTFILE="${LASTFILE:-.codex/auto-loop.last_id}"
SESSION_ID="${SESSION_ID:-}" # optional: resume an existing Codex session
WATCH_SENDER="${WATCH_SENDER:-claude}" # only react to messages from this sender
LAST=0
if [ -f "$LASTFILE" ]; then
LAST=$(cat "$LASTFILE" 2>/dev/null || echo 0)
fi
if ! [[ "$LAST" =~ ^[0-9]+$ ]]; then LAST=0; fi
echo "auto-loop started: target=$TARGET sender=$WATCH_SENDER interval=${INTERVAL}s last=$LAST session=${SESSION_ID:-new}"
while true; do
JSON=$(curl -sS -m 10 "$BASE_URL/api/messages?target=$TARGET&limit=200" || true)
# Only look at messages from WATCH_SENDER — ignore own (codex) messages
NEW=$(printf "%s" "$JSON" | jq -r --argjson d "$LAST" --arg sender "$WATCH_SENDER" \
'[.messages[] | select(.sender == $sender)] | last | .id // $d' 2>/dev/null || echo "$LAST")
if [[ "$NEW" =~ ^[0-9]+$ ]] && [ "$NEW" -gt "$LAST" ]; then
echo "$(date -Iseconds) new messages from $WATCH_SENDER (last=$LAST, new=$NEW) — launching Codex"
PROMPT="Fetch messages from the $TARGET channel (since id $LAST) sent by $WATCH_SENDER and review them. Post your feedback back to the same channel."
if [ -n "$SESSION_ID" ]; then
# Resume existing session — keeps full conversation context across reviews
codex exec --dangerously-bypass-approvals-and-sandbox resume "$SESSION_ID" "$PROMPT"
else
# Start a fresh session
codex exec --dangerously-bypass-approvals-and-sandbox "$PROMPT"
fi
LAST="$NEW"
echo "$LAST" > "$LASTFILE"
fi
sleep "$INTERVAL"
done运行它
chmod +x .codex/auto-review-loop.sh
# Start a new session each time
BASE_URL=http://127.0.0.1:8010 TARGET=proj-x INTERVAL=15 \
bash .codex/auto-review-loop.sh
# Or resume an existing Codex session (keeps conversation context)
BASE_URL=http://127.0.0.1:8010 TARGET=proj-x SESSION_ID=abc123 \
bash .codex/auto-review-loop.sh运作原理
- 脚本民意调查
/api/messages每INTERVAL秒 - 当出现新消息时,它会运行
codex exec(非交互模式),用于处理任务和 自动退出 - 如果
SESSION_ID已设置,它使用codex exec resume继续现有的会议——食品法典委员会保留了完整的对话历史,并以之前的审查为基础 - Codex连接到MCP中继,获取新消息,对其进行审查,并发布反馈
- 最后一个看到的ID被持久化到磁盘上,因此重新启动会从停止的地方继续
- 循环继续等待下一条消息
为什么codex exec而不是codex? 常规codex命令打开一个交互式终端UI,该UI等待用户输入并且从不退出。codex exec是为脚本和自动化设计的无头/非交互模式——它运行任务并在完成后退出。
Codex CLI会话管理
每次Codex CLI聊天都会获得一个 会话ID 储存在 ~/.codex/sessions/。您可以使用这些来保持审查的连续性。
| 命令 | 目的 |
|---|---|
/status | 显示当前会话ID(在正在运行的会话内) |
codex resume | 从列表中选择要继续的会话 |
codex resume | 按ID恢复特定会话 |
codex fork | 将会话分叉到新线程中 |
codex fork --last | 分叉最近的会话 |
您还可以键入 /resume 在CLI中获取交互式会话选择器。
提示: 在第一次Codex运行后,从以下位置获取会话ID /status 或 ~/.codex/sessions/ 并将其作为 SESSION_ID 自动循环。这样,每次审查迭代都建立在同一个对话线程上,为Codex提供了之前反馈的完整背景。
审批和沙盒模式
| 标记 | 批准 | 文件写入 | 网络 |
|---|---|---|---|
| *(默认)* | 命令/写入前询问 | 仅限工作区 | 已阻止 |
--full-auto | 无 | 仅限工作区 | 已阻止 |
--full-auto +网络配置 | 无 | 仅限工作区 | 允许 |
--sandbox danger-full-access | 命令前询问 | 任何地方 | 允许 |
--dangerously-bypass-approvals-and-sandbox | 无 | 任何地方 | 允许 |
重要提示: --full-auto 默认情况下阻止网络访问。由于Codex需要到达MCP中继,除非启用网络访问,否则上述自动循环脚本将失败。启用网络访问
选项1: 在配置中启用网络(推荐)。增添 .codex/config.toml:
[sandbox_workspace_write]
network_access = true然后 --full-auto 按原样工作。
选项2: 内联传递沙盒配置:
codex exec --full-auto -c 'sandbox_workspace_write.network_access=true' "$PROMPT"选项3: 完全绕过沙盒(谨慎使用):
codex exec --dangerously-bypass-approvals-and-sandbox "$PROMPT"具有网络访问功能的全自动脚本
此变体使用 --dangerously-bypass-approvals-and-sandbox 确保Codex能够不受任何限制地到达MCP中继:
#!/usr/bin/env bash
set -u
BASE_URL="${BASE_URL:-http://127.0.0.1:8010}"
TARGET="${TARGET:-proj-x}"
INTERVAL="${INTERVAL:-20}"
LASTFILE="${LASTFILE:-.codex/auto-loop.last_id}"
SESSION_ID="${SESSION_ID:-}"
WATCH_SENDER="${WATCH_SENDER:-claude}" # only react to messages from this sender
LAST=0
if [ -f "$LASTFILE" ]; then
LAST=$(cat "$LASTFILE" 2>/dev/null || echo 0)
fi
if ! [[ "$LAST" =~ ^[0-9]+$ ]]; then LAST=0; fi
echo "auto-loop started: target=$TARGET sender=$WATCH_SENDER interval=${INTERVAL}s last=$LAST session=${SESSION_ID:-new}"
while true; do
JSON=$(curl -sS -m 10 "$BASE_URL/api/messages?target=$TARGET&limit=200" || true)
# Only look at messages from WATCH_SENDER — ignore own (codex) messages
NEW=$(printf "%s" "$JSON" | jq -r --argjson d "$LAST" --arg sender "$WATCH_SENDER" \
'[.messages[] | select(.sender == $sender)] | last | .id // $d' 2>/dev/null || echo "$LAST")
if [[ "$NEW" =~ ^[0-9]+$ ]] && [ "$NEW" -gt "$LAST" ]; then
echo "$(date -Iseconds) new messages from $WATCH_SENDER (last=$LAST, new=$NEW) — launching Codex"
PROMPT="Fetch messages from the $TARGET channel (since id $LAST) sent by $WATCH_SENDER and review them. Post your feedback back to the same channel."
if [ -n "$SESSION_ID" ]; then
codex exec --dangerously-bypass-approvals-and-sandbox resume "$SESSION_ID" "$PROMPT"
else
codex exec --dangerously-bypass-approvals-and-sandbox "$PROMPT"
fi
LAST="$NEW"
echo "$LAST" > "$LASTFILE"
fi
sleep "$INTERVAL"
done更安全的替代方案: 如果您希望保留工作区沙盒,请添加network_access = true致你的.codex/config.toml(见上文选项1)和使用--full-auto相反。
8) 注意事项
- 此服务器将消息存储在内存中。重新启动服务器会清除历史记录。
- 想要坚持?将内存中的列表替换为SQLite/Redis,同时保留相同的工具。
