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 +42 -22
- package/README.zh-CN.md +41 -21
- package/dist/cli.js +29 -7
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/src/daemon/cleanup.ts +17 -1
- package/src/mcp/tools.ts +3 -1
- package/src/storage/agents-repo.ts +20 -6
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
|
-
##
|
|
7
|
+
## Quick start
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### Claude Code
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
7
|
+
## 快速开始
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### Claude Code
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
### 推荐:
|
|
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
|
-
|
|
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
|
|
529
|
-
|
|
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
|
-
|
|
544
|
-
|
|
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
|
-
|
|
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
|
}
|