连接器

Channels 频道通知

把外部 IM 的入站消息推送到正在运行的会话——你不在终端时,千手大师也能收到消息并做出回应。

  • 飞书 / Telegram / Discord / 微信
  • MCP 插件协议
  • --channels

这是什么

在 Channels 的模型里,一个「频道」本质上就是一个 MCP 服务器:它对外提供发送消息的工具(出站), 并在收到外部消息时向千手大师发送一条 MCP 通知 notifications/claude/channel(入站)。 客户端把通知内容包进一个 <channel> 标签后入队,模型据此判断消息来源,并决定用哪个工具回复。

这意味着 Channels 不是某一家的专有集成,而是一套协议:只要某个 MCP 服务器声明了 capabilities.experimental['claude/channel'] 能力,它就能把外部事件推送进你正在运行的会话。

入站消息被包装成的结构
<channel source="plugin:weixin:weixin" chat_id="..." sender_id="..." message_id="...">
消息正文
</channel>

meta 字段会被渲染成标签属性,因此键名必须是合法标识符([a-zA-Z_][a-zA-Z0-9_]*), 实际使用中常见的键是 chat_id、user、message_id。

i
和 Bridge / 远程控制的区别

Channels 是「外部事件推入会话」,面向 IM 消息;Bridge 面向远程会话控制与交互,二者是独立模块。

前置条件

  • 一个正在运行的千手大师会话(交互式或 print/SDK 模式均可,--channels 两者都支持)。
  • 一个已连接、且声明了 claude/channel 能力的 MCP 服务器。非频道服务器不会被注册通知处理器(连接本身保持正常)。
  • 在启动命令中用 --channels 显式列出该服务器——这是会话级开关,也是对「允许它推送入站消息」的信任声明。
  • 插件型频道需通过市场白名单校验;企业/团队组织可通过托管设置自行指定 allowedChannelPlugins。
✓
渠道开关默认开启

源码中 isChannelsEnabled() 恒为 true(已绕过 GrowthBook 开关),无需额外申请即可使用。

启用方式

--channels 的每一项都必须带 plugin: 或 server: 前缀标签, 未打标签或缺少市场的插件项会直接报错并以退出码 1 结束:

合法标签格式
plugin:<name>@<marketplace>   # 市场插件提供的频道(强制走白名单)
server:<name>                 # 手动配置的 MCP 服务器
  1. 安装或配置频道来源:市场插件用 /plugin install 安装;手动服务器则在 MCP 配置中加入。
  2. 在启动命令中声明频道:重复该参数或一次列出多项均可。
    启用频道监听
    # 插件格式(走白名单校验)
    qsdashi --channels plugin:feishu@claude-code-feishu-channel
    
    # 服务器格式(手动配置的 MCP 服务器)
    qsdashi --channels server:my-slack-bridge
    
    # 同时启用多个频道:重复该参数或一次列出多项
    qsdashi --channels plugin:feishu@claude-code-feishu-channel --channels server:discord-bot
  3. 确认启动提示:启动界面会打印 Listening for channel messages from: ...,并附带提示注入风险警告。 该项只表示「白名单已设置」,服务器是否真正连上、是否匹配到 MCP 服务器仍需以实际连接为准。

开发模式

测试自定义频道(尚未进入白名单)时,可用 --dangerously-load-development-channels。 它仅限交互式会话,启动时会弹出确认对话框;接受后仅绕过 --channels 的白名单校验, 不会绕过组织策略,且绕过不泄露到同时传入的 --channels 条目。

开发模式
qsdashi --dangerously-load-development-channels server:my-custom-channel

支持的平台

Channels 通过市场插件或内置插件接入,以下为仓库文档中明确列出的来源:

Channel说明来源
Telegram官方 Telegram Bot 集成/plugin install telegram@claude-plugins-official
Discord官方 Discord Bot 集成/plugin install discord@claude-plugins-official
iMessagemacOS 原生消息/plugin install imessage@claude-plugins-official
飞书 (Feishu / Lark)双向消息、群组聊天、文件附件社区插件 claude-code-feishu-channel
微信 (WeChat)内置 channel,扫码登录、双向消息、附件透传内置,plugin:weixin@builtin
i
Slack 等属于「服务器格式」示例

除上述插件外,任何实现了频道协议的 MCP 服务器都可通过 server:<name> 接入, 文档与源码注释中出现的 server:my-slack-bridge 即属此类示例,并非官方预置插件。

参数与配置

参数作用说明
--channels <entries...> 声明本会话允许推送入站消息的频道 每项须为 plugin:name@marketplace 或 server:name;可重复或一次多项
--dangerously-load-development-channels <entries...> 加载未进入白名单的频道 仅交互式;启动需确认;不绕过组织策略
qsdashi weixin login 扫码登录微信账号 内置微信 Channel 专用
qsdashi weixin login clear 清除已登录的微信账号 删除本地账号凭据
qsdashi weixin access pair <code> 确认微信配对码 授权后该用户消息才会进入会话

白名单与组织策略

插件型频道的白名单来自 GrowthBook 的 tengu_harbor_ledger,粒度为插件级 (插件获批则其下所有频道服务器获批)。团队/企业组织若在托管设置中配置了 allowedChannelPlugins,它会取代该账本,由管理员承担信任决定。

