cross-agent-teams-mcp 0.5.8 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -59
- package/README.zh-CN.md +30 -52
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/mcp/tools.ts +1 -0
package/README.md
CHANGED
|
@@ -65,32 +65,7 @@ Common flags:
|
|
|
65
65
|
- `--db <path>` (default `~/.cross-agent-teams-mcp/data.db`)
|
|
66
66
|
- `--pid-file <path>` (default `~/.cross-agent-teams-mcp/daemon.pid`)
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
To let agents on another trusted machine use this daemon, bind the daemon to a LAN address and set a shared bearer token:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
npx -y cross-agent-teams-mcp@latest daemon \
|
|
74
|
-
--host 10.0.0.10 \
|
|
75
|
-
--port 9100 \
|
|
76
|
-
--token "$XATS_TOKEN" \
|
|
77
|
-
--device host-a
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Then configure the peer host's Claude Code channel proxy to connect back to that daemon:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
npx -y -p cross-agent-teams-mcp@latest cross-agent-teams-channel \
|
|
84
|
-
--daemon-url http://10.0.0.10:9100/mcp \
|
|
85
|
-
--token "$XATS_TOKEN" \
|
|
86
|
-
--device host-b
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Agents are namespaced by `(device, team, name)`. A bare `send_message({to_agent_name:"creator"})` resolves on the caller's own device; use `creator:host-b` to address a same-team agent on another device. `list_agents` shows the `device` field so you can compose those addresses.
|
|
90
|
-
|
|
91
|
-
Security notes: non-loopback `--host` requires `--token`, and the token is shared by everyone who can use that daemon. Treat LAN exposure as trusted-team only; there is no per-agent authorization, device whitelist, or TLS in this mode.
|
|
92
|
-
|
|
93
|
-
Upgrade note: the first startup after this version auto-migrates the storage schema from `(team, name)` identity to `(device, team, name)` identity and backfills existing rows with the daemon's local `--device` label. Rolling back after registering multiple devices with the same `(team, name)` can violate the old uniqueness assumption.
|
|
68
|
+
For multi-host / multi-device setups (LAN, tailscale, etc.), see [section 4](#4-cross-host--cross-device-collaboration) below.
|
|
94
69
|
|
|
95
70
|
## 2. Configure your agent's MCP client
|
|
96
71
|
|
|
@@ -251,13 +226,35 @@ Or with an explicit team:
|
|
|
251
226
|
|
|
252
227
|
If you don't give a team, the agent uses your current working directory's basename — so you typically don't need to think about it.
|
|
253
228
|
|
|
254
|
-
###
|
|
229
|
+
### Talk to other agents
|
|
230
|
+
|
|
231
|
+
Address by name, by team, or by role:
|
|
255
232
|
|
|
256
|
-
|
|
233
|
+
> Send a message to bob: how is the migration going?
|
|
234
|
+
>
|
|
235
|
+
> Tell my team I'm starting the deploy.
|
|
236
|
+
>
|
|
237
|
+
> Send the frontend role a heads-up that the API will change.
|
|
238
|
+
>
|
|
239
|
+
> What's in my inbox?
|
|
257
240
|
|
|
258
|
-
|
|
241
|
+
The agent picks the right tool (`send_message`, `broadcast`, `broadcast_to_role`, `get_inbox`). Outgoing messages also wake the recipient automatically — you don't need a separate poke.
|
|
259
242
|
|
|
260
|
-
|
|
243
|
+
### See who else is around
|
|
244
|
+
|
|
245
|
+
> Who else is registered on xats?
|
|
246
|
+
>
|
|
247
|
+
> List agents on team backend.
|
|
248
|
+
|
|
249
|
+
## 4. Cross-host / cross-device collaboration
|
|
250
|
+
|
|
251
|
+
Most users only need the single-host setup above; the `device` axis is invisible in loopback-only setups and you can skip this entire section. Read on only if you want agents on multiple physical machines (LAN, tailscale, etc.) to share one daemon.
|
|
252
|
+
|
|
253
|
+
The setup needs three coordinated changes — **daemon bind**, **peer `.mcp.json`**, and **agent registration**. Agents are namespaced by `(device, team, name)`: a bare `send_message({to_agent_name:"creator"})` resolves on the caller's own device, while `creator:host-b` addresses a same-team agent on another device.
|
|
254
|
+
|
|
255
|
+
### 1. Daemon-side: bind beyond loopback
|
|
256
|
+
|
|
257
|
+
Stop the daemon and restart with a non-loopback `--host` and a `--token`. The token is mandatory whenever `--host` is non-loopback — the daemon refuses to start otherwise (`token_required_for_non_loopback_bind`). Optionally set `--device` for the daemon-host label (defaults to `os.hostname()` lowercased with `[^a-z0-9_-]` replaced by `-`):
|
|
261
258
|
|
|
262
259
|
```bash
|
|
263
260
|
npx -y cross-agent-teams-mcp@latest daemon \
|
|
@@ -267,9 +264,9 @@ npx -y cross-agent-teams-mcp@latest daemon \
|
|
|
267
264
|
--device host-a
|
|
268
265
|
```
|
|
269
266
|
|
|
270
|
-
Use a specific LAN IP (e.g. `10.0.0.10`) or a tailscale CGNAT IP (`100.x.x.x`) instead of `0.0.0.0` if you want to restrict the listener.
|
|
267
|
+
Use a specific LAN IP (e.g. `10.0.0.10`) or a tailscale CGNAT IP (`100.x.x.x`) instead of `0.0.0.0` if you want to restrict the listener. macOS will prompt to allow node to accept network connections on the first non-loopback bind.
|
|
271
268
|
|
|
272
|
-
|
|
269
|
+
### 2. Peer-side: `.mcp.json` updates
|
|
273
270
|
|
|
274
271
|
Each remote teammate's Claude Code needs **two** changes from the default loopback config: the HTTP entry must carry an `Authorization: Bearer …` header, and the channel proxy must pass `--token` AND `--device`:
|
|
275
272
|
|
|
@@ -309,47 +306,28 @@ bearer_token_env_var = "XATS_TOKEN"
|
|
|
309
306
|
|
|
310
307
|
The **daemon-side** `.mcp.json` (the machine running the daemon) needs the same `headers.Authorization` because the daemon now requires the token on every request, even loopback ones — once `--token` is set, no path through `/mcp` is unauthenticated.
|
|
311
308
|
|
|
312
|
-
|
|
309
|
+
### 3. Agent registration
|
|
313
310
|
|
|
314
|
-
Restart Claude Code (or codex) on the peer machine so the channel proxy spawns with the new `--device` argument.
|
|
311
|
+
Restart Claude Code (or codex) on the peer machine so the channel proxy spawns with the new `--device` argument. The proxy's startup hint then embeds the device verbatim, and the user's reply contains it too:
|
|
315
312
|
|
|
316
313
|
> Register me to xats as alice, device host-b.
|
|
317
314
|
|
|
318
|
-
If a remote `register_agent` call omits `device`, the daemon rejects with `device_required_from_remote` — the agent must self-declare.
|
|
315
|
+
If a remote `register_agent` call omits `device`, the daemon rejects with `device_required_from_remote` — the agent must self-declare. `device` becomes part of the identity tuple `(device, team, name)`, so two physical machines can each host a `creator` in `team=default` without collision.
|
|
319
316
|
|
|
320
|
-
|
|
317
|
+
### 4. Addressing across devices
|
|
321
318
|
|
|
322
319
|
Once everyone is registered, use the `name:device` suffix to address a same-team agent on another device:
|
|
323
320
|
|
|
324
321
|
> Send creator on host-a a message: build is green.
|
|
325
322
|
|
|
326
|
-
This resolves to `creator:host-a` and routes to that exact `(device=host-a, team=…, name=creator)` row.
|
|
323
|
+
This resolves to `creator:host-a` and routes to that exact `(device=host-a, team=…, name=creator)` row. A bare `creator` always resolves on the caller's own device.
|
|
327
324
|
|
|
328
325
|
Notes:
|
|
329
326
|
|
|
330
327
|
- `list_agents` returns a `device` field on every entry — use it to see which devices contribute to your team and to compose the right `name:device` target.
|
|
331
|
-
- `get_inbox` returns `from_name` and `from_device` on every message.
|
|
332
|
-
- Security caveat: the bearer token is shared across everyone who can reach the daemon.
|
|
333
|
-
|
|
334
|
-
### Talk to other agents
|
|
335
|
-
|
|
336
|
-
Address by name, by team, or by role:
|
|
337
|
-
|
|
338
|
-
> Send a message to bob: how is the migration going?
|
|
339
|
-
>
|
|
340
|
-
> Tell my team I'm starting the deploy.
|
|
341
|
-
>
|
|
342
|
-
> Send the frontend role a heads-up that the API will change.
|
|
343
|
-
>
|
|
344
|
-
> What's in my inbox?
|
|
345
|
-
|
|
346
|
-
The agent picks the right tool (`send_message`, `broadcast`, `broadcast_to_role`, `get_inbox`). Outgoing messages also wake the recipient automatically — you don't need a separate poke.
|
|
347
|
-
|
|
348
|
-
### See who else is around
|
|
349
|
-
|
|
350
|
-
> Who else is registered on xats?
|
|
351
|
-
>
|
|
352
|
-
> List agents on team backend.
|
|
328
|
+
- `get_inbox` returns `from_name` and `from_device` on every message. When replying via `send_message`, if `from_device !== <your device>` use `from_name:from_device`; otherwise the bare name is correct. `send_message_by_id({to_agent_id: from_agent_id, ...})` is the device-agnostic safe fallback.
|
|
329
|
+
- Security caveat: the bearer token is shared across everyone who can reach the daemon. Treat LAN exposure as a trusted-team boundary; there is no per-agent auth, device whitelist, or TLS in this mode.
|
|
330
|
+
- Upgrade note: the first startup after introducing the `device` axis auto-migrates the storage schema from `(team, name)` identity to `(device, team, name)` identity and backfills existing rows with the daemon's local `--device` label. Rolling back after registering multiple devices with the same `(team, name)` can violate the old uniqueness assumption.
|
|
353
331
|
|
|
354
332
|
## More
|
|
355
333
|
|
package/README.zh-CN.md
CHANGED
|
@@ -65,32 +65,7 @@ daemon 默认监听 `127.0.0.1:9100`. MCP endpoint: `http://127.0.0.1:9100/mcp`
|
|
|
65
65
|
- `--db <path>` (默认 `~/.cross-agent-teams-mcp/data.db`)
|
|
66
66
|
- `--pid-file <path>` (默认 `~/.cross-agent-teams-mcp/daemon.pid`)
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
要让可信局域网里另一台机器上的 agent 使用这个 daemon, 把 daemon 绑定到 LAN 地址并设置共享 bearer token:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
npx -y cross-agent-teams-mcp@latest daemon \
|
|
74
|
-
--host 10.0.0.10 \
|
|
75
|
-
--port 9100 \
|
|
76
|
-
--token "$XATS_TOKEN" \
|
|
77
|
-
--device host-a
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
然后在对端机器上让 Claude Code channel proxy 连回这个 daemon:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
npx -y -p cross-agent-teams-mcp@latest cross-agent-teams-channel \
|
|
84
|
-
--daemon-url http://10.0.0.10:9100/mcp \
|
|
85
|
-
--token "$XATS_TOKEN" \
|
|
86
|
-
--device host-b
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
agent 身份现在按 `(device, team, name)` 命名空间区分. 裸的 `send_message({to_agent_name:"creator"})` 会解析到调用者自己的 device; 要发给另一个 device 上同 team 的 agent, 用 `creator:host-b`. `list_agents` 会显示 `device` 字段, 方便拼出这个地址.
|
|
90
|
-
|
|
91
|
-
安全说明: 非 loopback 的 `--host` 必须带 `--token`, 并且这个 token 会被所有能使用该 daemon 的人共享. LAN 暴露只适合可信团队环境; 当前模式没有 per-agent 鉴权, device 白名单或 TLS.
|
|
92
|
-
|
|
93
|
-
升级说明: 升级到这个版本后首次启动会自动迁移存储 schema, 把身份从 `(team, name)` 改为 `(device, team, name)`, 并用 daemon 本机的 `--device` 标签回填旧数据. 如果已经注册了多个 device 上相同 `(team, name)` 的 agent 再回滚, 可能违反旧版本的唯一性假设.
|
|
68
|
+
多主机 / 多设备 (LAN, tailscale 等) 场景请看下面的 [第 4 节](#4-跨主机--跨设备协作).
|
|
94
69
|
|
|
95
70
|
## 2. 在 agent 端配置 MCP client
|
|
96
71
|
|
|
@@ -251,11 +226,33 @@ agent 第一次连上 xats 时不会自动注册, 要等你开口. 直接说:
|
|
|
251
226
|
|
|
252
227
|
不传 team 的话, agent 会用当前工作目录的 basename 作为默认 team — 一般情况下你不用操心.
|
|
253
228
|
|
|
254
|
-
###
|
|
229
|
+
### 跟其它 agent 对话
|
|
230
|
+
|
|
231
|
+
按名字, 按 team, 按 role 都行:
|
|
232
|
+
|
|
233
|
+
> Send a message to bob: how is the migration going?
|
|
234
|
+
>
|
|
235
|
+
> Tell my team I'm starting the deploy.
|
|
236
|
+
>
|
|
237
|
+
> Send the frontend role a heads-up that the API will change.
|
|
238
|
+
>
|
|
239
|
+
> What's in my inbox?
|
|
255
240
|
|
|
256
|
-
|
|
241
|
+
agent 会自动挑对应工具 (`send_message`, `broadcast`, `broadcast_to_role`, `get_inbox`). 发消息的同时会自动唤醒收件人, 不用单独再 poke.
|
|
257
242
|
|
|
258
|
-
|
|
243
|
+
### 看看还有谁在线
|
|
244
|
+
|
|
245
|
+
> Who else is registered on xats?
|
|
246
|
+
>
|
|
247
|
+
> List agents on team backend.
|
|
248
|
+
|
|
249
|
+
## 4. 跨主机 / 跨设备协作
|
|
250
|
+
|
|
251
|
+
大部分用户只用单机就够了, loopback 场景下 `device` 这个轴是透明的, 本节可以完全跳过. 只有当你想让多台物理机器 (LAN, tailscale 等) 共享一个 daemon 时, 才需要往下看.
|
|
252
|
+
|
|
253
|
+
跨设备需要三处配套修改 — **daemon bind**, **远端 `.mcp.json`**, **agent 注册**. agent 身份按 `(device, team, name)` 命名空间区分: 裸的 `send_message({to_agent_name:"creator"})` 解析到调用者自己的 device, 用 `creator:host-b` 可以指到另一个 device 上同 team 的 agent.
|
|
254
|
+
|
|
255
|
+
### 1. Daemon 侧: bind 到非 loopback
|
|
259
256
|
|
|
260
257
|
停掉旧 daemon, 用非 loopback `--host` 和 `--token` 重启. `--host` 非 loopback 时 `--token` **必填**, 否则 daemon 拒绝启动 (`token_required_for_non_loopback_bind`). `--device` 可选, 不传则从 daemon 主机的 hostname 派生 (小写 + 非 `[a-z0-9_-]` 替换为 `-`):
|
|
261
258
|
|
|
@@ -269,7 +266,7 @@ npx -y cross-agent-teams-mcp@latest daemon \
|
|
|
269
266
|
|
|
270
267
|
想限定监听接口, 把 `0.0.0.0` 换成具体 LAN IP (例如 `10.0.0.10`) 或者 tailscale CGNAT IP (`100.x.x.x`) 都行. macOS 第一次绑非 loopback 端口会弹"允许 node 接受网络连接", 选允许.
|
|
271
268
|
|
|
272
|
-
|
|
269
|
+
### 2. 远端机器侧: 改 `.mcp.json`
|
|
273
270
|
|
|
274
271
|
每台远端同事的 Claude Code 相对默认 loopback 配置都要改两处 — HTTP 入口加 `Authorization: Bearer …` 头, channel proxy 加 `--token` 和 `--device`:
|
|
275
272
|
|
|
@@ -309,7 +306,7 @@ bearer_token_env_var = "XATS_TOKEN"
|
|
|
309
306
|
|
|
310
307
|
**daemon 所在机器** (host-a 这台) 的 `.mcp.json` 同样需要加 `headers.Authorization` — daemon 一旦设了 `--token`, 所有 `/mcp` 请求 (包括 loopback) 都要带 token, 没例外.
|
|
311
308
|
|
|
312
|
-
|
|
309
|
+
### 3. Agent 注册
|
|
313
310
|
|
|
314
311
|
重启远端的 Claude Code (或 codex), channel proxy 用新的 `--device` 启动后, startup hint 会把 device 直接嵌进引导文案, 用户回复时一并带上即可:
|
|
315
312
|
|
|
@@ -317,7 +314,7 @@ bearer_token_env_var = "XATS_TOKEN"
|
|
|
317
314
|
|
|
318
315
|
如果远端 `register_agent` 不传 device, daemon 回 `device_required_from_remote` 直接拒. device 进入身份键 `(device, team, name)`, 所以两台机器都可以有 `team=default` 下的 `creator`, 不会撞名.
|
|
319
316
|
|
|
320
|
-
|
|
317
|
+
### 4. 跨设备寻址
|
|
321
318
|
|
|
322
319
|
注册完成后, 用 `name:device` 后缀寻址同 team 不同 device 的 agent:
|
|
323
320
|
|
|
@@ -330,26 +327,7 @@ bearer_token_env_var = "XATS_TOKEN"
|
|
|
330
327
|
- `list_agents` 每条返回都有 `device` 字段, 用它看清 team 里哪些 device 在贡献 agent, 再拼对的 `name:device`.
|
|
331
328
|
- `get_inbox` 每条消息都带 `from_name` 和 `from_device`. 回复时如果 `from_device !== 自己 device`, 用 `from_name:from_device`; 同 device 用裸名即可. `send_message_by_id({to_agent_id: from_agent_id, ...})` 是 device 无关的安全兜底.
|
|
332
329
|
- 安全提醒: bearer token 在能连到 daemon 的所有人之间共享, 把 LAN 暴露当作可信团队边界处理 — 本模式没有 per-agent 鉴权, 没有 device 白名单, 也没有 TLS.
|
|
333
|
-
|
|
334
|
-
### 跟其它 agent 对话
|
|
335
|
-
|
|
336
|
-
按名字, 按 team, 按 role 都行:
|
|
337
|
-
|
|
338
|
-
> Send a message to bob: how is the migration going?
|
|
339
|
-
>
|
|
340
|
-
> Tell my team I'm starting the deploy.
|
|
341
|
-
>
|
|
342
|
-
> Send the frontend role a heads-up that the API will change.
|
|
343
|
-
>
|
|
344
|
-
> What's in my inbox?
|
|
345
|
-
|
|
346
|
-
agent 会自动挑对应工具 (`send_message`, `broadcast`, `broadcast_to_role`, `get_inbox`). 发消息的同时会自动唤醒收件人, 不用单独再 poke.
|
|
347
|
-
|
|
348
|
-
### 看看还有谁在线
|
|
349
|
-
|
|
350
|
-
> Who else is registered on xats?
|
|
351
|
-
>
|
|
352
|
-
> List agents on team backend.
|
|
330
|
+
- 升级说明: 引入 `device` 轴之后首次启动会自动迁移存储 schema, 把身份从 `(team, name)` 改为 `(device, team, name)`, 并用 daemon 本机的 `--device` 标签回填旧数据. 如果已经注册了多个 device 上相同 `(team, name)` 的 agent 再回滚, 可能违反旧版本的唯一性假设.
|
|
353
331
|
|
|
354
332
|
## 更多
|
|
355
333
|
|
package/dist/cli.js
CHANGED
|
@@ -3748,6 +3748,7 @@ function registerBusinessTools(server, db, getCallerAgentId, fanout, onRegisterS
|
|
|
3748
3748
|
'Requests such as "register to xats" or "register to cross-agent-teams" refer to this MCP service, not to the `team` field; do not set `team` to `xats` or `cross-agent-teams` from those phrases.',
|
|
3749
3749
|
'Do not treat the bare word "register" as a request for this tool unless the current conversation is already about cross-agent-teams registration.',
|
|
3750
3750
|
"When the end user has not explicitly specified `team`, callers should pass `project_dir` as the current working directory so the daemon derives a project-scoped default team from its basename; if omitted, it falls back to `default`.",
|
|
3751
|
+
'REPORTING RULE: on success the response carries the actual `team` the daemon assigned. When summarizing the registration to the user, surface that returned `team` value verbatim; NEVER derive or paraphrase the team from `project_dir`, cwd, or your own pre-call assumption. Failing to read the response masks the daemon\'s `default` fallback (e.g. when `project_dir` was forgotten) and produces misleading "team: X (from cwd basename)" reports that break later cross-team send_message diagnostics.',
|
|
3751
3752
|
'`agent_type` must describe the runtime behind `ui_pid`, not merely the current MCP caller. For example, if `ui_pid` points at an external editor process, pass `agent_type="custom"` with `agent_type_name=<editor>` even when the registration request is issued from a different harness.',
|
|
3752
3753
|
"STRONGLY RECOMMENDED: pass `ui_pid` unless it is truly unobtainable (codex callers excepted, see DETECTION step 1). Without it, automatic runtime binding usually fails to converge and tmux-based cross-agent poke delivery stays off until a separate `bind_runtime_identity(...)` call. From Claude Code, `$PPID` inside a Bash tool call is the `claude` CLI pid. With `ui_pid` the daemon binds via verified pid \u2192 tty \u2192 pane evidence in one shot.",
|
|
3753
3754
|
"After registration, the daemon best-effort attempts runtime binding for recognized local clients so tmux-based poke delivery can come up without a second tool call.",
|