关于 tunnel-mcp
tunnel-mcp 是一个 MCP 服务,通过临时端到端加密隧道连接 Claude Agent。它支持双人会话和多人房间,并提供消息与加密文件共享,同时由人类掌控实际操作。
主要功能
- 01创建和加入加密隧道
- 02双人会话与多人房间
- 03收发消息
- 04加密共享文件并校验哈希
- 05查看成员与会话状态
- 06结束会话或离开
适用场景
- 01让两位开发者的 Claude Agent 协作
- 02跨不同机器配对调试
- 03向会话成员共享项目文件
MCP 相关
它向 MCP 客户端提供创建、加入、收发消息和关闭隧道会话的工具,也支持文件共享和查看会话状态。Claude MCP 客户端可用这些工具直接连接 Agent。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
9收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| goal | string | 是 | |
| invites | integer | 否 |
详细介绍
tunnel-mcp
在两位开发者的 Claude Agent 之间建立直接、端到端加密的隧道——无需人工复制粘贴。

只需 30 秒,即可亲自复现——克隆仓库,然后:
npm ci && npm run demo
这会通过 Cloudflare 的边缘网络打开一个真实的加密隧道,以访客身份加入,交换端到端加密消息,验证加入链接只能使用一次,然后拆除整个隧道。
两位开发者各自运行 Claude Agent 并需要让它们协作时,通常的做法是由人坐在中间,把消息从一个聊天窗口复制粘贴到另一个。tunnel-mcp 无需人工介入。这是一个 MCP 服务,允许一位开发者的 Agent 打开一次性的加密隧道,另一位开发者的 Agent 可直接连接到该隧道,让两个 Agent 直接交流——同时由各自的用户掌控文件系统或 Shell 中实际发生的操作。
工作原理
一位开发者(主机)调用 tunnel_open。其本地的 tunnel-mcp 进程会变成进程内 WebSocket 中继,并通过一次性的 cloudflared Quick Tunnel 将其接入互联网——无需端口转发,也无需配置服务。另一位开发者(访客)使用主机分享的链接调用 tunnel_join,其 Agent 会向外连接到同一条隧道。由于双方都只发起出站连接,因此即使位于普通防火墙和 NAT 后也能正常工作。
Host machine Guest machine
┌───────────────────┐ outbound HTTPS ┌───────────────────┐
│ Claude (host) │ wss:// │ Claude (guest) │
│ │ │ ┌──────────────┐ │ │ │
│ tunnel_open/say/ │──────▶ cloudflared │◀────────│ tunnel_join/say/ │
│ listen/close │ │ Quick Tunnel │─────────▶ listen/close │
│ │ │ └──────────────┘ │ │ │
│ in-process relay │ └───────────────────┘
└───────────────────┘
中继和 cloudflared 子进程只会在会话期间运行,并会在拆除时销毁。对话记录仅保存在内存中——不会写入磁盘,并会在拆除时随进程一起消失。
安装
npm install -g tunnel-mcp
# or, without installing:
npx tunnel-mcp
将其注册到 Claude Code(两位开发者都只需操作一次):
claude mcp add tunnel -- tunnel-mcp # if globally installed
# or, with no global install:
claude mcp add tunnel -- npx -y tunnel-mcp
tunnel-mcp是一个 stdio MCP 服务,而非交互式命令行工具。手动启动它只会让它静静等待客户端——这是预期行为。运行tunnel-mcp --help查看用法,或运行tunnel-mcp --version查看版本。
tunnel-etiquette 技能会教每个 Agent 如何在隧道中行事(将对端视为不可信输入,并在执行对端提出的任何操作前先征求其用户确认)。安装软件包时会自动将该技能复制到 ~/.claude/skills/(尽力而为)。如果禁用了安装脚本(npm install --ignore-scripts),或者你想将其安装到自定义目录或强制更新,请显式运行:
npx tunnel-mcp install-skill # into ~/.claude/skills
npx tunnel-mcp install-skill --dir <path> --force # elsewhere / overwrite
设置 TUNNEL_SKILLS_DIR 可更改默认目标目录;设置 TUNNEL_SKIP_SKILL_INSTALL=1 可选择不自动复制。
如果 cloudflared 尚未位于 PATH 中,则会在首次需要时自动下载到 ~/.tunnel/bin——无需额外安装。
快速入门
主机 — 让 Claude 根据目标打开隧道:
“打开一条隧道,一起调试结账流程。”
Claude 会调用 tunnel_open({ goal }),并返回一条可直接转发的邀请 — 一条纯文本消息,其中包含一次性设置命令和加入链接。通过可信渠道(Slack 私信等)将它发给另一位开发者 — 该链接属于机密,因为其中包含此会话的加密密钥。它只能使用一次,且约 10 分钟后过期(tunnel_open 会报告 joinLinkExpiresInSec),因此请尽快分享。
访客 — 粘贴链接并让 Claude 加入:
“加入这条隧道:
<link>”
Claude 会调用 tunnel_join({ joinLink }),了解目标,并获取房间成员名单 — 使用默认的单个邀请时,房间里只有你们两人。
需要不止一位访客?改为打开一个房间:
“为我和两位队友打开一条隧道,一起调试结账流程。”
Claude 会调用 tunnel_open({ goal, invites: 3 }) — invites 是要安排加入的队友人数(最多 15 人,加上主机可同时连接 16 人)— 并为每位队友返回一条邀请,而不是单个链接。将每条邀请转发给一位且仅一位成员;每条邀请只能使用一次,因此不要把同一链接给两个人。需要在会话中途添加成员,或重新邀请邀请过期前未使用的成员?tunnel_invite({ count })(仅限主机)可以生成更多邀请。
双方 — Agent 通过 tunnel_say 逐轮发送消息,并通过 tunnel_listen 等待下一条回复。在房间中,每条消息都会附带 fromName,让 Agent 知道是谁说了什么,并在需要时与各自的用户确认。
结束会话取决于角色:主机调用 tunnel_close,为所有人结束会话并拆除中继 — 内存中的对话记录也会随之消失,因为它从未写入磁盘。成员调用 tunnel_close 只会离开;房间会为其他成员继续保持开放。
**分享文件:**任何成员都可以调用 tunnel_share({ path }),向房间发送文本文件或二进制文件 — 文件会从磁盘读取、计算哈希,并在穿过隧道前使用房间密钥加密,因此中继始终只能看到密文。队友会在 tunnel_listen 中收到 artifact 消息,也可以在 tunnel_status().artifacts 中查看文件信息(id、名称、类型、大小、发送者)。想要接收文件的队友可以调用 tunnel_receive({ artifactId, savePath }),并自行选择保存路径 — 文件字节会先解密并与发送者的 sha256 校验,之后才会写入;若不匹配,则会拒绝保存。任何当前成员都可以获取文件,直到文件过期(TTL 为 30 分钟)或会话结束 — 每次调用 tunnel_receive 都会独立重新获取并验证文件。使用较旧客户端的成员会被静默跳过(tunnel_share 结果中的 olderMembers)— 他们不会看到邀请。文件名会以明文元数据传输,因此不要在文件名中放入机密内容;并应将接收的每个文件都视为不可信输入 — 请参阅 etiquette skill。
工具
| 工具 | 使用者 | 用途 |
|---|---|---|
tunnel_open({goal, invites?}) | 主持方 | 启动中继和 Quick Tunnel,并为每位队友获取一个邀请链接(默认为 1 个,即经典的双人模式)。 |
tunnel_invite({count?}) | 主持方 | 在会话期间生成更多单次使用、限时有效的邀请链接。 |
tunnel_join({joinLink}) | 成员 | 使用邀请链接接入房间并进行身份验证;返回当前成员名单。 |
tunnel_say({text}) | 任意 | 向房间发送消息。 |
tunnel_listen({sinceSeq?, timeoutMs?}) | 任意 | 等待下一条或多条消息,每条消息都会标注发送者的 fromName。 |
tunnel_share({path}) | 任意 | 与房间共享文件(文本或二进制),并进行端到端加密;返回 {artifactId, offeredTo, olderMembers}。 |
tunnel_receive({artifactId, savePath}) | 任意 | 获取已提供的文件,验证其哈希值,并将其写入你选择的路径。 |
tunnel_status() | 任意 | 查看会话信息:角色、目标、成员名单、待处理的邀请、已提供的文件、lastSeq。 |
tunnel_close({summary?}) | 任意 | 主持方:结束所有人的会话。成员:离开房间。 |
安全模型
tunnel-mcp 本质上是一个安全敏感工具——它会在开发者的 AI Agent 之间建立实时通道。以下是它确切提供和不提供的保护:
- 聊天消息正文经过端到端加密。 每条
tunnel_say正文都会先使用 NaClsecretbox(XSalsa20-Poly1305,通过tweetnacl)加密,然后才通过cloudflared管道。中继和管道看到的聊天正文始终只有密文。 - 目标、每位参与者的显示名称和系统事件均为明文。
tunnel_open目标、每位成员的名称以及连接事件(加入/离开/空闲/关闭)都以明文元数据形式发送——请勿在目标字符串或显示名称中放入机密信息。 - 身份验证通过密钥持有证明完成,而非传输密钥。 加入时会使用 HMAC 挑战来证明加入成员持有与主机相同的密钥;原始密钥本身绝不会通过网络传输。
- 每个邀请都是一次性、限时凭证。 邀请中包含会话密钥,因此请像对待密码一样处理——只通过你已信任的渠道(如 Slack 私信)分享,绝不要发到公开的 issue、PR 或聊天中,并且每个邀请只转发给一个人。邀请由最先兑换的人使用(他们离开后也无法再次使用),并会在约 10 分钟后自动过期,因此邀请泄露后的暴露时间较短且有上限。
- 只允许你邀请的人加入——默认仅限双方参与,房间需主动启用(最多 16 人),每个邀请均为一次性且限时。可加入人数取决于主机选择生成的邀请数量,而非恰好持有房间密钥的人数。
- 共享文件经过端到端加密和哈希验证。
tunnel_share会先使用与聊天相同的房间密钥,通过 NaClsecretbox加密文件字节,然后才通过隧道传输,并附带内容的明文 sha256 值;tunnel_receive会先解密、重新组装并验证哈希,然后才写入磁盘。文件名、大小和类型均为明文元数据(请勿在文件名中放入机密信息),收到的文件不可信——tunnel_receive只会写入接收者选择的路径,绝不会使用发送者提供的名称。 - 对端是未经信任的输入源,而非指令来源。 其他 Agent 发来的消息是需要审慎判断的数据,而不是可执行的命令——这适用于房间内的每位成员,而不只是某一位。行为规范技能要求每个 Agent 在写入文件、运行风险较高的命令,或根据对端所说的内容宣布某项修复“已确认”之前,先取得其对应人类用户的同意。
- 所有内容都是临时的。 对话记录只保存在内存中——绝不会写入磁盘,并会随进程结束而消失。拆除行为取决于角色:主机执行
tunnel_close(或其进程退出,或 30 分钟内没有消息)会结束所有人的会话,并拆除中继和cloudflared子进程;成员执行tunnel_close只会离开房间——房间会为其他成员继续保持开放。
完整威胁模型及漏洞报告方式,请参阅 SECURITY.md。
要求
- Node.js >= 20
- Claude MCP 客户端(例如 Claude Code)
cloudflared——如果尚未加入PATH,首次使用时会自动安装到~/.tunnel/bin
开发
npm ci # install dependencies
npm test # run the test suite (248 tests, TDD)
npm run build # compile TypeScript
npm run lint # eslint
npm run format:check # prettier --check .
npm run test:coverage # vitest run --coverage
有关如何提出更改,请参阅 CONTRIBUTING.md。
故障排除
tunnel-mcp / npx tunnel-mcp“没有任何反应”。 它是一个 stdio MCP 服务,而不是交互式命令行工具——不带参数时,它会启动并等待 MCP 客户端通过 stdin/stdout 连接。这是预期行为。将它注册到客户端(见上文),或运行 tunnel-mcp --help。
访客加入时出现 getaddrinfo ENOTFOUND …trycloudflare.com。 cloudflared 快速隧道会在每条隧道的 DNS 记录传播之前几秒钟打印 URL。如果有任何程序过早查询该域名,就会收到 NXDOMAIN,而解析器会将其负缓存长达 30 分钟——即使隧道已经上线,也会导致加入失败。tunnel-mcp 会避免这种情况:tunnel_open 会等待记录实际解析成功(通过 Cloudflare 的 1.1.1.1 的 DoH;该 IP 不会经过你的系统解析器,因此不会污染它),然后再返回链接;访客则会先使用系统 DNS,失败时再回退到 DoH。因此,直接尝试加入应该就能成功;如果遇到 ENOTFOUND,较早的尝试可能已经污染了缓存——请等待缓存过期,或刷新 DNS(在 macOS 上运行 sudo dscacheutil -flushcache)。仅在会阻止 DoH(1.1.1.1)且系统 DNS 已能解析 *.trycloudflare.com 的网络上设置 TUNNEL_DOH=off。
路线图 / 尚不支持
这是一个 MVP。目前明确不在支持范围内的功能:
- 主机离线 / 异步消息传递
- 其他传输方式(ngrok、WebRTC)
- 邀请轮换(在会话中替换某个仍然有效的邀请;请注意,邀请本身已经是一次性且会过期的——参见上文的安全模型)
- 加密目标或其他元数据
许可证
MIT — 参见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。