npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cross-agent-teams-mcp

v0.6.1

Published

MCP daemon for cross-agent collaboration

Readme

cross-agent-teams-mcp

English README

一个本地 MCP daemon, 让同一台机器上的多个 AI 编码 agent (Claude Code, Codex, opencode) 互相通信. agent 注册到 daemon, 互发 1-to-1 消息, 在 team 或 role 内广播, 互相唤醒 — 全部通过一个本地 daemon 完成, 不依赖任何外部服务.

为什么不直接用 Claude Code 自带的 agent teams?

Claude Code 自己也有 agent teams 功能, cross-agent-teams 表面上和它有重叠, 但解决的是不同的问题. 三个具体的理由:

跨 agent 支持. Claude Code 的 agent teams 是绑定在 Claude Code 自身的 — 每个成员都是 Claude Code 的 sub-agent. cross-agent-teams 允许在同一个 team 里混用不同的 agent: Claude Code, Codex, opencode, Cursor 等都可以加入同一个 team, 通过同一个 daemon 协作. 按场景选最合适的 agent, 而不是被某一个 harness 锁死.

更强的持久性与可控性. 本项目的设计是每个 agent 进程都由你手动启动和停止. 这比"按需隐式拉起"麻烦, 但也更可控, 更持久 — agent 自己保留长期上下文, 记忆, 会话状态, 不会被编排器隐式重建. 一个专家 agent 可以挂着跑几小时甚至几天, 你一直跟同一个 session 对话.

跨设备 / 跨用户协作. daemon 最近新增了跨物理机组 team 的能力 (见 第 4 节). 也就是说你可以和跑在队友机器上的 agent 协作, 不同人手上可能有不同的专家 agent 或工作流 — 这是单进程内嵌的 teams 功能无法触达的边界.

快速开始

Claude Code

# 1. 启动 daemon (跑一次, 保持运行)
npx -y cross-agent-teams-mcp@latest daemon --port 9100 &

# 2. 在你的项目下安装 MCP 配置
npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code

# 3. 带上 channel loader 启动 Claude Code (需要手动确认权限)
claude --dangerously-load-development-channels server:cross-agent-teams-channel

其它 agent (Codex, opencode, ...)

# 1. 启动 daemon (跑一次, 保持运行)
npx -y cross-agent-teams-mcp@latest daemon --port 9100 &

# 2. 在你的项目下安装 MCP 配置 (交互式选择对应 agent)
npx mcpsmgr add jtianling/cross-agent-teams-mcp

# 3. 按平时的方式启动对应 coding agent

注意: 只有 Claude Code 默认就能收到 push 唤醒. Codex 需要 --remote + launcher 配置 (见下面 section 2) 才能被 poke; 没配的话只有邮箱, 不会自动醒. opencode / cursor 等其它 agent 只有跑在 tmux pane 里才能被 poke. 没接通 push 唤醒的情况下, 让 agent 自己手动收信即可 (跟它说"查一下我的 xats inbox").

之后用平时跟 agent 对话的语言就能用了:

# Agent A 里:
Register me to xats as backend on team default.

# Agent B 里:
Register me to xats as frontend on team default.
Send backend a message: the API has changed.

就这些. 下面是细节 — daemon 参数, 手动 MCP 配置, codex --remote 设置, 更多使用方式.

1. 启动 daemon

在本机起一次, 让进程保持运行 (单独终端 / tmux / screen / launchd 都行):

npx -y cross-agent-teams-mcp@latest daemon --port 9100

daemon 默认监听 127.0.0.1:9100. MCP endpoint: http://127.0.0.1:9100/mcp, 健康检查: http://127.0.0.1:9100/health.

常用参数:

  • --port <n> (默认 9100)
  • --host <addr> (默认 127.0.0.1)
  • --device <label> (默认从 hostname 派生)
  • --token <t> (Bearer 鉴权)
  • --db <path> (默认 ~/.cross-agent-teams-mcp/data.db)
  • --pid-file <path> (默认 ~/.cross-agent-teams-mcp/daemon.pid)

多主机 / 多设备 (LAN, tailscale 等) 场景请看下面的 第 4 节.

2. 在 agent 端配置 MCP client

推荐: mcpsmgr (快速开始里已经演示)

mcpsmgr 读取本仓库的 mcpsmgr.json, 一次性把对应 agent 需要的 MCP 条目写进配置 — 包括 Claude Code 的 stdio channel proxy 条目, Codex 的 experimental_use_rmcp_client 开关和 streamable-http MCP 条目.

覆盖 daemon 端口:

npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code --port 9300

手动配置