校验是两段式的:先比对「你输入的标签」与「实际安装的插件来源」是否一致(pluginSource 的市场必须匹配), 再比对白名单。标签只是意图,运行时的 plugin:name:X 可能来自任何市场,因此必须核实。

内置微信 Channel

仓库内置了微信 Channel(plugin:weixin@builtin),无需安装外部市场插件。它是一个本地 stdio MCP 服务器,通过轮询微信接口接收消息,并暴露两个出站工具。

登录与会话启用

微信登录与启用
# 扫码登录(终端展示二维码 / URL)
qsdashi weixin login

# 清除登录状态
qsdashi weixin login clear

# 在会话中启用内置微信 channel
qsdashi --channels plugin:weixin@builtin

账号凭据保存在 ~/.claude/channels/weixin/account.json(权限 0600), 可用环境变量 WEIXIN_STATE_DIR 覆盖状态目录。

配对授权

默认访问策略为 pairing(配对)。当收到未授权用户的消息时,Channel 会回一条 6 位数字配对码(有效期约 10 分钟),并提示运营侧在终端确认:

确认配对
qsdashi weixin access pair <code>

确认后该用户的 ID 写入 access.json 的 allowFrom 列表,后续消息才会进入会话。 访问策略支持 pairing、allowlist、disabled 三种取值。

可用的 MCP 工具

工具参数作用
reply chat_id、text、可选 files[] 回复微信消息,可附带本地绝对路径的附件
send_typing chat_id 发送「正在输入」状态

服务器会透传图片、语音、文件、视频附件:下载解密后落到临时目录,并在入站消息里带上 attachment_path / attachment_type 元数据;语音还会附带转写文本。

远程权限审批

声明了 capabilities.experimental['claude/channel/permission'] 的频道服务器, 还能把工具权限对话框转发到你的手机上。流程是双向、结构化的:

  1. 客户端发送审批请求:当权限对话框打开时,客户端发出 notifications/claude/channel/permission_request, 携带 request_id、tool_name、description 与截断到约 200 字符的 input_preview。
  2. 你回复简短指令:服务器把提示格式化后发到对应平台,你回复形如 yes <5位短码> 或 no <5位短码> 的消息。
  3. 服务器回传结构化事件:服务器解析回复后发出 notifications/claude/channel/permission,携带 {request_id, behavior}。客户端按 request_id 匹配待处理项——它不会对普通频道文本做正则匹配, 因此只有服务器显式发出该事件才可能触发审批。
权限回复格式(服务器侧需实现)
/^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i

短码为 5 位小写字母(字母表去掉易与 1/I 混淆的 l),大小写不敏感以适配手机自动纠错。 内置微信 Channel 会把提示格式化为「Tool / Reason / Input」并附带回复方法。

安全与注意事项

!
入站消息携带提示注入风险

频道消息最终会作为对话内容进入模型上下文。启动提示明确警告: inbound messages will be pushed into this session, this carries prompt injection risks。 只对可信来源启用频道;不再需要时,重启并去掉 --channels 参数即可关闭。

!
信任边界是白名单,不是终端

权限转发依赖频道服务器解析并回传事件。被攻陷的频道服务器可以伪造 yes <id> 事件。 这是已知并接受的残余风险——审批对话框只增加攻击成本,不能彻底阻断已被攻陷的频道。

  • 频道服务器必须显式声明能力,客户端才注册对应通知处理器;能力缺失的服务器被跳过,连接本身不受影响。
  • 频道是否被信任取决于它出现在 --channels 列表里,而非运行时形态推断,这能防止受信服务器「偷偷」加上能力。
  • 服务器格式(server:)的条目不参与插件白名单(schema 仅支持插件),只在开发标志下被放行。
  • 权限转发还受独立运行时开关 tengu_harbor_permissions 控制,在会话挂载时读取一次,会话中途变更需重启生效。

常见问题与排错

启动时报「entries must be tagged」

--channels 的每一项都必须带 plugin: 或 server: 前缀,且插件项必须含 @marketplace。缺少标签、缺少市场名都会被视为硬错误。

启动提示显示了频道,但没有消息进来

  • 提示只代表白名单已设置,不代表服务器已连接。
  • 确认对应的 MCP 服务器已配置且连接成功;server: 条目若没有同名服务器配置会被标记为未匹配。
  • 确认服务器声明了 claude/channel 能力,否则通知处理器不会注册。
  • 收到的消息若非白名单用户,需先完成配对授权,否则会被挡在会话之外。

提示「you asked for plugin:X@Y but the installed X is from Z」

标签里的市场与实际安装来源不一致。安装的插件来自其它市场,需改用正确的 @marketplace,或重新安装。

微信扫码后仍提示未连接

检查状态目录下的 account.json 是否存在。会话过期(接口返回 errcode -14)时轮询会暂停约 30 秒后重试,必要时重新执行 qsdashi weixin login。

团队/企业环境里插件被拦

组织若设置了 allowedChannelPlugins,它会取代默认白名单。请让管理员把对应插件加入托管设置。