cross-agent-teams-mcp 0.5.4 → 0.5.5

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
@@ -4,12 +4,47 @@
4
4
 
5
5
  A local MCP daemon that lets multiple AI coding agents (Claude Code, Codex, opencode) running on the same machine talk to each other. Agents register, send 1-to-1 messages, broadcast to a team or role, and wake each other up — all over a single daemon, no external services.
6
6
 
7
- ## What's in the npm package
7
+ ## Quick start
8
8
 
9
- `cross-agent-teams-mcp` ships two bins from the same package:
9
+ ### Claude Code
10
10
 
11
- - **`cross-agent-teams-mcp daemon`** — the long-running HTTP daemon. Stores agents, mailboxes, and the task list in a local SQLite file, exposes its tools at `http://127.0.0.1:9100/mcp`.
12
- - **`cross-agent-teams-channel`** a stdio MCP shim that lets Claude Code receive `notifications/channel_wake` from the daemon (Claude Code's experimental channel capability). Required for Claude Code wake-ups; not needed for Codex (which uses its own app-server transport) or opencode (which falls back to tmux-pane injection).
11
+ ```bash
12
+ # 1. Start the daemon (run once, keep it alive)
13
+ npx -y cross-agent-teams-mcp@latest daemon --port 9100 &
14
+
15
+ # 2. In your project, install the MCP config
16
+ npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code
17
+
18
+ # 3. Start Claude Code with the channel loader (manual permission prompt expected)
19
+ claude --dangerously-load-development-channels server:cross-agent-teams-channel
20
+ ```
21
+
22
+ ### Other agents (Codex, opencode, ...)
23
+
24
+ ```bash
25
+ # 1. Start the daemon (run once, keep it alive)
26
+ npx -y cross-agent-teams-mcp@latest daemon --port 9100 &
27
+
28
+ # 2. In your project, install the MCP config (interactive picker)
29
+ npx mcpsmgr add jtianling/cross-agent-teams-mcp
30
+
31
+ # 3. Start your coding agent as usual
32
+ ```
33
+
34
+ Note: only Claude Code gets push wake out of the box. Codex needs the `--remote` + launcher setup (see section 2 below) for pokes; without it, it has a mailbox but no wake. opencode / cursor / other agents only receive pokes when running inside a tmux pane. If push wake isn't wired up, ask the agent to check its inbox manually ("check my xats inbox").
35
+
36
+ Then talk to your agent in plain language:
37
+
38
+ ```
39
+ # In agent A:
40
+ Register me to xats as backend on team default.
41
+
42
+ # In agent B:
43
+ Register me to xats as frontend on team default.
44
+ Send backend a message: the API has changed.
45
+ ```
46
+
47
+ That's it. Sections below cover the details — daemon flags, manual MCP config, codex `--remote` setup, more usage patterns.
13
48
 
14
49
  ## 1. Start the daemon
15
50
 
@@ -30,26 +65,11 @@ Common flags:
30
65
 
31
66
  ## 2. Configure your agent's MCP client
32
67
 
33
- ### Recommended: install via `mcpsmgr`
34
-
35
- The fastest path is the [`mcpsmgr`](https://www.npmjs.com/package/mcpsmgr) CLI. It reads this repo's manifest (`mcpsmgr.json`) and writes the right MCP entries (and any required stdio proxy entries) into your agent's config in one shot.
36
-
37
- ```bash
38
- cd <your-project>
39
-
40
- # Pick one or run the bare command for an interactive picker.
41
- npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code
42
- npx mcpsmgr add jtianling/cross-agent-teams-mcp -a codex
43
- npx mcpsmgr add jtianling/cross-agent-teams-mcp # interactive
44
- ```
45
-
46
- What it does:
68
+ ### Recommended: `mcpsmgr` (shown in Quick start)
47
69
 
48
- - For Claude Code, writes both `.mcp.json` entries (the HTTP server AND the `cross-agent-teams-channel` stdio proxy) you don't have to know there are two.
49
- - For Codex, writes `~/.codex/config.toml` with `experimental_use_rmcp_client = true` plus the streamable-http MCP entry.
50
- - Prints the post-install steps you still need to run yourself (e.g. the `--dangerously-load-development-channels server:cross-agent-teams-channel` flag for Claude Code, or the codex `--remote` setup if you want push wake).
70
+ [`mcpsmgr`](https://www.npmjs.com/package/mcpsmgr) reads this repo's `mcpsmgr.json` and writes the right MCP entries into your agent's config in one shot — including the Claude Code stdio channel proxy entry, the Codex `experimental_use_rmcp_client` toggle, and the streamable-http MCP entry.
51
71
 
52
- Override the daemon port:
72
+ To override the daemon port:
53
73
 
54
74
  ```bash
55
75
  npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code --port 9300
package/README.zh-CN.md CHANGED
@@ -4,12 +4,47 @@
4
4
 
5
5
  一个本地 MCP daemon, 让同一台机器上的多个 AI 编码 agent (Claude Code, Codex, opencode) 互相通信. agent 注册到 daemon, 互发 1-to-1 消息, 在 team 或 role 内广播, 互相唤醒 — 全部通过一个本地 daemon 完成, 不依赖任何外部服务.
6
6
 
7
- ## npm 包内容
7
+ ## 快速开始
8
8
 
9
- `cross-agent-teams-mcp` 在同一个包里发两个 bin:
9
+ ### Claude Code
10
10
 
11
- - **`cross-agent-teams-mcp daemon`** — 长驻 HTTP daemon. 把 agent 注册表和邮箱存在本地 SQLite 文件里, MCP endpoint 在 `http://127.0.0.1:9100/mcp`.
12
- - **`cross-agent-teams-channel`** stdio MCP shim, 让 Claude Code 通过 `notifications/channel_wake` 接收唤醒通知 (Claude Code 的 experimental channel capability). Claude Code 需要它接收 wake; Codex 用自己的 app-server 通道, opencode 走 tmux-pane 文本注入, 都不需要 channel proxy.
11
+ ```bash
12
+ # 1. 启动 daemon (跑一次, 保持运行)
13
+ npx -y cross-agent-teams-mcp@latest daemon --port 9100 &
14
+
15
+ # 2. 在你的项目下安装 MCP 配置
16
+ npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code
17
+
18
+ # 3. 带上 channel loader 启动 Claude Code (需要手动确认权限)
19
+ claude --dangerously-load-development-channels server:cross-agent-teams-channel
20
+ ```
21
+
22
+ ### 其它 agent (Codex, opencode, ...)
23
+
24
+ ```bash
25
+ # 1. 启动 daemon (跑一次, 保持运行)
26
+ npx -y cross-agent-teams-mcp@latest daemon --port 9100 &
27
+
28
+ # 2. 在你的项目下安装 MCP 配置 (交互式选择对应 agent)
29
+ npx mcpsmgr add jtianling/cross-agent-teams-mcp
30
+
31
+ # 3. 按平时的方式启动对应 coding agent
32
+ ```
33
+
34
+ 注意: 只有 Claude Code 默认就能收到 push 唤醒. Codex 需要 `--remote` + launcher 配置 (见下面 section 2) 才能被 poke; 没配的话只有邮箱, 不会自动醒. opencode / cursor 等其它 agent 只有跑在 tmux pane 里才能被 poke. 没接通 push 唤醒的情况下, 让 agent 自己手动收信即可 (跟它说"查一下我的 xats inbox").
35
+
36
+ 之后用平时跟 agent 对话的语言就能用了:
37
+
38
+ ```
39
+ # Agent A 里:
40
+ Register me to xats as backend on team default.
41
+
42
+ # Agent B 里:
43
+ Register me to xats as frontend on team default.
44
+ Send backend a message: the API has changed.
45
+ ```
46
+
47
+ 就这些. 下面是细节 — daemon 参数, 手动 MCP 配置, codex `--remote` 设置, 更多使用方式.
13
48
 
14
49
  ## 1. 启动 daemon
15
50
 
@@ -30,24 +65,9 @@ daemon 默认监听 `127.0.0.1:9100`. MCP endpoint: `http://127.0.0.1:9100/mcp`
30
65
 
31
66
  ## 2. 在 agent 端配置 MCP client
32
67
 
33
- ### 推荐: `mcpsmgr` 安装
34
-
35
- 最快的方式是用 [`mcpsmgr`](https://www.npmjs.com/package/mcpsmgr) CLI. 它读取本仓库的 manifest (`mcpsmgr.json`), 一次性把对应 agent 需要的 MCP 条目 (含必要的 stdio proxy 条目) 写到 agent 的配置文件里.
36
-
37
- ```bash
38
- cd <your-project>
39
-
40
- # 选一个, 或者用裸命令进入交互式选择.
41
- npx mcpsmgr add jtianling/cross-agent-teams-mcp -a claude-code
42
- npx mcpsmgr add jtianling/cross-agent-teams-mcp -a codex
43
- npx mcpsmgr add jtianling/cross-agent-teams-mcp # 交互式
44
- ```
45
-
46
- 它做了什么:
68
+ ### 推荐: `mcpsmgr` (快速开始里已经演示)
47
69
 
48
- - Claude Code: 同时写两条 `.mcp.json` 条目 (HTTP 工具 + `cross-agent-teams-channel` stdio proxy) 你不用记两条.
49
- - Codex: 写 `~/.codex/config.toml`, 带上 `experimental_use_rmcp_client = true` 和 streamable-http MCP 条目.
50
- - 打印你还需要自己跑的 post-install 步骤 (例如 Claude Code 的 `--dangerously-load-development-channels server:cross-agent-teams-channel` 启动 flag, 或 codex 想要 push 唤醒时的 `--remote` 配置).
70
+ [`mcpsmgr`](https://www.npmjs.com/package/mcpsmgr) 读取本仓库的 `mcpsmgr.json`, 一次性把对应 agent 需要的 MCP 条目写进配置 — 包括 Claude Code stdio channel proxy 条目, Codex `experimental_use_rmcp_client` 开关和 streamable-http MCP 条目.
51
71
 
52
72
  覆盖 daemon 端口:
53
73
 
package/dist/cli.js CHANGED
@@ -388,6 +388,7 @@ function toAgentRow(row) {
388
388
  var AgentsRepo = class {
389
389
  constructor(db) {
390
390
  this.db = db;
391
+ this.list = this.list.bind(this);
391
392
  }
392
393
  db;
393
394
  findByIdentity(args) {
@@ -525,8 +526,8 @@ var AgentsRepo = class {
525
526
  );
526
527
  }
527
528
  list(args) {
528
- const rows = this.db.prepare(
529
- `SELECT
529
+ const exclude = args.excludeRoles ?? [];
530
+ const baseSelect = `SELECT
530
531
  agent_id,
531
532
  agent_type,
532
533
  agent_type_name,
@@ -539,9 +540,17 @@ var AgentsRepo = class {
539
540
  delivery_payload,
540
541
  last_seen_at
541
542
  FROM agents
542
- WHERE team=?
543
- ORDER BY registered_at ASC`
544
- ).all(args.team);
543
+ WHERE team=?`;
544
+ const orderBy = ` ORDER BY registered_at ASC`;
545
+ let rows;
546
+ if (exclude.length > 0) {
547
+ const placeholders = exclude.map(() => "?").join(",");
548
+ rows = this.db.prepare(
549
+ `${baseSelect} AND role NOT IN (${placeholders})${orderBy}`
550
+ ).all(args.team, ...exclude);
551
+ } else {
552
+ rows = this.db.prepare(`${baseSelect}${orderBy}`).all(args.team);
553
+ }
545
554
  const nowMs = Date.now();
546
555
  return rows.map((row) => {
547
556
  const agent = toAgentRow(row);
@@ -3642,7 +3651,7 @@ function registerBusinessTools(server, db, getCallerAgentId, fanout, onRegisterS
3642
3651
  if (typeof who !== "string") return toText(who);
3643
3652
  const row = agents.findById(who);
3644
3653
  return run(() => ({
3645
- agents: agents.list({ team: row.team }).map(toPublicAgentRow)
3654
+ agents: agents.list({ team: row.team, excludeRoles: ["__channel_proxy__"] }).map(toPublicAgentRow)
3646
3655
  }));
3647
3656
  }
3648
3657
  );
@@ -4249,11 +4258,24 @@ function runCleanup(db, opts = {}) {
4249
4258
  );
4250
4259
  const deleteMessages = db.prepare(`DELETE FROM messages WHERE sent_at < ?`);
4251
4260
  const deleteEvents = db.prepare(`DELETE FROM events WHERE created_at < ?`);
4261
+ const deleteStaleProxies = db.prepare(
4262
+ `DELETE FROM agents
4263
+ WHERE role = '__channel_proxy__'
4264
+ AND last_seen_at < ?
4265
+ AND NOT EXISTS (
4266
+ SELECT 1 FROM agents host
4267
+ WHERE host.delivery_kind = 'claude-channel'
4268
+ AND host.role <> '__channel_proxy__'
4269
+ AND json_extract(host.delivery_payload, '$.channel_session_id')
4270
+ = json_extract(agents.delivery_payload, '$.channel_session_id')
4271
+ )`
4272
+ );
4252
4273
  const tx = db.transaction(() => {
4253
4274
  const s = deleteStatus.run(ageCutoff);
4254
4275
  const m = deleteMessages.run(ageCutoff);
4255
4276
  const e = deleteEvents.run(ageCutoff);
4256
- return Number(s.changes) + Number(m.changes) + Number(e.changes);
4277
+ const p = deleteStaleProxies.run(ageCutoff);
4278
+ return Number(s.changes) + Number(m.changes) + Number(e.changes) + Number(p.changes);
4257
4279
  });
4258
4280
  return { deleted: tx() };
4259
4281
  }