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 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
- ### Cross-host (LAN) collaboration
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
- ### Cross-device communication
229
+ ### Talk to other agents
230
+
231
+ Address by name, by team, or by role:
255
232
 
256
- Cross-device messaging needs three coordinated changes **daemon bind**, **peer `.mcp.json`**, and **agent registration**. Pure single-host users can ignore this entire section; the new `device` axis is invisible in loopback-only setups.
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
- #### 1. Daemon-side: bind beyond loopback
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
- 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 `-`):
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. macOS will prompt to allow node to accept network connections on the first non-loopback bind.
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
- #### 2. Peer-side: `.mcp.json` updates
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
- #### 3. Agent registration
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. The proxy's startup hint then embeds the device verbatim, and the user's reply contains it too:
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. `device` becomes part of the identity tuple `(device, team, name)`, so two physical machines can each host a `creator` in `team=default` without collision.
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
- #### 4. Addressing across devices
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. A bare `creator` always resolves on the caller's own device.
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. 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.
332
- - 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.
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
- ### 跨主机 (LAN) 协作
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
- ### 跨设备 (device) 通信
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
- 跨设备通信需要三处配套修改 **daemon bind**, **远端 `.mcp.json`**, **agent 注册**. 纯单机用户可以完全跳过本节, loopback 场景下 device 这个轴是透明的.
241
+ agent 会自动挑对应工具 (`send_message`, `broadcast`, `broadcast_to_role`, `get_inbox`). 发消息的同时会自动唤醒收件人, 不用单独再 poke.
257
242
 
258
- #### 1. Daemon 侧: bind 到非 loopback
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
- #### 2. 远端机器侧: 改 `.mcp.json`
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
- #### 3. Agent 注册
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
- #### 4. 跨设备寻址
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.",