如果不想用 mcpsmgr (私有 fork / 自定义 token / 自定义 stdio args / 或者就是想手写), 各 agent 的原始配置如下.

Claude Code (两个条目都需要 — HTTP 用于工具, stdio 用于 channel 唤醒)

.mcp.json (或 ~/.claude.json):

{
  "mcpServers": {
    "cross-agent-teams": {
      "type": "http",
      "url": "http://127.0.0.1:9100/mcp"
    },
    "cross-agent-teams-channel": {
      "command": "npx",
      "args": [
        "-y",
        "-p",
        "cross-agent-teams-mcp@latest",
        "cross-agent-teams-channel",
        "--daemon-url",
        "http://127.0.0.1:9100/mcp"
      ]
    }
  }
}

启动 Claude Code 时加上 channel loader, 让它订阅 channel proxy 推过来的唤醒通知:

claude --dangerously-load-development-channels server:cross-agent-teams-channel

server:<name> 后缀 必须 等于 .mcp.json 里的 MCP server key (上例中是 cross-agent-teams-channel). 如果 daemon 启动带了 --token <t>, 在 HTTP 条目里加 "headers": { "Authorization": "Bearer <t>" }, 并在 channel proxy args 里加 --token <t>.

Codex CLI

Codex 通过 Streamable HTTP 跟 daemon 通信. 唤醒走 Codex 自己的 app-server WebSocket, 不经 channel proxy.

最小配置 (只能收邮箱, 没有 push 唤醒)

~/.codex/config.toml:

experimental_use_rmcp_client = true

[mcp_servers.cross-agent-teams-mcp]
type = "streamable-http"
url = "http://127.0.0.1:9100/mcp"

experimental_use_rmcp_client = true 必须放在顶级, 缺这条 streamable-http MCP 加载不了.

daemon 带了 --token <t> 时: 在启动 codex 的 shell 里 export XATS_TOKEN=<t>, 然后在 [mcp_servers.cross-agent-teams-mcp] 块里加 bearer_token_env_var = "XATS_TOKEN". (Codex 0.130+ 会静默忽略老写法 [mcp_servers.X.headers] — 它真正认的 key 是 http_headersbearer_token_env_var, 后者更推荐, token 不会落进可能被签入仓库的配置里.)

这种最小配置下 send_message 给这个 codex 会写邮箱, 但需要手动调 get_inbox 拉读, 没有跨会话 push 唤醒.

让别人能唤醒你 (codex-appserver poke)

要让别的 agent 能主动唤醒这个 codex thread (而不只是发邮件), 需要 codex-appserver delivery. 这里有个不直观的坑要写清楚:

codex --remote 模式下, MCP server 是 app-server 加载的, 不是 TUI 加载的. 上面那段 MCP 配置必须放在 app-server 启动时读到的 CODEX_HOME 里 — 一般就是全局 ~/.codex/config.toml. 仅在 TUI 这边设 CODEX_HOME--remote 模式下对 MCP 不起作用.

启动顺序:

# 1) 在某个长跑终端起 codex app-server (它的 CODEX_HOME 决定 MCP set)
codex app-server --listen ws://127.0.0.1:8799

# 2) 在另一个终端启动 codex TUI, 连同一个 app-server
codex --remote ws://127.0.0.1:8799

如果第 1 步的 app-server 的 CODEX_HOME 里没配 cross-agent-teams-mcp, --remote 进去的 codex agent 根本看不到 MCP 工具, register_agent 调都调不到.

推荐: launcher 函数 (tmux pane 自动绑定)

为了让 daemon 把 wake-hint 直接 inject 到 codex thread (而不是只 paste 到 tmux pane), daemon 需要知道 codex 进程在哪个 tmux pane. launcher 通过 pre-register-codex-pane CLI 在 exec codex 之前先把 pane 占住. 把下面的函数加到 ~/.zshrc:

free-xats-codex() {
    local xats_agent_id codex_home search_dir
    xats_agent_id="$(uuidgen)"
    search_dir="$PWD"
    while [[ "$search_dir" != "/" ]]; do
        if [[ -f "$search_dir/.codex/config.toml" ]]; then
            codex_home="$search_dir/.codex"
            break
        fi
        search_dir="${search_dir:h}"
    done

    if [[ -n "$TMUX_PANE" ]]; then
        npx -y cross-agent-teams-mcp pre-register-codex-pane \
            --pane "$TMUX_PANE" \
            --agent-id "$xats_agent_id" \
            >/dev/null 2>&1 \
            || echo "[xats] pre-register failed (continuing without pane claim)" >&2
    fi

    if [[ -n "$codex_home" ]]; then
        CODEX_HOME="$codex_home" exec codex \
            --remote ws://127.0.0.1:8799 \
            -C "$PWD" \
            -c xats.agent_id="\"$xats_agent_id\"" "$@"
    else
        exec codex \
            --remote ws://127.0.0.1:8799 \
            -C "$PWD" \
            -c xats.agent_id="\"$xats_agent_id\"" "$@"
    fi
}

