Claude Code 的 Channels 功能为外部系统提供了一种将事件实时推送到运行时会话中的机制。与传统的命令行交互不同,Channels 允许 CI/CD 流水线、监控系统、Webhook 服务甚至即时通讯平台与正在运行的 Claude Code 进程建立双向通信链路。这一能力基于 Model Context Protocol(MCP)构建,本质上是一个特殊的 MCP 服务器,通过 stdio 传输层与 Claude Code 主进程交换数据。本文将从协议层面深入剖析 Channels 的技术实现,探讨如何构建自定义通道以支持 IDE 与 Agent 进程的双向实时通信。
核心架构:Channel 作为 MCP 服务器
Claude Code Channels 的设计遵循了 MCP 协议的扩展约定。从架构角度看,每个 Channel 实际上是一个运行在本地机器上的 MCP 服务器,Claude Code 以子进程的方式启动它并通过标准输入输出进行通信。这种设计避免了暴露额外的网络端口,同时保持了协议的一致性。根据官方文档,Channel 服务器需要满足三个核心要求:声明 claude/channel 能力以注册通知监听器、在事件发生时发送 notifications/claude/channel 通知、以及使用 stdio 传输层进行进程间通信。
外部系统与 Channel 服务器的连接方式取决于具体场景。对于聊天平台(如 Telegram 和 Discord),插件在本地运行并轮询平台的 API,当用户直接消息到达时,插件接收消息并转发给 Claude Code。而对于 Webhook 类型的场景(如 CI 构建失败、监控告警),服务器监听本地 HTTP 端口,外部系统通过 POST 请求将事件发送到该端口,再由服务器推送到 Claude Code 会话中。这种灵活的架构使得开发者可以根据实际需求选择合适的接入方式。
事件通知协议与数据格式
当 Channel 服务器需要向 Claude Code 推送事件时,需要调用 MCP 服务器的 notification() 方法,指定方法名为 notifications/claude/channel。通知携带两个关键参数:content 表示事件主体内容,以字符串形式传递;meta 为可选的元数据对象,每个键值对都会作为属性附加到 <channel> 标签上,用于传递路由上下文信息。需要特别注意的是,元数据键必须是有效的标识符,仅包含字母、数字和下划线,包含连字符或其他特殊字符的键会被静默丢弃。
事件到达 Claude Code 侧后,会被包装在 <channel> 标签中呈现给模型。标签的 source 属性自动设置为服务器配置的名称,其他元数据键则作为额外属性出现。例如,当一个 CI 构建失败事件到达时,Claude 看到的上下文类似于:<channel source="ci-bot" severity="high" run_id="1234">build failed on main: https://ci.example.com/run/1234</channel>。这种结构化的事件表示方式使得 Claude 能够理解事件来源、提取关键信息并做出适当的响应。
对于需要双向通信的场景,Channel 服务器需要暴露一个标准的 MCP 工具。具体实现包括在服务器构造函数的 capabilities.tools 字段中声明工具支持、注册 ListToolsRequestSchema 和 CallToolRequestSchema 的处理程序、以及在 instructions 字段中向 Claude 说明何时以及如何使用回复工具。官方提供的 fakechat 演示服务器展示了完整的双向通信实现,包括文件附件处理和消息编辑功能。
构建自定义 Channel 的技术步骤
构建一个自定义 Channel 服务器首先需要安装 @modelcontextprotocol/sdk 包,这是 MCP 协议的标准实现库。运行时方面,官方预构建插件使用 Bun,但开发者也可以选择 Node.js 或 Deno,只要能够运行 MCP SDK 即可。创建服务器实例时,需要在 capabilities 中声明 experimental['claude/channel'] 字段,这是一个空对象,其存在本身即表示该服务器具备 Channel 功能。
以下是一个最小化的单向 Channel 服务器实现示例,使用 Bun 作为运行时:
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
const mcp = new Server(
{ name: 'my-channel', version: '0.0.1' },
{
capabilities: {
experimental: { 'claude/channel': {} },
},
instructions: 'Events arrive as <channel source="my-channel">. Handle them appropriately.',
},
)
await mcp.connect(new StdioServerTransport())
// 推送事件的调用方式
await mcp.notification({
method: 'notifications/claude/channel',
params: {
content: 'build failed on main branch',
meta: { severity: 'high', commit: 'abc123' },
},
})
对于需要接收回复的双向通道,需要在 capabilities 中添加 tools: {},并在服务器中注册工具处理程序。工具的 schema 定义遵循标准 MCP 约定,包括名称、描述和输入参数架构。处理程序中实现实际的发送逻辑,例如调用外部 API 将消息发送回原始平台。
安全防护:发送者验证与权限控制
将外部事件直接注入 AI 模型的运行时会话存在潜在的安全风险,特别是 prompt 注入攻击的可能性。为此,Claude Code Channels 实现了多层次的安全防护机制。最核心的是发送者允许列表(allowlist)机制:每个已批准的 Channel 插件维护一个仅允许特定 ID 推送消息的列表,来自未列入名单发送者的消息会被静默丢弃。
对于 Telegram 和 Discord 这类平台,Channel 通过配对流程(pairing flow)来建立允许列表:用户首先在平台上向机器人发送任意消息,机器人回复一个配对代码,然后在 Claude Code 会话中批准该代码,用户的平台 ID 就会被添加到允许列表中。这种设计确保了只有经过显式授权的用户才能向会话推送事件。
在企业场景下,Team 和 Enterprise 计划的管理员可以通过托管设置全局控制 Channels 功能的可用性。默认情况下,Pro 和 Max 计划的个人用户可以自由使用 Channels,但需要通过 --channels 标志在每个会话中单独启用。对于组织用户,管理员需要在 claude.ai 管理后台明确启用 channelsEnabled 设置,否则即使 MCP 服务器已连接,Channel 消息也不会到达会话。如果设置被禁用,用户启动时会收到提示,要求管理员开启该功能。
研究预览期的限制与测试方法
在当前的研究预览阶段,Claude Code Channels 存在一些特定限制。首先,所有可用的 Channel 插件必须来自 Anthropic 维护的允许列表,自定义插件不能直接使用。用户如果想测试自己构建的 Channel,需要使用 --dangerously-load-development-channels 标志来绕过允许列表检查。这个标志是按条目生效的,与 --channels 标志配合使用时不会扩展绕过范围。
使用开发标志启动 Claude Code 的方式有两种:对于作为插件构建的 Channel,使用 claude --dangerously-load-development-channels plugin:yourplugin@yourmarketplace;对于尚无插件包装的原始 .mcp.json 服务器,使用 claude --dangerously-load-development-channels server:webhook。研究预览期间,官方提供的预置 Channel 包括 Telegram、Discord 和用于本地演示的 fakechat。如果希望将自定义 Channel 提交到官方插件市场,需要通过安全审查流程才能被添加到允许列表中。
对于需要长期运行 unattended 工作流的用户,需要注意事件仅在会话保持运行时才会到达。如果用户离开终端且遇到权限提示符,会话会暂停直到用户在本地批准。为了支持无人值守的自动化场景,可以使用 --dangerously-skip-permissions 标志绕过权限提示,但该选项仅应在完全信任的环境中使用,因为这样会允许 Claude Code 自动执行任何操作而无需用户确认。
工程实践建议
在实际项目中集成 Claude Code Channels 时,建议采用以下工程实践。首先,根据业务场景选择合适的通道类型:单向通道适用于监控告警、CI/CD 通知等只需要将事件推送给 Claude 处理的场景;双向通道则适用于需要 Claude 通过聊天界面回复用户或执行操作后反馈结果的场景。
其次,在生产环境中,务必实现完整的发送者验证逻辑。不应仅依赖平台层面的身份验证,而应在 Channel 服务器端检查发送者 ID 是否在允许列表中。官方文档特别强调应该基于发送者身份(message.from.id)进行 gating,而非基于房间或聊天 ID,因为在群聊场景下这两者不同,基于房间 gating 会允许群内任何人注入消息。
最后,对于需要高可用性的无人值守场景,建议将 Claude Code 运行在持久化的后台进程或终端会话中,并结合监控告警系统确保进程健康。同时应该仔细评估 --dangerously-skip-permissions 的使用场景,确保自动化操作不会导致意外的系统变更。
参考资料
- Claude Code 官方文档:Push events into a running session with channels(https://code.claude.com/docs/en/channels)
- Claude Code 官方文档:Channels reference(https://code.claude.com/docs/en/channels-reference)