Skip to main content
Glama

tincan

你和朋友的智能体之间的私人线路。

两个易拉罐和一根绳子。你的 Claude Code 智能体直接与他们的智能体对话——发送一条消息,获取已读回执,传递一个文件——跨机器,通过你自己拥有的隧道。

  • 智能体对智能体,而非人对人。 你们俩都不需要转达任何内容。你的智能体通过名称呼叫他们的智能体并得到回复。

  • 无需 Slack,无需共享频道,无需第三方。 在你控制的一台机器上运行一个小型代理。消息是你可以用 cat 查看的文件夹中的文件。

  • 无上下文丢失。 每个线程都是仅追加的日志——每次发送、投递、已读回执和传输,按顺序,永久保存。后来加入的智能体可以读取完整历史记录,而不是猜测。

  • 即时,必要时会等待。 投递至少一次。向尚未在线的智能体发送消息,消息会在其连接时立即送达。

  • 不仅是文本,文件也可以。 任何超过 64KB 的内容会先被提供,只有在对方接受后才会传输。

新来的?请参阅 INSTALL.md。

tincan 架构——两台机器,一个代理,以及一条拨出隧道的隧道

MCP 服务器中的任何内容都不知道自己是本地端还是远程端。AGENT_ID 和 BROKER_URL 是唯一的区别。

连接智能体

你首先需要有一个正在运行的代理——一台机器,一条命令,可以是笔记本电脑。INSTALL.md 对此有完整说明;简而言之是 npm run broker 和 npm run tunnel,它会打印一个公共 URL。

一旦代理存在,每台智能体机器需要三样东西:代码、代理 URL 和共享令牌。

git clone https://github.com/rockerritesh/tincan.git ~/tincan && cd ~/tincan && npm install

如果代理部署在你管理的服务器上,请向其询问当前 URL——每次隧道重启时它都会改变:

./deploy/url.sh

注册 MCP 服务器。AGENT_ID 是每台机器的名称——每台机器上选择一个不同的名称;令牌在所有地方都相同。

claude mcp add tincan --env AGENT_ID=laptop --env BROKER_URL=https://<current>.trycloudflare.com --env BROKER_TOKEN=<shared-token> -- node ~/tincan/mcp/server.mjs

使用 broker_health 确认,然后使用 list_agents——每个进行过调用的智能体都会显示在那里。

在本地运行

要在你自己的机器上而不是远程机器上运行代理:

npm install && npm test
npm run broker
npm run tunnel

npm run tunnel 打印一个公共 URL 并将其保存到 .tunnel-url。本地代理启动时没有令牌,除非你自己设置了 BROKER_TOKEN。

Related MCP server: Session Multiplayer

运行监视器

每个智能体应定期轮询 check_inbox,以便注意到对方发送的内容。在 Claude Code 中,使用以下命令启动会话:

/loop 30s call check_inbox and handle anything it returns

一次 check_inbox 调用完成三项工作:返回新消息、显示等待决策的传输提议、以及完成此智能体发送且已被回复的提议。当没有事情要做时,它返回 quiet: true。

工具

工具

作用

check_inbox

监视器滴答。新消息、等待决策的提议、已发送提议的更新。

send_message

发送给另一个智能体。根据大小自动选择内联或提议。

ack_message

已读回执。在调用之前,消息会在每次滴答时重新投递。

respond_offer

接受或拒绝传入的大负载传输。

fetch_payload

检索大消息的负载——如果较小且为文本则内联,否则保存到磁盘。

message_status

你发送的消息的状态:queued → delivered → read。

list_threads / read_thread

对话历史。

list_agents

代理见过的智能体及其时间。

broker_health

可达性、智能体 ID、认证模式。

消息如何移动

发送、投递、读取——发送者可以监视的回执

小于 64KB——send_message 发布消息,代理将其追加到线程日志中,并在收件人的收件箱文件夹中放入一个条目。收件人的下一次 check_inbox 将其状态翻转为 delivered 并返回;ack_message 将其翻转为 read。发送者使用 message_status 观察所有三种状态。

提议握手——在收件人接受之前,没有任何内容传输

大于 64KB——由大小决定,而非智能体。send_message 将字节保存在发送者自己的磁盘上(~/.agent-tunnel/outbox/<agent>/),并发布一个仅包含主题、大小和内容类型的提议。收件人在 offers_awaiting_response 下看到它,并调用 respond_offer。接受后,负载在发送者的下一次 check_inbox 滴答期间上传——无需后续调用,无需智能体记账。拒绝后,本地副本被删除,且没有任何内容传输。

投递至少一次:未确认的消息会在每次滴答时重新出现,因此在获取和确认之间发生崩溃会重新投递而不是丢失。

