- 概述:频道如何工作
- 您需要什么:要求和一般步骤
- 示例:构建 webhook 接收器:最小单向演练
- 服务器选项:构造函数字段
- 通知格式:事件有效负载和传递行为
- 公开回复工具:让 Claude 发送消息回复
- 门控入站消息:发送者检查以防止提示注入
- 中继权限提示:将工具批准提示转发到远程频道
概述
Channel 是一个在与 Claude Code 相同的机器上运行的 MCP 服务器。Claude Code 将其作为子进程生成并通过 stdio 进行通信。您的频道服务器是外部系统和 Claude Code 会话之间的桥梁:- 聊天平台(Telegram、Discord):您的插件在本地运行并轮询平台的 API 以获取新消息。当有人向您的机器人发送 DM 时,插件接收消息并将其转发给 Claude。无需公开 URL。
- Webhooks(CI、监控):您的服务器在本地 HTTP 端口上侦听。外部系统 POST 到该端口,您的服务器将有效负载推送到 Claude。
您需要什么
唯一的硬性要求是@modelcontextprotocol/sdk 包和 Node.js 兼容的运行时。Bun、Node 和 Deno 都可以工作。研究预览中的预构建插件使用 Bun,但您的频道不一定要使用。
您的服务器需要:
- 声明
claude/channel能力,以便 Claude Code 注册通知侦听器 - 当发生某事时发出
notifications/claude/channel事件 - 通过 stdio transport 连接(Claude Code 将您的服务器作为子进程生成)
--dangerously-load-development-channels 在本地测试。有关详细信息,请参阅在研究预览期间测试。
示例:构建 webhook 接收器
本演练构建一个单文件服务器,该服务器侦听 HTTP 请求并将其转发到您的 Claude Code 会话中。最后,任何可以发送 HTTP POST 的东西,如 CI 管道、监控警报或curl 命令,都可以将事件推送到 Claude。
此示例使用 Bun 作为运行时,用于其内置的 HTTP 服务器和 TypeScript 支持。您可以改用 Node 或 Deno;唯一的要求是 MCP SDK。
编写频道服务器
创建一个名为 该文件按顺序执行三项操作:
webhook.ts 的文件。这是您的整个频道服务器:它通过 stdio 连接到 Claude Code,并在端口 8788 上侦听 HTTP POST。当请求到达时,它将主体作为频道事件推送到 Claude。webhook.ts
- 服务器配置:使用
claude/channel在其能力中创建 MCP 服务器,这是告诉 Claude Code 这是一个频道的原因。instructions字符串进入 Claude 的系统提示:告诉 Claude 期望什么事件、是否回复以及如果应该回复,使用哪个工具和传回哪个属性。 - Stdio 连接:通过 stdin/stdout 连接到 Claude Code。这对任何 MCP 服务器 都是标准的:Claude Code 将其作为子进程生成。
- HTTP 侦听器:在端口 8788 上启动本地 Web 服务器。每个 POST 主体都通过
mcp.notification()作为频道事件转发给 Claude。content成为事件主体,每个meta条目成为<channel>标签上的属性。侦听器需要访问mcp实例,因此它在同一进程中运行。对于更大的项目,您可以将其拆分为单独的模块。
向 Claude Code 注册您的服务器
将服务器添加到您的 MCP 配置中,以便 Claude Code 知道如何启动它。对于同一目录中的项目级 Claude Code 在启动时读取您的 MCP 配置并将每个服务器作为子进程生成。
.mcp.json,使用相对路径。对于 ~/.claude.json 中的用户级配置,使用完整的绝对路径,以便可以从任何项目找到服务器:.mcp.json
测试它
在研究预览期间,自定义频道不在允许列表上,因此使用开发标志启动 Claude Code:第一次在此项目中启动会话时,Claude Code 在使用来自 有效负载作为 在您的 Claude Code 终端中,您会看到 Claude 接收消息并开始响应:读取文件、运行命令或消息要求的任何操作。这是一个单向频道,因此 Claude 在您的会话中行动,但不会通过 webhook 发送任何内容回复。要添加回复,请参阅公开回复工具。如果事件没有到达,诊断取决于
.mcp.json 的新服务器之前要求同意。对话框报告”在此项目中找到新的 MCP 服务器:webhook”。选择使用此 MCP 服务器继续。当 Claude Code 启动时,它读取您的 MCP 配置,将您的 webhook.ts 作为子进程生成,HTTP 侦听器自动在您配置的端口上启动(此示例中为 8788)。您不需要自己运行服务器。启动横幅下方的暗淡通知确认频道已注册:Channels (experimental) messages from server:webhook inject directly in this session · restart without --dangerously-load-development-channels to stop。如果您看到”被组织政策阻止”,您的组织管理员需要启用频道。在单独的终端中,通过向您的服务器发送带有消息的 HTTP POST 来模拟 webhook。此示例向端口 8788 发送 CI 失败警报(或您配置的任何端口):<channel> 标签到达您的 Claude Code 会话中:curl 返回的内容:curl成功但没有任何内容到达 Claude:在您的会话中运行/mcp以检查服务器的状态。“Failed to connect”通常意味着您的服务器文件中存在依赖项或导入错误;检查~/.claude/debug/<session-id>.txt处的调试日志以获取 stderr 跟踪。curl失败,显示”connection refused”:端口要么尚未绑定,要么来自较早运行的陈旧进程正在占用它。lsof -i :<port>显示正在侦听的内容;在重新启动会话之前kill陈旧进程。
在研究预览期间测试
在研究预览期间,每个频道都必须在批准的允许列表上才能注册。开发标志在确认提示后绕过特定条目的允许列表。此示例显示两种条目类型:--channels 结合不会将绕过扩展到 --channels 条目。在研究预览期间,批准的允许列表由 Anthropic 策划,因此您的频道在您构建和测试时保持在开发标志上。
此标志仅跳过允许列表。
channelsEnabled 组织政策仍然适用。不要使用它来运行来自不受信任来源的频道。服务器选项
频道在Server 构造函数中设置这些选项。instructions 和 capabilities.tools 字段是标准 MCP;capabilities.experimental['claude/channel'] 和 capabilities.experimental['claude/channel/permission'] 是频道特定的添加:
| 字段 | 类型 | 描述 |
|---|---|---|
capabilities.experimental['claude/channel'] | object | 必需。始终为 {}。存在注册通知侦听器。 |
capabilities.experimental['claude/channel/permission'] | object | 可选。始终为 {}。声明此频道可以接收权限中继请求。声明后,Claude Code 将工具批准提示转发到您的频道,以便您可以远程批准或拒绝它们。请参阅中继权限提示。 |
capabilities.tools | object | 仅双向。始终为 {}。标准 MCP 工具能力。请参阅公开回复工具。 |
instructions | string | 推荐。添加到 Claude 的系统提示。告诉 Claude 期望什么事件、<channel> 标签属性的含义、是否回复,如果是,使用哪个工具以及传回哪个属性(如 chat_id)。 |
capabilities.tools。此示例显示双向设置,其中频道能力、工具和说明已设置:
notifications/claude/channel 调用 mcp.notification()。参数在下一部分中。
通知格式
您的服务器使用两个参数发出notifications/claude/channel:
| 字段 | 类型 | 描述 |
|---|---|---|
content | string | 事件主体。作为 <channel> 标签的主体传递。 |
meta | Record<string, string> | 可选。每个条目成为 <channel> 标签上的属性,用于路由上下文,如聊天 ID、发送者名称或警报严重性。键必须是标识符:仅字母、数字和下划线。包含连字符或其他字符的键会被静默删除。 |
Server 实例上调用 mcp.notification() 来推送事件。此示例推送带有两个元键的 CI 失败警报:
<channel> 标签中。source 属性从您的服务器配置的名称自动设置:
mcp.notification() 上的 await 在消息写入传输时解析,而不是在 Claude 处理它时解析。如果会话尚未将您的服务器加载为频道,或组织政策阻止它,事件会被静默删除,不会向您的服务器返回错误。
如果您需要传递确认,请在您的服务器中跟踪事件状态,并公开一个回复工具,Claude 可以调用它来报告状态回来。
事件排队进入会话并按顺序处理。如果在 Claude 忙碌时有多个通知到达,它们会在下一个轮次一起传递,Claude 将它们作为一个组处理。要并发处理独立事件流,请运行单独的会话。
公开回复工具
如果您的频道是双向的,如聊天桥接而不是警报转发器,请公开一个标准 MCP 工具,Claude 可以调用它来发送消息回复。关于工具注册的任何内容都不是频道特定的。回复工具有三个组件:- 您的
Server构造函数能力中的tools: {}条目,以便 Claude Code 发现工具 - 定义工具的架构并实现发送逻辑的工具处理程序
- 您的
Server构造函数中的instructions字符串,告诉 Claude 何时以及如何调用工具
注册回复工具
将以下内容添加到
webhook.ts。import 与您的其他导入一起位于文件顶部;两个处理程序位于 Server 构造函数和 mcp.connect() 之间。这注册了一个 reply 工具,Claude 可以使用 chat_id 和 text 调用它:webhook.ts,具有双向支持。出站回复通过 GET /events 使用 Server-Sent Events (SSE) 流式传输,因此 curl -N localhost:8788/events 可以实时观看它们;入站聊天到达 POST /:
"Full
门控入站消息
未门控的频道是提示注入向量。任何可以到达您的端点的人都可以在 Claude 前面放置文本。侦听聊天平台或公共端点的频道需要在发出任何内容之前进行真正的发送者检查。 在调用mcp.notification() 之前,根据允许列表检查发送者。此示例删除来自不在集合中的发送者的任何消息:
message.from.id,而不是 message.chat.id。在群组聊天中,这些不同,根据房间进行门控会让允许列表中的任何人向会话注入消息。
Telegram 和 Discord 频道以相同的方式在发送者允许列表上进行门控。它们通过配对引导列表:用户向机器人发送 DM,机器人回复配对代码,用户在其 Claude Code 会话中批准它,其平台 ID 被添加。有关完整配对流程,请参阅任一实现。iMessage 频道采用不同的方法:它在启动时从 Messages 数据库检测用户自己的地址,并自动让它们通过,其他发送者通过句柄添加。
中继权限提示
权限中继需要 Claude Code v2.1.81 或更高版本。较早的版本忽略
claude/channel/permission 能力。中继如何工作
当权限提示打开时,中继循环有四个步骤:- Claude Code 生成一个短请求 ID 并通知您的服务器
- 您的服务器将提示和 ID 转发到您的聊天应用
- 远程用户使用该 ID 回复是或否
- 您的入站处理程序将回复解析为判决,Claude Code 仅在 ID 匹配开放请求时应用它
权限请求字段
来自 Claude Code 的出站通知是notifications/claude/channel/permission_request。与频道通知一样,传输是标准 MCP,但方法和架构是 Claude Code 扩展。params 对象有四个字符串字段,您的服务器将其格式化为出站提示:
| 字段 | 描述 |
|---|---|
request_id | 从 a-z 中抽取的五个小写字母,不包括 l,因此在手机上输入时永远不会读作 1 或 I。将其包含在您的出站提示中,以便可以在回复中回显。Claude Code 仅接受携带其发出的 ID 的判决。本地终端对话不显示此 ID,因此您的出站处理程序是了解它的唯一方式。 |
tool_name | Claude 想要使用的工具的名称,例如 Bash 或 Write。 |
description | 此特定工具调用执行的操作的人类可读摘要,与本地终端对话显示的文本相同。对于 Bash 调用,这是 Claude 对命令的描述,或者如果没有给出,则是命令本身。 |
input_preview | 工具的参数作为 JSON 字符串,截断为 200 个字符。对于 Bash,这是命令;对于 Write,这是文件路径和内容的前缀。如果您只有一行消息的空间,请从您的提示中省略它。您的服务器决定显示什么。 |
notifications/claude/channel/permission,有两个字段:request_id 回显上面的 ID,behavior 设置为 'allow' 或 'deny'。允许让工具调用继续;拒绝拒绝它,与在本地对话中回答”否”相同。两个判决都不影响未来的调用。
向聊天桥接添加中继
向双向频道添加权限中继需要三个组件:- 您的
Server构造函数中experimental能力下的claude/channel/permission: {}条目,以便 Claude Code 知道转发提示 notifications/claude/channel/permission_request的通知处理程序,格式化提示并通过您的平台 API 发送它- 您的入站消息处理程序中的检查,识别
yes <id>或no <id>并发出notifications/claude/channel/permission判决通知,而不是将文本转发给 Claude
处理传入请求
在您的
Server 构造函数和 mcp.connect() 之间注册一个通知处理程序。当权限对话打开时,Claude Code 使用四个请求字段调用它。您的处理程序为您的平台格式化提示,并包括使用 ID 回复的说明:在您的入站处理程序中拦截判决
您的入站处理程序是接收来自您的平台的消息的循环或回调:与您根据发送者进行门控和发出
notifications/claude/channel 以将聊天转发给 Claude 的地方相同。在聊天转发调用之前添加一个检查,识别判决格式并改为发出权限通知。正则表达式匹配 Claude Code 生成的 ID 格式:五个字母,永远不是 l。/i 标志容忍手机自动更正将回复大写;在将其发送回之前将捕获的 ID 小写。- 不同格式:您的入站处理程序的正则表达式无法匹配,因此
approve it或yes之类的文本(没有 ID)会作为正常消息落入 Claude。 - 正确格式,错误的 ID:您的服务器发出判决,但 Claude Code 找不到具有该 ID 的开放请求并静默删除它。
完整示例
下面组装的webhook.ts 结合了本页的所有三个扩展:回复工具、发送者门控和权限中继。如果您从这里开始,您还需要初始演练中的项目设置和 .mcp.json 条目。
为了使两个方向都可以从 curl 测试,HTTP 侦听器提供两个路径:
GET /events:保持 SSE 流打开并将每个出站消息作为data:行推送,因此curl -N可以实时观看 Claude 的回复和权限提示到达。POST /:入站端,与之前相同的处理程序,现在在聊天转发分支之前插入了判决格式检查。
"Full
webhook.ts:
reply 工具发送其答案回复时,权限对话打开。本地对话在您的 Claude Code 终端中打开,片刻后,提示出现在 /events 流中,包括五字母 ID。从远程端批准它:
reply 工具运行,Claude 的回复在流中着陆。
此文件中的三个频道特定部分:
Server构造函数中的能力:claude/channel注册通知侦听器,claude/channel/permission选择加入权限中继,tools让 Claude 发现回复工具。- 出站路径:
reply工具处理程序是 Claude 为会话响应调用的;PermissionRequestSchema通知处理程序是当权限对话打开时 Claude Code 调用的。两者都调用send()通过/events广播,但它们由系统的不同部分触发。 - HTTP 处理程序:
GET /events保持 SSE 流打开,以便 curl 可以实时观看出站;POST是入站,根据X-Sender标头进行门控。yes <id>或no <id>主体作为判决通知进入 Claude Code,永远不会到达 Claude;其他任何东西都作为频道事件转发给 Claude。
打包为插件
要使您的频道可安装和可共享,请将其包装在插件中并将其发布到市场。用户使用/plugin install 安装它,然后使用 --channels plugin:<name>@<marketplace> 按会话启用它。
发布到您自己的市场的频道仍然需要 --dangerously-load-development-channels 来运行,因为它不在批准的允许列表上。默认允许列表是 claude-plugins-official 中的频道插件,由 Anthropic 自行策划。应用内提交表单将插件添加到社区市场,该市场不在频道允许列表上。
如果您正在与 Anthropic 合作伙伴联系合作,请与他们联系以协调官方市场列表。在 Team 和 Enterprise 计划上,管理员可以改为将您的插件包含在组织自己的 allowedChannelPlugins 列表中,该列表替换默认的 Anthropic 允许列表。