为无头AI编程助手构建人机交互桥:基于MCP与OpenClaw的异步决策方案
1. 项目概述为无头Claude Code装上“嘴巴”和“耳朵”如果你和我一样经常在服务器上跑一些自动化的代码生成或重构任务那你肯定对Claude Code这个工具不陌生。它是个命令行里的编程助手能根据你的指令直接修改代码库效率非常高。但有个问题一直挺烦人的当它运行在无头环境比如服务器、CI/CD流水线或者后台进程时一旦遇到需要人工决策的点比如“这两个重构方案选哪个”或者“这个API密钥是多少”整个流程就卡住了。它没法像在IDE里那样弹个对话框问你只能默默失败或者停在那里等你发现。totorospirit/cc-openclaw-bridge这个项目就是为了解决这个“最后一公里”的问题而生的。它本质上是一个MCPModel Context Protocol服务器专门为Claude Code设计。你可以把它理解成给一个沉默的、埋头干活的AI程序员配了一个“通信兵”。当Claude Code在后台执行任务遇到需要你拍板的事情时这个“桥”会把问题打包通过一个叫OpenClaw的AI智能体平台发送到你日常使用的通讯软件上比如Telegram、Signal或者Discord。你在手机上点一下、回句话答案就能实时传回给Claude Code让它继续工作。整个流程是异步、非阻塞的。Claude Code发起询问后并不会傻等而是把问题“寄存”起来然后通过事件机制通知OpenClaw去取。这意味着你的Claude Code任务可以挂起你去开会、吃饭回来在手机上处理一下堆积的决策请求任务就能自动恢复。这对于需要长时间运行、中间有多处需要人工确认的自动化脚本比如复杂的代码迁移、敏感的数据处理来说简直是神器。它把人的判断无缝嵌入了自动化流程既保证了AI执行的效率又保留了关键环节的人为控制。2. 核心架构与通信原理解析要理解这个桥怎么工作得先拆开看它的几个核心组件和它们之间的握手方式。整个系统设计得非常精巧利用了文件系统和HTTP回调这两种简单可靠的机制避免了复杂的消息队列或长连接使得部署和调试都相对直观。2.1 核心组件角色分工整个系统涉及五个角色它们各司其职共同完成一次“提问-回答”的循环Claude Code (-p模式): 这是任务的发起者和执行者。它运行在无头模式下通过标准输入输出与MCP服务器通信。OpenClaw Bridge (MCP Server): 这是项目的核心。它扮演双重角色对Claude Code它是一个标准的MCP服务器提供了ask_user和notify_user两个工具Tool。当Claude Code调用这些工具时桥负责处理。对OpenClaw它是一个事件触发器和HTTP服务端。它把问题写入文件并触发OpenClaw来读取同时启动一个临时的HTTP服务器等待OpenClaw回传答案。IPC 文件目录 (/tmp/cc-openclaw-bridge/): 这是一个基于文件系统的“邮箱”或“任务队列”。桥把问题写成JSON文件放在这里OpenClaw从这里取走任务。这种方式依赖操作系统的文件系统简单、跨语言、易监控。OpenClaw Agent: 这是用户的“智能管家”。它持续监控着上述IPC目录。一旦发现有新文件桥通过系统事件唤醒它它就读取文件内容将格式化后的问题通过其集成的通道如Telegram Bot、Discord Webhook发送给真正的用户。User (Telegram, Signal, Discord...): 最终决策者。在熟悉的聊天界面里看到问题做出选择或输入文本。2.2 一次完整的问答时序让我们跟踪一次ask_user调用的完整生命周期这能帮你彻底理解调试时问题可能出在哪一环发起询问Claude Code 在执行claude -p refactor the auth module时代码逻辑判断需要选择认证方案。它通过MCP协议调用桥提供的ask_user工具并附上问题列表。桥接处理桥收到请求后会做几件事生成一个唯一的会话ID通常包含时间戳和进程ID。在IPC目录下创建一个ask-{session-id}.json文件里面完整存储了问题内容、选项以及一个至关重要的callbackUrl。这个URL指向桥自己临时启动的一个HTTP服务器例如http://127.0.0.1:某个随机端口/callback。通过OpenClaw提供的机制比如一个特定的系统调用或写入某个信号文件发送一个“唤醒事件”告诉OpenClaw Agent“有新的待处理任务快来取”随后桥进入等待状态启动一个超时计时器默认5分钟。代理转发OpenClaw Agent 被唤醒扫描IPC目录发现新的ask-*.json文件。它读取文件根据里面的格式将问题渲染成对用户友好的消息例如在Telegram里变成带按钮的卡片或选择题然后发送到用户绑定的聊天界面。用户回复用户在Telegram上点击“JWT”按钮或者输入一段文本作为回答。答案回传OpenClaw Agent 收集到用户的回复后按照ask-*.json文件中指定的callbackUrl向桥的临时HTTP服务器发起一个POST请求请求体里包含了答案如{answer: JWT}。桥接回调桥的HTTP服务器收到POST请求验证后将答案返回给正在等待的Claude Code MCP调用。流程继续Claude Code 拿到答案“JWT”继续执行重构认证模块的后续代码。注意notify_user的流程更简单它只到第3步就结束了。桥创建notify-*.json文件并触发事件OpenClaw Agent 读取并转发给用户后没有回调步骤因为不需要回复。这种基于文件系统和HTTP回调的松耦合设计好处非常明显可靠性即使OpenClaw Agent暂时离线问题文件也会持久化在磁盘上不会丢失。可调试性你可以直接去/tmp/cc-openclaw-bridge/目录下查看生成的JSON文件确认问题是否被正确格式化。也可以查看OpenClaw的日志看它是否读取并转发了消息。灵活性OpenClaw Agent 只要实现了读取文件和发送HTTP请求的逻辑可以用任何语言编写并且可以连接任何消息平台。3. 从零开始的部署与配置实操理解了原理我们来动手把它搭起来。整个过程可以分为三个部分安装桥本身、配置Claude Code、最后配置OpenClaw Agent。我会假设你已经在本地或服务器上安装了Node.js环境并且有一个可用的OpenClaw实例。3.1 安装与注册MCP服务器官方提供了极简的安装脚本但对于生产环境或想了解细节的用户我建议分步操作这样出错了也好排查。第一步获取项目代码# 克隆仓库 git clone https://github.com/totorospirit/cc-openclaw-bridge.git cd cc-openclaw-bridge # 查看项目结构 ls -la你会看到核心的index.js(MCP服务器主文件)、install.sh、setup-env.mjs以及一些配置文件。第二步运行安装脚本推荐初次使用# 给脚本执行权限 chmod x install.sh # 执行安装 ./install.sh这个脚本做了几件关键事情确定安装路径如果你是在临时目录克隆的它会自动将项目文件复制到持久化目录~/.local/share/cc-openclaw-bridge/。这很重要因为MCP配置需要指向一个稳定的路径。注册MCP服务器它会修改Claude Code的MCP服务器配置文件。这个文件通常位于~/.config/claude-desktop/mcp.json或类似路径。脚本会添加一个新的服务器条目指向桥的index.js。更新使用文档它会在~/.claude/CLAUDE.md文件中追加关于如何使用这个桥的简要说明这样你在Claude Desktop里也能看到提示。第三步手动检查安装可选但建议安装脚本可能因环境而异。完成后最好检查一下MCP配置是否生效。# 查看Claude Code的MCP配置路径可能不同请根据你的安装调整 cat ~/.config/Claude/mcp.json你应该能看到一个类似下面的条目被添加进去{ mcpServers: { openclaw-bridge: { command: node, args: [/home/yourname/.local/share/cc-openclaw-bridge/index.js], env: { OPENCLAW_BRIDGE_IPC_DIR: /tmp/cc-openclaw-bridge } } } }如果没找到你可能需要手动创建或编辑这个配置文件。这是MCP服务器能否被Claude Code调用的关键。第四步容器环境特殊设置如果你是将Claude Code和这个桥运行在OpenClaw的容器环境内比如一个统一的开发环境Pod则需要运行node setup-env.mjs这个脚本会检查环境变量并确保桥在容器内使用正确的路径和网络设置。它主要处理容器内文件共享卷的路径映射问题。3.2 配置你的OpenClaw Agent桥安装好了还得让OpenClaw Agent知道怎么跟它配合。OpenClaw Agent通常通过配置文件如AGENTS.md或HEARTBEAT.md来定义行为。你需要在你OpenClaw Agent的配置中添加一个定期的检查任务。以下是一个添加到HEARTBEAT.md的示例配置它让Agent每分钟检查一次IPC目录## Claude Code 桥接器支持 **任务**: 监控Claude Code桥接请求 **频率**: 每分钟 **脚本**: bash #!/bin/bash IPC_DIR/tmp/cc-openclaw-bridge # 检查目录是否存在 if [ ! -d $IPC_DIR ]; then exit 0 fi # 处理询问文件 (ask-*.json) for ask_file in $IPC_DIR/ask-*.json; do [ -e $ask_file ] || continue # 处理无文件的情况 # 1. 读取文件内容解析JSON # 2. 根据内容构造用户消息例如用Telegram Bot API发送带键盘的消息 # 3. 将用户回复通过HTTP POST发送到 callbackUrl # 4. 处理完成后删除或归档该ask_file done # 处理通知文件 (notify-*.json) - 更简单只需转发 for notify_file in $IPC_DIR/notify-*.json; do [ -e $notify_file ] || continue # 1. 读取并转发消息 # 2. 处理完成后删除或归档该notify_file done # 处理总结文件 (summary-*.json) - 会话结束报告 for summary_file in $IPC_DIR/summary-*.json; do [ -e $summary_file ] || continue # 1. 读取并转发总结报告 # 2. 处理完成后删除或归档该summary_file done说明: 此脚本需根据你实际的消息平台APITelegram Bot, Discord Webhook等进行实现。核心逻辑是发现文件 - 解析 - 转发 - 等待/获取用户输入 - 回调 - 清理。 **实操心得**这里是最容易出问题的地方。你的Agent脚本必须正确处理JSON解析、网络请求发送消息和POST回调以及文件锁。一个常见的坑是如果多个Claude Code实例同时运行可能会产生并发读写。简单的处理方式是在Agent读取文件后立即将其移动到 processing/ 子目录处理完毕后再删除避免重复处理。 ### 3.3 环境变量详解与调优 项目提供了一系列环境变量让你能精细控制桥的行为。你可以在启动Claude Code之前设置它们。 bash # 示例启动一个带有丰富上下文信息的Claude Code任务 export OPENCLAW_BRIDGE_IPC_DIR/tmp/my-cc-bridge # 自定义IPC目录避免冲突 export OPENCLAW_BRIDGE_TIMEOUT_MS600000 # 将超时设置为10分钟处理复杂决策 export CC_WORKDIR/home/user/projects/auth-service # 告诉桥当前项目路径 export CC_TASK将登录模块从Session迁移到JWT并更新所有相关API # 任务描述 export CC_IDauth-migration-$(date %s) # 生成一个唯一且易读的实例ID # 然后启动Claude Code claude -p 开始重构关键变量解析OPENCLAW_BRIDGE_HOST: 默认是127.0.0.1。如果你在Docker容器内运行桥而OpenClaw Agent在宿主机或其他容器你需要将其改为0.0.0.0否则回调请求无法从外部访问。CC_WORKDIR和CC_TASK: 这两个信息会被桥添加到它生成的ask-*.json和notify-*.json文件中。OpenClaw Agent在向用户展示问题时可以把这些上下文信息一并显示出来比如“关于项目/home/user/projects/auth-service中的任务‘迁移JWT’需要您决策”。这能极大提升用户体验让用户知道当前问题属于哪个任务背景。CC_ID: 在多实例运行时用这个ID来区分不同任务流。建议设置为包含任务语义和进程标识的字符串方便在日志和文件列表中辨识。4. 工具使用详解与最佳实践桥提供了两个核心MCP工具ask_user和notify_user。它们的参数设计得很灵活用好了能极大提升交互效率。4.1ask_user设计高效的决策点ask_user的核心是questions数组最多支持4个问题。每个问题都可以配置得很丰富。基础单问题示例{ questions: [ { question: 发现数据库schema版本落后是否运行迁移脚本, header: DB Migration, options: [ { label: 是, description: 自动运行 alembic upgrade head }, { label: 否, description: 跳过手动处理 }, { label: 查看差异, description: 先显示将要执行的SQL } ] } ], context: 启动应用前检查 }header: 像一个标题标签在消息界面可能被用作消息标题或分类让用户快速抓住重点。options:label是返回给Claude Code的值description是给用户看的解释。务必让description清晰明了因为用户看不到你的代码上下文。高级批量提问示例 一次调用收集多个相关决策减少来回次数。{ questions: [ { question: 选择部署环境, header: Env, options: [ { label: staging, description: 预发布环境 }, { label: production, description: 生产环境 } ] }, { question: 确认部署分支, header: Branch, options: [ { label: main, description: 主干分支 }, { label: feat/new-api, description: 新功能分支 } ] }, { question: 部署后是否运行集成测试, header: Test, options: [ { label: yes, description: 是 }, { label: no, description: 否 } ] } ], context: 执行自动化部署流水线 }Claude Code会一次性收到一个包含三个答案的数组。这种设计适合流程中多个连续决策点能保持任务的原子性。自由文本输入与多选 当options字段不存在时桥会提示用户输入自由文本。这对于输入变量名、确认关键字符串如确认删除的表名非常有用。多选功能则允许用户从选项中挑选多个适用于“选择要清理的日志文件”等场景。注意事项问题设计是门艺术。问题要具体、选项要互斥且覆盖所有可能。避免使用“是/否”这种过于简单的选项而是像上面例子那样加上描述性后缀明确每个选择的后果。因为用户可能在忙碌中快速决策清晰的描述能防止误操作。4.2notify_user恰到好处的进度同步notify_user用于单向通知不需要回复。别把它当成日志流——那样会骚扰用户。它应该用于标志性的、关键的状态变更。好的用例{ message: ✅ 所有单元测试通过覆盖率提升至92%。正在创建Pull Request #451..., context: 功能分支 CI }{ message: ⚠️ 检测到生产数据库连接缓慢已自动切换到只读副本。请检查主库状态。, context: 生产环境监控 }不好的用例{ message: 正在编译...编译完成。正在运行第1个测试...第1个测试通过..., context: CI } // 这种细粒度的信息应该写入日志文件而不是推送通知。最佳实践将notify_user与ask_user结合使用。例如在开始一个耗时任务前通知在遇到关键决策时询问在任务成功或失败时再次通知。这样形成完整的交互闭环。4.3 会话总结不可或缺的收尾这是项目一个非常贴心的功能。当Claude Code进程退出时桥会自动生成一个summary-*.json文件记录本次会话中所有的问题、答案和通知。这个总结的价值在于审计与追溯对于自动化任务尤其是生产环境的操作有一份完整的人机交互记录至关重要。训练与优化你可以分析哪些决策点最常被触发从而优化脚本逻辑减少不必要的询问。用户反馈OpenClaw Agent可以将这份总结发送给用户让用户快速回顾刚才批准了哪些操作心中有数。确保你的OpenClaw Agent配置了处理summary-*.json的逻辑哪怕只是简单地将其内容转发到某个日志频道。5. 多实例运行、问题排查与性能考量当你想用这个模式来管理多个并行的Claude Code任务时比如同时让AI重构前端和后端代码就需要考虑多实例运行。5.1 多实例运行机制桥本身支持多实例。每个Claude Code进程启动时桥会生成一个独立的HTTP回调服务器监听不同端口和对应的唯一会话ID。所有的问题文件ask-{unique-id}.json都放在同一个IPC目录下。关键在于OpenClaw Agent的处理逻辑简单方式Agent读取所有ask-*.json文件然后将所有问题合并到一个消息里发送给用户并注明每个问题来自哪个任务通过CC_ID或CC_TASK区分。用户统一回复Agent再根据文件中的callbackUrl分别回传答案。高级方式Agent可以更智能地分组。例如将所有相同CC_WORKDIR的问题归为一组或者按CC_TASK描述归类。这需要你在Agent脚本中实现更复杂的解析和呈现逻辑。环境变量设置建议 为了在多实例下提供清晰上下文务必设置好CC_ID,CC_TASK,CC_WORKDIR。# 实例1处理前端 export CC_IDfe-redesign-$$ export CC_TASK将UI组件库从Antd迁移到MUI export CC_WORKDIR$PWD/frontend claude -p 开始迁移组件库 # 实例2处理后端 export CC_IDbe-api-refactor-$$ export CC_TASK将REST API重构为GraphQL export CC_WORKDIR$PWD/backend claude -p 开始设计GraphQL Schema 5.2 常见问题排查清单在实际使用中你可能会遇到一些问题。下面是一个快速排查指南现象可能原因排查步骤Claude Code调用ask_user后无响应最终超时1. OpenClaw Agent未运行或未正确配置。2. IPC目录权限问题。3. 回调HTTP服务器启动失败。1. 检查/tmp/cc-openclaw-bridge/目录下是否生成了ask-*.json文件。2. 检查OpenClaw Agent日志看它是否被唤醒并读取了文件。3. 检查桥的日志如果已配置看回调服务器是否在监听。用户在Telegram上回复了但Claude Code没收到答案1. OpenClaw Agent未正确POST到callbackUrl。2. 网络问题回调请求被拦截。3. 回调服务器已超时关闭。1. 查看OpenClaw Agent发送POST请求的日志确认URL和Payload正确。2. 使用curl手动模拟POST请求到callbackUrl看桥是否有响应。3. 检查桥的超时设置OPENCLAW_BRIDGE_TIMEOUT_MS是否太短。通知或问题没有发送到用户1. OpenClaw Agent的消息发送逻辑有误如Bot Token错误。2. 问题文件格式错误Agent解析失败。1. 检查OpenClaw Agent自身连接消息平台的日志。2. 直接查看IPC目录下的JSON文件确认其格式符合规范。多实例运行时答案混乱OpenClaw Agent没有正确关联答案与问题文件。1. 确保Agent在发送消息时携带了能区分任务的标识如CC_ID。2. 确保Agent在收到回复后能准确找到对应的callbackUrl。调试技巧启用桥的详细日志在启动Claude Code前设置DEBUGcc-openclaw-bridge:*环境变量可以在控制台看到桥的详细操作日志。手动测试Agent写一个简单的脚本模拟桥的行为在IPC目录创建一个JSON文件看你的Agent是否能正确处理。检查文件锁在Agent脚本中处理文件前先尝试用flock命令或其他机制加锁避免并发读写损坏JSON内容。5.3 性能与扩展性考量对于大多数个人或小团队的使用场景这个桥的性能绰绰有余。但如果你计划大规模部署需要考虑以下几点IPC目录的扩展性所有实例共享同一个文件系统目录。如果并发任务极多每秒数百个文件系统的IO可能成为瓶颈。此时可以考虑将IPC目录放在内存文件系统如/dev/shm上或者为不同类别的任务设置不同的子目录。HTTP回调服务器每个Claude Code实例都会启动一个独立的HTTP服务器。虽然端口是动态分配的但大量实例会占用较多端口资源。确保系统允许的临时端口范围足够大/proc/sys/net/ipv4/ip_local_port_range。OpenClaw Agent的负载Agent需要轮询文件系统。如果任务非常密集轮询间隔可能需要调整得更短但这会增加Agent的CPU使用率。一个优化方案是使用inotify等文件系统事件监听机制来替代轮询实现事件驱动但这需要更复杂的Agent实现。安全性回调服务器默认绑定在127.0.0.1这在单机环境下是安全的。如果在多机环境需要仔细配置网络和防火墙确保只有受信任的OpenClaw Agent可以访问回调端口。切勿在公网暴露回调服务器。我个人在几个长期运行的自动化代码审查和数据库迁移任务中使用了这个桥稳定性令人满意。它的价值不在于技术的高深而在于用简单的组件解决了一个切实的痛点——让无头AI工具具备了与人实时协作的能力。将决策权通过最常用的聊天工具交还给用户这种模式极大地扩展了自动化脚本的应用边界。从简单的“是否继续”到复杂的选择题和文本输入它让AI不再是黑盒执行而是变成了一个可随时请示、汇报的智能副手。