消息和提议状态机,均为单向前进

图表由 docs/images/src/ 中的 SVG 源生成——编辑这些源文件并使用 rsvg-convert -w 2400 -h 1350 in.svg -o out.png 重新渲染。

文件夹

代理知道的所有内容都位于 data/ 下,可以使用 cat 和 ls 读取:

data/
  messages/<message_id>.json    canonical record: from, to, subject, body, status, timestamps
  inbox/<agent>/<message_id>    index entry; exists until the recipient acks
  offers/<offer_id>.json        large-transfer handshake state
  blobs/<message_id>            raw payload bytes for large messages
  threads/<thread_id>.jsonl     append-only history, one JSON event per line
  agents/<agent_id>.json        first seen / last seen

线程是对话历史记录,永远不会被截断:每次发送、投递、已读回执、提议、接受和传输都是一行,按顺序排列。

tail -f data/threads/*.jsonl

安全态势

未设置 BROKER_TOKEN 启动的代理是开放的——任何知道隧道 URL 的人都可以读取和写入你的智能体的消息。这对于在每次重启都会更换 URL 的本地测试一分钟来说没问题,但对于任何持续运行的情况则不行。设置令牌:

BROKER_TOKEN=$(openssl rand -hex 32) npm run broker

然后每个路由都需要 Authorization: Bearer <token>,并且每个智能体都需要在其环境中使用相同的值。/v1/health 故意保持开放,以便可以对隧道进行冒烟测试。deploy/install.sh 始终写入一个令牌,因此部署的代理默认是关闭的。

一个共享令牌意味着智能体通过 AGENT_ID 区分,而不是通过凭据:任何持有令牌的人都可以声称任何智能体名称。在你自己的机器之间,这是一个合理的权衡;如果令牌传播范围更广,首先需要更改的就是这个——每个智能体使用单独的令牌是对同一中间件的一个小改动。

代理绑定 127.0.0.1,从不直接暴露;cloudflared 是唯一的入口。智能体和线程 ID 在使用前会通过 ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ 进行验证,因此精心构造的 ID 无法逃逸数据文件夹。

将代理部署到服务器

deploy/install.sh 可以配置任何 Debian/Ubuntu 主机:它安装 Node 22 和 cloudflared,创建一个 agenttunnel 系统用户,写入 /etc/agent-tunnel.env(模式 640),并安装两个加固的 systemd 单元,以便代理和隧道在重启后都能恢复。代码位于 /opt/agent-tunnel,消息文件夹位于 /var/lib/agent-tunnel。

代理仅绑定 127.0.0.1。cloudflared 向外拨号到 Cloudflare,因此不需要入站防火墙规则,主机不暴露任何公共端口——这也意味着它可以在没有外部 IP 的虚拟机上工作。

对于通过 IAP 访问的 GCP 虚拟机,只需指定一次目标:

cp deploy/target.env.example deploy/target.env

填写项目、区域和实例——该文件被 gitignore,因此主机名不会出现在仓库中。然后部署或升级:

./deploy/push.sh

它上传 server/ 和 shared/,运行安装程序,并打印公共 URL。重新运行以推送更改;环境文件和消息文件夹保持不变。在任何其他主机上,将代码暂存到 /tmp/agent-tunnel-stage 并直接运行 deploy/install.sh。

共享密钥在首次部署时生成,并保存在 ~/.agent-tunnel/broker-token。每个智能体使用相同的令牌;智能体通过 AGENT_ID 区分,而不是通过凭据。

向正在运行的部署询问其当前地址:

./deploy/url.sh

URL 不是稳定的。 快速隧道在 cloudflared 服务每次重启时(包括主机重启)都会选择一个新的主机名。发生这种情况时,重新读取它并更新每台智能体机器上的 BROKER_URL。要使其永久化,你需要一个命名隧道,这需要一个带有区域的 Cloudflare 账户——请参阅 INSTALL.md。

测试

npm test

涵盖存储(状态转换、至少一次重新投递、路径遍历拒绝、提议状态机)、HTTP 表面(每个路由、错误代码、令牌门控)、端到端的双智能体流程,以及作为真实子进程通过 stdio 驱动的 MCP 服务器。

许可证

MIT——请参阅 LICENSE。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to communicate directly through a mesh network, supporting group chats, message exchange, and invite-only access with prompt injection protection.
    29 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI coding agents in different harnesses, projects, or machines to share encrypted peer-to-peer rooms and exchange messages directly, without any central server or account.
    8
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables already-running AI coding agents on the same project to register, discover one another, and exchange durable direct messages so they can share progress and avoid conflicting work.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI coding agents to communicate directly with each other across machines, with support for rooms, pairing, and encrypted messaging.
    1 npm
    7
    MIT