行为:

  • tmux 内 ($TMUX_PANE 非空): 先发一条 pre-register (pane_id + UUID + 120s TTL) 给 daemon. codex agent 之后调 register_agent({agent_type: "codex", thread_id: $CODEX_THREAD_ID, ...}) 时, daemon 会用 pending pre-reg + 匹配 codex 进程 argv 自动绑 tmux_pane_id.
  • --remote ws://127.0.0.1:8799 让 codex 连步骤 (1) 起好的 app-server.
  • -c xats.agent_id="\"$uuid\"" 把 UUID 暴露在 codex argv 里, daemon 用它反向校验 pane.

详细配置 (auth header, 底层 register_agent 用法): docs/configs/codex-cli.md.

其它编码 agent (opencode, cursor, ...)

非 Claude Code 也非 Codex 的工具 — opencode, cursor, 编辑器扩展, 自己的 harness — 直接通过 Streamable HTTP 连 daemon, 注册时用 agent_type="custom" (agent 自己会判断). 这些 agent 没有专用的唤醒通道; 跨 agent poke 通过把文本注入到 agent 所在的 tmux pane 实现, 所以把 agent 跑在 tmux 窗口里, 注册时 daemon 会自动解析 pid → tty → pane.

各工具的具体配置片段在 docs/configs/opencode.md (其它在 docs/configs/).

3. 从 agent 里使用

agent 连上 daemon 后, 你不需要去记工具名字. 直接用平时跟 agent 对话的语言告诉它你想干嘛, agent 会自己挑工具 — 下面列的是 你说的话, 不是底层 API.

注意: 这些都要在 agent 会话内说. 不要用 curl 或其它外部 HTTP client 去注册或发消息 — 那会开一个不同的 MCP session, 消息送不到你这里.

注册当前会话

agent 第一次连上 xats 时不会自动注册, 要等你开口. 直接说:

Register me to xats as alice.

或者指定 team:

Register me to xats as alice on team backend.

不传 team 的话, agent 会用当前工作目录的 basename 作为默认 team — 一般情况下你不用操心.

跟其它 agent 对话

按名字, 按 team, 按 role 都行:

Send a message to bob: how is the migration going?

Tell my team I'm starting the deploy.

Send the frontend role a heads-up that the API will change.

What's in my inbox?

agent 会自动挑对应工具 (send_message, broadcast, broadcast_to_role, get_inbox). 发消息的同时会自动唤醒收件人, 不用单独再 poke.

看看还有谁在线

Who else is registered on xats?

List agents on team backend.

4. 跨主机 / 跨设备协作

大部分用户只用单机就够了, loopback 场景下 device 这个轴是透明的, 本节可以完全跳过. 只有当你想让多台物理机器 (LAN, tailscale 等) 共享一个 daemon 时, 才需要往下看.

跨设备需要三处配套修改 — daemon bind, 远端 .mcp.json, agent 注册. agent 身份按 (device, team, name) 命名空间区分: 裸的 send_message({to_agent_name:"creator"}) 解析到调用者自己的 device, 用 creator:host-b 可以指到另一个 device 上同 team 的 agent.

1. Daemon 侧: bind 到非 loopback

停掉旧 daemon, 用非 loopback --host--token 重启. --host 非 loopback 时 --token 必填, 否则 daemon 拒绝启动 (token_required_for_non_loopback_bind). --device 可选, 不传则从 daemon 主机的 hostname 派生 (小写 + 非 [a-z0-9_-] 替换为 -):

npx -y cross-agent-teams-mcp@latest daemon \
  --host 0.0.0.0 \
  --port 9100 \
  --token "$XATS_TOKEN" \
  --device host-a

想限定监听接口, 把 0.0.0.0 换成具体 LAN IP (例如 10.0.0.10) 或者 tailscale CGNAT IP (100.x.x.x) 都行. macOS 第一次绑非 loopback 端口会弹"允许 node 接受网络连接", 选允许.

2. 远端机器侧: 改 .mcp.json

每台远端同事的 Claude Code 相对默认 loopback 配置都要改两处 — HTTP 入口加 Authorization: Bearer … 头, channel proxy 加 --token--device.

--device 对跨主机场景是关键配置. daemon 端会拒掉任何不带 device 的远程 register_agent (返回 device_required_from_remote), 因此 channel proxy 缺 --device 时会陷入 register/fail/respawn 死循环, 永远叫不醒目标 agent — auto-poke 会静默退化成 no_pane. v0.5.18 起 proxy 在 daemon 非 loopback 且未传 --device 时会用 os.hostname() 自动派生一个 label 并 stderr 打 notice, 但派生值仍可能与 daemon 本机标签撞 (触发 device_spoofing_local_label_from_remote), 跨主机部署务必为每台机器在配置里显式钉死 --device:

{
  "mcpServers": {
    "cross-agent-teams": {
      "type": "http",
      "url": "http://10.0.0.10:9100/mcp",
      "headers": {
        "Authorization": "Bearer xats"
      }
    },
    "cross-agent-teams-channel": {
      "command": "npx",
      "args": [
        "-y", "-p", "cross-agent-teams-mcp@latest",
        "cross-agent-teams-channel",
        "--daemon-url", "http://10.0.0.10:9100/mcp",
        "--token", "xats",
        "--device", "host-b"
      ]
    }
  }
}

如果远端用的是 Codex CLI, 改 ~/.codex/config.toml:

[mcp_servers.cross-agent-teams-mcp]
url = "http://10.0.0.10:9100/mcp"
bearer_token_env_var = "XATS_TOKEN"

启动前 export XATS_TOKEN=xats.

daemon 所在机器 (host-a 这台) 的 .mcp.json 同样需要加 headers.Authorization — daemon 一旦设了 --token, 所有 /mcp 请求 (包括 loopback) 都要带 token, 没例外.

3. Agent 注册

重启远端的 Claude Code (或 codex), channel proxy 用新的 --device 启动后, startup hint 会把 device 直接嵌进引导文案, 用户回复时一并带上即可:

Register me to xats as alice, device host-b.

如果远端 register_agent 不传 device, daemon 回 device_required_from_remote 直接拒. device 进入身份键 (device, team, name), 所以两台机器都可以有 team=default 下的 creator, 不会撞名.

4. 跨设备寻址

注册完成后, 用 name:device 后缀寻址同 team 不同 device 的 agent:

Send creator on host-a a message: build is green.

这条解析成 creator:host-a, 路由到 (device=host-a, team=…, name=creator) 这一行. 裸名字 creator 始终解析到 caller 自己 device.

要点:

  • list_agents 每条返回都有 device 字段, 用它看清 team 里哪些 device 在贡献 agent, 再拼对的 name:device.
  • get_inbox 每条消息都带 from_namefrom_device. 回复时如果 from_device !== 自己 device, 用 from_name:from_device; 同 device 用裸名即可. send_message_by_id({to_agent_id: from_agent_id, ...}) 是 device 无关的安全兜底.
  • 安全提醒: bearer token 在能连到 daemon 的所有人之间共享, 把 LAN 暴露当作可信团队边界处理 — 本模式没有 per-agent 鉴权, 没有 device 白名单, 也没有 TLS.
  • 升级说明: 引入 device 轴之后首次启动会自动迁移存储 schema, 把身份从 (team, name) 改为 (device, team, name), 并用 daemon 本机的 --device 标签回填旧数据. 如果已经注册了多个 device 上相同 (team, name) 的 agent 再回滚, 可能违反旧版本的唯一性假设.

5. 跨设备场景下 Codex 特有的坑

--token + Codex --remote 模式下会暴露三个本地单设备 setup 看不到的问题:

  • app-server 的 env 在启动时固化. codex app-server --listen ... 继承启动它那个 shell 的环境. 你在另一个 shell export XATS_TOKEN=… 之后, 已经在跑的 app-server 看不到 —— codex MCP 握手时报 Deserialize error: data did not match any variant of untagged enum JsonRpcMessage (codex 把 daemon 返回的 401 body 当 JSON-RPC 帧解析失败). 解决: 在已经 exportXATS_TOKEN 的 shell 里重启 app-server.

  • --remote 会劫持工作目录. codex --remote … 下 session 的 cwd 是 app-server 进程的 cwd, 不是 TUI 的, 所以 launcher 无论在哪个目录跑都会落回 app-server 启动时的目录. 在 codex 命令上加 -C "$PWD" 覆盖 (上面 launcher 已经带了).

  • 项目级 .codex/config.toml 会覆盖全局. 陈旧的 per-project 配置块 —— 尤其在 iCloud / Dropbox 之类跨机同步的目录里 —— 会盖掉你的全局鉴权设置, 报错形如某个 codex mcp list (只反映全局) 里看不到的 server 名启动失败. 审计: find ~ -path '*/.codex/config.toml' -print, 删掉或更新陈旧条目.

更多