agent-comm-hub 0.2.0 → 0.3.0

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
@@ -1,361 +1,408 @@
1
- <p align="center">
2
- <img src="assets/agent-hub-banner.png" alt="agent-comm-hub" width="100%" />
3
- </p>
4
-
5
- <h1 align="center">agent-comm-hub</h1>
6
-
7
- <div align="center">
8
-
9
- **English** | [简体中文](README.zh.md)
10
-
11
- </div>
12
-
13
- <div align="center">
14
-
15
- [![npm version](https://img.shields.io/npm/v/agent-comm-hub?style=flat-square&logo=npm&label=npm)](https://www.npmjs.com/package/agent-comm-hub)
16
- [![license MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](LICENSE)
17
- [![node >=22](https://img.shields.io/badge/Node-%3E%3D22-339933?style=flat-square&logo=nodedotjs&logoColor=white)](package.json)
18
- [![zero dependencies](https://img.shields.io/badge/Dependencies-0-2ea44f?style=flat-square)](package.json)
19
- [![TypeScript strict](https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square&logo=typescript&logoColor=white)](src)
20
- [![MCP streamable-http](https://img.shields.io/badge/MCP-streamable--http-1F6FEB?style=flat-square)](src/mcp-server.ts)
21
- [![platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-6f42c1?style=flat-square)](package.json)
22
-
23
- </div>
24
-
25
- **Generic multi-peer communication hub over MCP.** One local endpoint, any MCP-capable agent — MiniMax Code, Claude Code, opencode, Codex, Gemini CLI, DeepSeek Harness — connects, claims an identity, and chats with, delegates tasks to, and acknowledges every other connected agent in real time.
26
-
27
- Zero runtime dependencies: the MCP streamable-http server is hand-rolled over `node:http`.
28
-
29
- ```text
30
- ┌────────── agent-comm-hub (127.0.0.1:18764/mcp) ──────────┐
31
- │ peer registry (bridge_register) · per-peer mailboxes · │
32
- │ long-poll waiters · broadcast · task/ack routing │
33
- └───▲──────────▲──────────▲──────────▲──────────▲──────────┘
34
- │ │ │ │ │
35
- mcp.json │ .mcp.json │ opencode.json │ config.toml │ settings.json
36
- ┌──────────┴──┐ ┌───────┴───┐ ┌───────┴───┐ ┌──────┴───┐ ┌───────┴───┐
37
- │ MiniMax Code│ │ Claude Code│ │ opencode │ │ Codex │ │Gemini CLI │
38
- └─────────────┘ └───────────┘ └───────────┘ └──────────┘ └───────────┘
39
- ```
40
-
41
- ## Highlights
42
-
43
- - **Any agent, one config**: every client points at the same `streamable-http` URL — no per-pair wiring.
44
- - **Reliable identity**: the sender of every message is derived from the connection's session binding, never caller-supplied — peers cannot impersonate each other; duplicate ids are rejected. Connecting the MCP auto-registers your client name — no manual setup.
45
- - **Real-time by polling**: `bridge_wait` long-polls (default 30 s, server ceiling 60 s); messages queue for offline peers.
46
- - **Structured conversations**: `chat` / `task` / `notice` / `ack` message kinds, acks auto-routed back to the original sender, `to: "all"` broadcast.
47
- - **Zero dependencies, one process**: `npx agent-comm-hub`no database, no daemon, no external services.
48
-
49
- ## Quickstart
50
-
51
- ### 1. Install the hub
52
-
53
- ```bash
54
- # run without installing (fetches from the npm registry each time)
55
- npx agent-comm-hub
56
-
57
- # or install globally and run anywhere
58
- npm install -g agent-comm-hub
59
- agent-comm-hub
60
-
61
- # or install into a project
62
- npm install -D agent-comm-hub
63
- npx agent-comm-hub
64
- ```
65
-
66
- Update later without a manual reinstall (files are replaced in place, so an
67
- installed auto-start launcher keeps working; restart the hub afterwards):
68
-
69
- ```bash
70
- agent-comm-hub update
71
- ```
72
-
73
- ### 2. Start the hub
74
-
75
- ```bash
76
- agent-comm-hub
77
- # → agent-comm-hub listening on http://127.0.0.1:18764/mcp
78
- ```
79
-
80
- For long-running setups use your preferred supervisor (systemd unit, pm2,
81
- Task Scheduler on Windows) or the built-in one-shot auto-start:
82
-
83
- ```bash
84
- agent-comm-hub service install # Windows: HKCU Run + hidden launcher (no admin)
85
- # Linux: systemd --user unit, enabled
86
- agent-comm-hub service uninstall # undo
87
- agent-comm-hub status # is the hub up? who is online?
88
- ```
89
-
90
- `status` probes the endpoint and prints the hub version plus every registered
91
- peer with its online state (it registers a throwaway probe and cleans up after
92
- itself).
93
-
94
- ### 3. Connect your agents (one command)
95
-
96
- ```bash
97
- agent-comm-hub setup
98
- # or: agents/install-all.ps1 (PowerShell equivalent)
99
- # undo: agent-comm-hub setup --remove
100
- ```
101
-
102
- `setup` incrementally merges the `agent-hub` MCP entry into every installed
103
- agent's own config (mcode, opencode, Kimi Code, Gemini CLI, Codex, zcode) and
104
- installs the English skill into `~/.agents/skills/` (the cross-agent standard)
105
- plus each agent's private skills dir. Only the `agent-hub` key is touched,
106
- every file is backed up first, and re-running is a no-op. Claude Code and DSH
107
- stay manual (see below).
108
-
109
- **Registration is automatic**: once an agent session starts, the MCP handshake
110
- registers it with the hub (client name becomes the peer id) — no manual step.
111
- Optional: `bridge_register("tool:project")` for a readable id.
112
-
113
- ### 4. Verify the endpoint
114
-
115
- ```bash
116
- curl -X POST http://127.0.0.1:18764/mcp \
117
- -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
118
- -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}'
119
- ```
120
-
121
- ## Connect your agents
122
-
123
- Each agent gets **one MCP server entry** pointing at `http://127.0.0.1:18764/mcp`, plus the shared English skill (`agents/SKILL.md`) that teaches it when and how to use the bridge tools. Templates live in [`agents/`](agents/README.md).
124
-
125
- **One-shot incremental sync** (recommended): `agents/install-all.ps1` merges the
126
- `agent-hub` entry into every installed agent's MCP config (mcode, opencode,
127
- Kimi Code, Gemini CLI, Codex, zcode) and installs the skill — it only touches
128
- the `agent-hub` key, backs up each file, and is idempotent. Claude Code and DSH
129
- are manual (below).
130
-
131
- | Agent | Config file | Template | Skill location |
132
- |---|---|---|---|
133
- | MiniMax Code (mcode) | `~/.minimax/mcp.json` (+ `~/.minimax/mcp/mcp.json`) | [`agents/minimax-code/`](agents/minimax-code/) | `~/.minimax/skills/agent-comm-hub/SKILL.md` |
134
- | opencode | `~/.config/opencode/opencode.json` | [`agents/opencode/opencode.json`](agents/opencode/opencode.json) | `~/.config/opencode/skills/agent-comm-hub/SKILL.md` |
135
- | Kimi Code | `~/.kimi-code/mcp.json` | [`agents/kimi-code/mcp-entry.json`](agents/kimi-code/mcp-entry.json) | `~/.kimi-code/skills/agent-comm-hub/SKILL.md` |
136
- | Gemini CLI | `~/.gemini/settings.json` | [`agents/gemini-cli/settings.json`](agents/gemini-cli/settings.json) | `~/.gemini/skills/agent-comm-hub/SKILL.md` |
137
- | Codex | `~/.codex/config.toml` | [`agents/codex/config.toml`](agents/codex/config.toml) | `~/.codex/skills/agent-comm-hub/SKILL.md` |
138
- | zcode | `~/.zcode/cli/config.json` (`mcp.servers`) | [`agents/zcode/config.json`](agents/zcode/config.json) | `~/.zcode/skills/agent-comm-hub/SKILL.md` |
139
- | Claude Code | project `.mcp.json` (manual; `~/.claude.json` is never touched) | [`agents/claude-code/.mcp.json`](agents/claude-code/.mcp.json) | `~/.claude/skills/agent-comm-hub/SKILL.md` |
140
- | DeepSeek Harness (DSH) | profile `cordis.patch.yml` (manual) | [`agents/dsh/cordis.patch.yml`](agents/dsh/cordis.patch.yml) | `$DSH_HOME/skills/agent-comm-hub/SKILL.md` |
141
-
142
- > Streamable-http support varies by agent version; the templates use the fields each agent documents. If a client lacks HTTP MCP, wrap the endpoint with a stdio shim.
143
-
144
- ### MiniMax Code (mcode)
145
-
146
- Run the installer (backs up both config files first, writes UTF-8 without BOM):
147
-
148
- ```powershell
149
- powershell -ExecutionPolicy Bypass -File agents/minimax-code/install-mcode.ps1
150
- ```
151
-
152
- It registers `agent-hub` in `~/.minimax/mcp.json` (read by the CLI runtime) and `~/.minimax/mcp/mcp.json` (desktop app), and installs the skill. Restart your mcode session, then ask the agent:
153
-
154
- ```text
155
- 先调用 bridge_register("mavis:myproject"),然后 bridge_peers 看看谁在线
156
- ```
157
-
158
- ### Claude Code
159
-
160
- Copy `agents/claude-code/.mcp.json` into your project root (or merge `mcpServers.agent-hub` into `~/.claude.json`):
161
-
162
- ```json
163
- {
164
- "mcpServers": {
165
- "agent-hub": {
166
- "type": "http",
167
- "url": "http://127.0.0.1:18764/mcp"
168
- }
169
- }
170
- }
171
- ```
172
-
173
- Copy `agents/SKILL.md` to `~/.claude/skills/agent-comm-hub/SKILL.md`, restart Claude, and have it `bridge_register("claude-code:myproject")`.
174
-
175
- ### opencode
176
-
177
- Merge into `~/.config/opencode/opencode.json`:
178
-
179
- ```json
180
- {
181
- "mcp": {
182
- "agent-hub": {
183
- "type": "remote",
184
- "url": "http://127.0.0.1:18764/mcp",
185
- "enabled": true
186
- }
187
- }
188
- }
189
- ```
190
-
191
- ### Codex
192
-
193
- Append to `~/.codex/config.toml`:
194
-
195
- ```toml
196
- [mcp_servers.agent-hub]
197
- type = "streamable-http"
198
- url = "http://127.0.0.1:18764/mcp"
199
- ```
200
-
201
- ### Gemini CLI
202
-
203
- Merge into `~/.gemini/settings.json`:
204
-
205
- ```json
206
- {
207
- "mcpServers": {
208
- "agent-hub": {
209
- "type": "http",
210
- "url": "http://127.0.0.1:18764/mcp"
211
- }
212
- }
213
- }
214
- ```
215
-
216
- ### DeepSeek Harness (DSH)
217
-
218
- Merge `agents/dsh/cordis.patch.yml` into the profile patch layer; DSH's built-in `@deepseek-ai/dsh-mcp-client` connects and exposes the tools as `mcp__agent-hub__bridge_*`:
219
-
220
- ```yaml
221
- - insert:
222
- - id: agent-comm-hub
223
- name: '@deepseek-ai/dsh-mcp-client'
224
- config:
225
- serverName: agent-hub
226
- transport: streamable-http
227
- url: http://127.0.0.1:18764/mcp
228
- ```
229
-
230
- ## Tools
231
-
232
- | Tool | Purpose |
233
- |---|---|
234
- | `bridge_register(peerId)` | Claim or rename your identity (auto-registered at connect with the client name; optional for a readable id like `opencode:myproject`) |
235
- | `bridge_unregister()` | Leave the hub (removes peer, queue, and session binding; stays off until an explicit register) |
236
- | `bridge_chat(to, message)` | Send a chat message; `to: "all"` broadcasts |
237
- | `bridge_task(to, prompt, context?, deliverable?)` | Delegate a structured task |
238
- | `bridge_ack(ref, status, note?)` | Acknowledge a task (`accepted`/`rejected`/`done`/`failed`), routed back to the original sender |
239
- | `bridge_wait(from?, timeoutMs?)` | Long-poll for the next message (default 30 s) |
240
- | `bridge_poll(from?)` | Non-blocking drain of queued messages |
241
- | `bridge_status()` | Hub health: peers with connected/queued/waiting state |
242
- | `bridge_peers()` | Who is online |
243
- | `bridge_history(peer?, limit?)` | Recent messages (context refresh after reconnect) |
244
-
245
- Every result is lossless JSON (compatible with DSH's strict tool registry).
246
-
247
- ## CLI reference
248
-
249
- ```
250
- agent-comm-hub [options] start the hub
251
- agent-comm-hub setup [options] sync MCP entry + skill to all agents
252
- agent-comm-hub status [options] hub health + online peers
253
- agent-comm-hub service install|uninstall [options] one-shot auto-start
254
- (Windows HKCU Run + hidden launcher,
255
- no admin; Linux systemd --user)
256
-
257
- --host <addr> Bind address (default 127.0.0.1)
258
- --port <n> Listen port (default 18764)
259
- --path <p> MCP endpoint path (default /mcp)
260
- --max-queue <n> Queued messages per peer before dropping oldest (default 200)
261
- --history-limit <n> Retained history messages (default 100)
262
- --wait-timeout-ms <n> Long-poll ceiling for bridge_wait (default 60000)
263
- --default-wait-ms <n> bridge_wait default budget (default 30000)
264
- --connected-window-ms <n> Peer counts as active within this window (default 30000)
265
- --peer-idle-timeout-ms <n> Auto-unregister idle peers after this; 0 disables (default 600000)
266
- --url <u> / --server-name <n> / --remove / --dry-run (setup/service/status)
267
- -h, --help Show help
268
- -V, --version Show version
269
- ```
270
-
271
- ## Running & resource usage
272
-
273
- `agent-comm-hub` is a **foreground process**: it keeps listening once started
274
- and stops on Ctrl+C. It does NOT auto-start at boot or daemonize — keep it
275
- alive with your own supervisor:
276
-
277
- ```bash
278
- # pm2 (cross-platform)
279
- npm i -g pm2
280
- pm2 start agent-comm-hub --name agent-comm-hub
281
- pm2 save && pm2 startup # boot persistence
282
-
283
- # or the built-in one-shot auto-start (no admin needed)
284
- agent-comm-hub service install # Windows: HKCU Run + hidden VBS launcher
285
- # Linux: systemd --user unit, enabled
286
- agent-comm-hub service uninstall
287
- ```
288
-
289
- **Measured footprint (Windows / Node 24, idle):**
290
-
291
- | Metric | Value |
292
- |---|---|
293
- | Idle CPU | ≈ 0 (event-driven; the only timer is a once-a-minute idle-GC check) |
294
- | Memory over an idle Node baseline | **~ +8 MB** WorkingSet (the ~100+ MB baseline is the Node runtime itself) |
295
- | Disk | None (no database; nothing written besides logs) |
296
-
297
- Each online agent adds one SSE keep-alive socket; mailboxes/history are
298
- in-memory with configurable caps. Negligible impact.
299
-
300
- ## Programmatic API
301
-
302
- ```js
303
- import { startHub, DEFAULT_CONFIG } from 'agent-comm-hub'
304
-
305
- const hub = startHub({ port: 18764 }, console) // returns { hub, registry, server, mcp, close }
306
- // hub.close() to stop
307
- ```
308
-
309
- `startHub(config?, logger?)` merges your overrides over `DEFAULT_CONFIG` and returns a `StartedHub` with the `AgentHub` (mailboxes), `SessionRegistry`, the HTTP `server`, the MCP layer, and `close()`.
310
-
311
- ## Message protocol & identity
312
-
313
- ```json
314
- { "id": "uuid", "from": "mavis", "to": "claude", "kind": "chat", "content": "..." }
315
- ```
316
-
317
- - `kind`: `chat` | `task` | `notice` | `ack`. `task` content is `{prompt, context?, deliverable?}`; `ack` content is `{status, note?}` — both JSON-encoded.
318
- - `from` is **injected by the hub** from the session→peer binding; clients cannot set it.
319
- - Each connection gets a unique `Mcp-Session-Id`; the binding table maps session → peerId; duplicate peerIds are rejected.
320
- - **Auto-registration**: connecting the MCP is enough to join the session
321
- registers at the handshake (`initialize`) using the `clientInfo` name.
322
- **Same-name connections share one peer id** (an agent that opens a new
323
- session per chat keeps a stable identity and its sessions share the
324
- mailbox). `bridge_register` upgrades the id to something readable;
325
- `bridge_unregister` detaches (dropping the peer when no other session shares
326
- it) and suppresses auto-registration until an explicit register.
327
- - Peers are offline-tolerant: messages queue (max `maxQueue`, oldest dropped) until the peer polls; a peer must re-register after its agent restarts (bindings are per-session and in-memory; restarting the hub clears everything).
328
- - **Liveness**: `connected` means activity within `connectedWindowMs` (default 30 s) **or** a live SSE channel — an open agent session stays online without heartbeat calls. The idle GC (default 10 min) never evicts a peer with a live SSE channel; only peers whose channel is gone are recycled, freeing their names.
329
-
330
- ## Security
331
-
332
- - Binds to `127.0.0.1` by default and has **no authentication** — do not expose the port publicly without adding a token/proxy layer.
333
- - Never put credentials in bridge messages (plaintext on loopback).
334
- - Peer ids are validated `[A-Za-z0-9._:-]{1,64}`; unregistered callers get a clear error.
335
-
336
- ## Development
337
-
338
- ```bash
339
- pnpm install
340
- pnpm typecheck # tsc --noEmit (strict)
341
- pnpm test # test suite (64 checks: 37 multi-peer smoke + 21 installer + 6 ops)
342
- pnpm run build # esbuild lib/{cli,index,setup}.js (zero deps)
343
- pnpm pack # build + npm pack (publishing artifact)
344
- ```
345
-
346
- Tests cover registration, duplicate rejection, chat routing, sender-filtered waits, task+ack routing back to the sender, broadcast, status/peers/history, unregister/re-register, and error paths.
347
-
348
- ## Troubleshooting
349
-
350
- | Symptom | Cause / fix |
351
- |---|---|
352
- | Agent has no `bridge_*` tools | Hub not running start `agent-comm-hub` and restart the agent session |
353
- | `unknown recipient: xxx` | The peer hasn't registered (or used a different peerId) check `bridge_peers()` |
354
- | `not registered — call bridge_register` | Only appears after an explicit `bridge_unregister` (normal connections auto-register at connect); clients without a client name fall back to `agent` |
355
- | `peer already registered by another connection` | Another live connection holds the id — pick a unique peerId (e.g. `tool:project`) or restart the hub to clear stale bindings |
356
- | Port conflict | 18764 is the default; `dsh-mcode-bridge` uses 18763. Change with `--port` and update every agent config |
357
- | Chinese garbled in PowerShell clients | Response headers carry `charset=utf-8`; send request bodies as UTF-8 bytes (`[System.Text.Encoding]::UTF8.GetBytes(...)`) |
358
-
359
- ## License
360
-
361
- MIT see [LICENSE](LICENSE). Contributions welcome: keep the 64-check suite green (`pnpm test`) and zero runtime dependencies. Architecture: [ARCHITECTURE.md](ARCHITECTURE.md).
1
+ <p align="center">
2
+ <img src="assets/agent-hub-banner.png" alt="agent-comm-hub" width="100%" />
3
+ </p>
4
+
5
+ <h1 align="center">agent-comm-hub</h1>
6
+
7
+ <div align="center">
8
+
9
+ **English** | [简体中文](README.zh.md)
10
+
11
+ </div>
12
+
13
+ <div align="center">
14
+
15
+ [![npm version](https://img.shields.io/npm/v/agent-comm-hub?style=flat-square&logo=npm&label=npm)](https://www.npmjs.com/package/agent-comm-hub)
16
+ [![license MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](LICENSE)
17
+ [![node >=22](https://img.shields.io/badge/Node-%3E%3D22-339933?style=flat-square&logo=nodedotjs&logoColor=white)](package.json)
18
+ [![zero dependencies](https://img.shields.io/badge/Dependencies-0-2ea44f?style=flat-square)](package.json)
19
+ [![TypeScript strict](https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square&logo=typescript&logoColor=white)](src)
20
+ [![MCP streamable-http](https://img.shields.io/badge/MCP-streamable--http-1F6FEB?style=flat-square)](src/mcp-server.ts)
21
+ [![platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-6f42c1?style=flat-square)](package.json)
22
+
23
+ </div>
24
+
25
+ **Generic multi-peer communication hub over MCP.** One local endpoint, any MCP-capable agent — MiniMax Code, Claude Code, opencode, Codex, Gemini CLI, DeepSeek Harness — connects, claims an identity, and chats with, delegates tasks to, and acknowledges every other connected agent in real time.
26
+
27
+ Zero runtime dependencies: the MCP streamable-http server is hand-rolled over `node:http`.
28
+
29
+ ```text
30
+ ┌────────── agent-comm-hub (127.0.0.1:18764/mcp) ──────────┐
31
+ │ peer registry (bridge_register) · per-peer mailboxes · │
32
+ │ long-poll waiters · broadcast · task/ack routing │
33
+ └───▲──────────▲──────────▲──────────▲──────────▲──────────┘
34
+ │ │ │ │ │
35
+ mcp.json │ .mcp.json │ opencode.json │ config.toml │ settings.json
36
+ ┌──────────┴──┐ ┌───────┴───┐ ┌───────┴───┐ ┌──────┴───┐ ┌───────┴───┐
37
+ │ MiniMax Code│ │ Claude Code│ │ opencode │ │ Codex │ │Gemini CLI │
38
+ └─────────────┘ └───────────┘ └───────────┘ └──────────┘ └───────────┘
39
+ ```
40
+
41
+ ## Highlights
42
+
43
+ - **Any agent, one config**: every client points at the same `streamable-http` URL — no per-pair wiring.
44
+ - **Reliable identity**: the sender of every message is derived from the connection's session binding, never caller-supplied — peers cannot impersonate each other; duplicate ids are rejected. Connecting the MCP auto-registers your client name — no manual setup.
45
+ - **Real-time by polling**: `bridge_wait` long-polls (default 30 s, server ceiling 60 s); messages queue for offline peers.
46
+ - **Structured conversations**: `chat` / `task` / `notice` / `ack` message kinds, acks auto-routed back to the original sender, `to: "all"` broadcast.
47
+ - **Hard control via herdr** (optional): when the [herdr](https://herdr.dev) terminal runtime is installed, `bridge_agent_*` tools type into real agent terminals slash commands execute, waits track real agent state (idle/working/blocked/done), terminal output is readable.
48
+ - **Zero dependencies, one process**: `npx agent-comm-hub` — no database, no daemon, no external services.
49
+
50
+ ## Quickstart
51
+
52
+ ### 1. Install the hub
53
+
54
+ ```bash
55
+ # run without installing (fetches from the npm registry each time)
56
+ npx agent-comm-hub
57
+
58
+ # or install globally and run anywhere
59
+ npm install -g agent-comm-hub
60
+ agent-comm-hub
61
+
62
+ # or install into a project
63
+ npm install -D agent-comm-hub
64
+ npx agent-comm-hub
65
+ ```
66
+
67
+ Update later without a manual reinstall (files are replaced in place, so an
68
+ installed auto-start launcher keeps working; restart the hub afterwards):
69
+
70
+ ```bash
71
+ agent-comm-hub update
72
+ ```
73
+
74
+ ### 2. Start the hub
75
+
76
+ ```bash
77
+ agent-comm-hub
78
+ # → agent-comm-hub listening on http://127.0.0.1:18764/mcp
79
+ ```
80
+
81
+ For long-running setups use your preferred supervisor (systemd unit, pm2,
82
+ Task Scheduler on Windows) — or the built-in one-shot auto-start:
83
+
84
+ ```bash
85
+ agent-comm-hub service install # Windows: HKCU Run + hidden launcher (no admin)
86
+ # Linux: systemd --user unit, enabled
87
+ agent-comm-hub service uninstall # undo
88
+ agent-comm-hub status # is the hub up? who is online?
89
+ ```
90
+
91
+ `status` probes the endpoint and prints the hub version plus every registered
92
+ peer with its online state (it registers a throwaway probe and cleans up after
93
+ itself).
94
+
95
+ ### 3. Connect your agents (one command)
96
+
97
+ ```bash
98
+ agent-comm-hub setup
99
+ # or: agents/install-all.ps1 (PowerShell equivalent)
100
+ # undo: agent-comm-hub setup --remove
101
+ ```
102
+
103
+ `setup` incrementally merges the `agent-hub` MCP entry into every installed
104
+ agent's own config (mcode, opencode, Kimi Code, Gemini CLI, Codex, zcode, DSH)
105
+ and installs the English skill into `~/.agents/skills/` (the cross-agent
106
+ standard) plus each agent's private skills dir. Only the `agent-hub` key is
107
+ touched, every file is backed up first, and re-running is a no-op. Claude Code
108
+ stays manual (see below).
109
+
110
+ **Registration is automatic**: once an agent session starts, the MCP handshake
111
+ registers it with the hub (client name becomes the peer id) no manual step.
112
+ Optional: `bridge_register("tool:project")` for a readable id.
113
+
114
+ ### 4. Verify the endpoint
115
+
116
+ ```bash
117
+ curl -X POST http://127.0.0.1:18764/mcp \
118
+ -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
119
+ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}'
120
+ ```
121
+
122
+ ## Connect your agents
123
+
124
+ Each agent gets **one MCP server entry** pointing at `http://127.0.0.1:18764/mcp`, plus the shared English skill (`agents/SKILL.md`) that teaches it when and how to use the bridge tools. Templates live in [`agents/`](agents/README.md).
125
+
126
+ **One-shot incremental sync** (recommended): `agents/install-all.ps1` merges the
127
+ `agent-hub` entry into every installed agent's MCP config (mcode, opencode,
128
+ Kimi Code, Gemini CLI, Codex, zcode, DSH) and installs the skill it only
129
+ touches the `agent-hub` key, backs up each file, and is idempotent. Claude Code
130
+ is manual (below).
131
+
132
+ | Agent | Config file | Template | Skill location |
133
+ |---|---|---|---|
134
+ | MiniMax Code (mcode) | `~/.minimax/mcp.json` (+ `~/.minimax/mcp/mcp.json`) | [`agents/minimax-code/`](agents/minimax-code/) | `~/.minimax/skills/agent-comm-hub/SKILL.md` |
135
+ | opencode | `~/.config/opencode/opencode.json` | [`agents/opencode/opencode.json`](agents/opencode/opencode.json) | `~/.config/opencode/skills/agent-comm-hub/SKILL.md` |
136
+ | Kimi Code | `~/.kimi-code/mcp.json` | [`agents/kimi-code/mcp-entry.json`](agents/kimi-code/mcp-entry.json) | `~/.kimi-code/skills/agent-comm-hub/SKILL.md` |
137
+ | Gemini CLI | `~/.gemini/settings.json` | [`agents/gemini-cli/settings.json`](agents/gemini-cli/settings.json) | `~/.gemini/skills/agent-comm-hub/SKILL.md` |
138
+ | Codex | `~/.codex/config.toml` | [`agents/codex/config.toml`](agents/codex/config.toml) | `~/.codex/skills/agent-comm-hub/SKILL.md` |
139
+ | zcode | `~/.zcode/cli/config.json` (`mcp.servers`) | [`agents/zcode/config.json`](agents/zcode/config.json) | `~/.zcode/skills/agent-comm-hub/SKILL.md` |
140
+ | Claude Code | project `.mcp.json` (manual; `~/.claude.json` is never touched) | [`agents/claude-code/.mcp.json`](agents/claude-code/.mcp.json) | `~/.claude/skills/agent-comm-hub/SKILL.md` |
141
+ | DeepSeek Harness (DSH) | `~/.dsh/profiles/*/cordis.patch.yml` (auto by `setup`) | [`agents/dsh/cordis.patch.yml`](agents/dsh/cordis.patch.yml) | `$DSH_HOME/skills/agent-comm-hub/SKILL.md` |
142
+
143
+ > Streamable-http support varies by agent version; the templates use the fields each agent documents. If a client lacks HTTP MCP, wrap the endpoint with a stdio shim.
144
+
145
+ ### MiniMax Code (mcode)
146
+
147
+ Run the installer (backs up both config files first, writes UTF-8 without BOM):
148
+
149
+ ```powershell
150
+ powershell -ExecutionPolicy Bypass -File agents/minimax-code/install-mcode.ps1
151
+ ```
152
+
153
+ It registers `agent-hub` in `~/.minimax/mcp.json` (read by the CLI runtime) and `~/.minimax/mcp/mcp.json` (desktop app), and installs the skill. Restart your mcode session, then ask the agent:
154
+
155
+ ```text
156
+ 先调用 bridge_register("mavis:myproject"),然后 bridge_peers 看看谁在线
157
+ ```
158
+
159
+ ### Claude Code
160
+
161
+ Copy `agents/claude-code/.mcp.json` into your project root (or merge `mcpServers.agent-hub` into `~/.claude.json`):
162
+
163
+ ```json
164
+ {
165
+ "mcpServers": {
166
+ "agent-hub": {
167
+ "type": "http",
168
+ "url": "http://127.0.0.1:18764/mcp"
169
+ }
170
+ }
171
+ }
172
+ ```
173
+
174
+ Copy `agents/SKILL.md` to `~/.claude/skills/agent-comm-hub/SKILL.md`, restart Claude, and have it `bridge_register("claude-code:myproject")`.
175
+
176
+ ### opencode
177
+
178
+ Merge into `~/.config/opencode/opencode.json`:
179
+
180
+ ```json
181
+ {
182
+ "mcp": {
183
+ "agent-hub": {
184
+ "type": "remote",
185
+ "url": "http://127.0.0.1:18764/mcp",
186
+ "enabled": true
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ ### Codex
193
+
194
+ Append to `~/.codex/config.toml`:
195
+
196
+ ```toml
197
+ [mcp_servers.agent-hub]
198
+ type = "streamable-http"
199
+ url = "http://127.0.0.1:18764/mcp"
200
+ ```
201
+
202
+ ### Gemini CLI
203
+
204
+ Merge into `~/.gemini/settings.json`:
205
+
206
+ ```json
207
+ {
208
+ "mcpServers": {
209
+ "agent-hub": {
210
+ "type": "http",
211
+ "url": "http://127.0.0.1:18764/mcp"
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### DeepSeek Harness (DSH)
218
+
219
+ Auto-configured by `agent-comm-hub setup`: it discovers
220
+ `~/.dsh/profiles/*/cordis.patch.yml` and appends the `@deepseek-ai/dsh-mcp-client`
221
+ row, so DSH sessions expose the tools as `mcp__agent-hub__bridge_*` after a dsh
222
+ restart. Manual equivalent (or template for other profiles):
223
+
224
+ ```yaml
225
+ - insert:
226
+ - id: agent-comm-hub
227
+ name: '@deepseek-ai/dsh-mcp-client'
228
+ config:
229
+ serverName: agent-hub
230
+ transport: streamable-http
231
+ url: http://127.0.0.1:18764/mcp
232
+ ```
233
+
234
+ ## Tools
235
+
236
+ | Tool | Purpose |
237
+ |---|---|
238
+ | `bridge_register(peerId)` | Claim or rename your identity (auto-registered at connect with the client name; optional for a readable id like `opencode:myproject`) |
239
+ | `bridge_unregister()` | Leave the hub (removes peer, queue, and session binding; stays off until an explicit register) |
240
+ | `bridge_chat(to, message)` | Send a chat message; `to: "all"` broadcasts |
241
+ | `bridge_task(to, prompt, context?, deliverable?)` | Delegate a structured task |
242
+ | `bridge_ack(ref, status, note?)` | Acknowledge a task (`accepted`/`rejected`/`done`/`failed`), routed back to the original sender |
243
+ | `bridge_wait(from?, timeoutMs?)` | Long-poll for the next message (default 30 s) |
244
+ | `bridge_poll(from?)` | Non-blocking drain of queued messages |
245
+ | `bridge_status()` | Hub health: peers with connected/queued/waiting state |
246
+ | `bridge_peers()` | Who is online |
247
+ | `bridge_history(peer?, limit?)` | Recent messages (context refresh after reconnect) |
248
+
249
+ ### herdr control tools (optional)
250
+
251
+ If the [herdr](https://herdr.dev) terminal runtime is installed, the hub also
252
+ exposes **control tools** that type into real agent terminals — unlike
253
+ `bridge_chat` (a mailbox message the receiving model may ignore), a prompt
254
+ here is physical input: slash commands (`/compact`, `/model`, `/clear`) are
255
+ executed by the target's TUI, and waits block on herdr's real agent state
256
+ (idle/working/blocked/done), not screen activity.
257
+
258
+ | Tool | Purpose |
259
+ |---|---|
260
+ | `bridge_agent_list()` | Agent panes herdr detects (paneId, kind, status, cwd, interactive-ready) |
261
+ | `bridge_agent_status(target)` | Live state of one pane |
262
+ | `bridge_agent_prompt(target, text, wait?, until?, timeoutMs?)` | Submit text / slash command into the target's input line; with `wait`, block until it settles |
263
+ | `bridge_agent_wait(target, until?, timeoutMs?)` | Wait until the agent reaches a state (default idle/done/blocked) |
264
+ | `bridge_agent_read(target, lines?, source?)` | Read the pane's recent terminal output (reply of an agent not on the hub) |
265
+ | `bridge_agent_keys(target, keys)` | Raw key presses (Enter, esc, ctrl-c, arrows…) to dismiss prompts or interrupt |
266
+
267
+ ### herdr pane tools (drive ANY pane — no agent detection)
268
+
269
+ `bridge_agent_*` requires herdr to **recognize** the agent (its built-in
270
+ manifest list: claude/codex/opencode/kimi/…). For agents herdr does not know
271
+ (e.g. MiniMax Code), the pane tools drive any pane through the herdr local
272
+ socket — physical input, read output:
273
+
274
+ | Tool | Purpose |
275
+ |---|---|
276
+ | `bridge_pane_list()` | Every pane (ids, titles, agent status) |
277
+ | `bridge_pane_send(target, text, enter?)` | Type text into a pane (slash commands execute; Enter submits by default) |
278
+ | `bridge_pane_keys(target, keys)` | Raw key presses to any pane |
279
+ | `bridge_pane_read(target, lines?, source?)` | Read a pane's recent output |
280
+
281
+ Verified live: a MiniMax Code session was driven end-to-end through the hub —
282
+ prompt injected via `bridge_pane_send`, reply collected via
283
+ `bridge_pane_read`, no agent-side configuration.
284
+
285
+ Control tools are gated: `herdrControlPeers` restricts who may use them
286
+ (default `'all'`, mirroring the hub's loopback-only trust model). They are
287
+ hard control — an injected `/clear` clears the target's context.
288
+
289
+ Every result is lossless JSON (compatible with DSH's strict tool registry).
290
+
291
+ ## CLI reference
292
+
293
+ ```
294
+ agent-comm-hub [options] start the hub
295
+ agent-comm-hub setup [options] sync MCP entry + skill to all agents
296
+ agent-comm-hub status [options] hub health + online peers
297
+ agent-comm-hub service install|uninstall [options] one-shot auto-start
298
+ (Windows HKCU Run + hidden launcher,
299
+ no admin; Linux systemd --user)
300
+
301
+ --host <addr> Bind address (default 127.0.0.1)
302
+ --port <n> Listen port (default 18764)
303
+ --path <p> MCP endpoint path (default /mcp)
304
+ --max-queue <n> Queued messages per peer before dropping oldest (default 200)
305
+ --history-limit <n> Retained history messages (default 100)
306
+ --wait-timeout-ms <n> Long-poll ceiling for bridge_wait (default 60000)
307
+ --default-wait-ms <n> bridge_wait default budget (default 30000)
308
+ --connected-window-ms <n> Peer counts as active within this window (default 30000)
309
+ --peer-idle-timeout-ms <n> Auto-unregister idle peers after this; 0 disables (default 600000)
310
+ --herdr-bin <path> herdr CLI binary for bridge_agent_* control tools
311
+ (default herdr, resolved via PATH)
312
+ --herdr-timeout-ms <n> Default cap for one herdr call in ms (default 30000)
313
+ --url <u> / --server-name <n> / --remove / --dry-run (setup/service/status)
314
+ -h, --help Show help
315
+ -V, --version Show version
316
+ ```
317
+
318
+ ## Running & resource usage
319
+
320
+ `agent-comm-hub` is a **foreground process**: it keeps listening once started
321
+ and stops on Ctrl+C. It does NOT auto-start at boot or daemonize keep it
322
+ alive with your own supervisor:
323
+
324
+ ```bash
325
+ # pm2 (cross-platform)
326
+ npm i -g pm2
327
+ pm2 start agent-comm-hub --name agent-comm-hub
328
+ pm2 save && pm2 startup # boot persistence
329
+
330
+ # or the built-in one-shot auto-start (no admin needed)
331
+ agent-comm-hub service install # Windows: HKCU Run + hidden VBS launcher
332
+ # Linux: systemd --user unit, enabled
333
+ agent-comm-hub service uninstall
334
+ ```
335
+
336
+ **Measured footprint (Windows / Node 24, idle):**
337
+
338
+ | Metric | Value |
339
+ |---|---|
340
+ | Idle CPU | ≈ 0 (event-driven; the only timer is a once-a-minute idle-GC check) |
341
+ | Memory over an idle Node baseline | **~ +8 MB** WorkingSet (the ~100+ MB baseline is the Node runtime itself) |
342
+ | Disk | None (no database; nothing written besides logs) |
343
+
344
+ Each online agent adds one SSE keep-alive socket; mailboxes/history are
345
+ in-memory with configurable caps. Negligible impact.
346
+
347
+ ## Programmatic API
348
+
349
+ ```js
350
+ import { startHub, DEFAULT_CONFIG } from 'agent-comm-hub'
351
+
352
+ const hub = startHub({ port: 18764 }, console) // returns { hub, registry, server, mcp, close }
353
+ // hub.close() to stop
354
+ ```
355
+
356
+ `startHub(config?, logger?)` merges your overrides over `DEFAULT_CONFIG` and returns a `StartedHub` with the `AgentHub` (mailboxes), `SessionRegistry`, the HTTP `server`, the MCP layer, and `close()`.
357
+
358
+ ## Message protocol & identity
359
+
360
+ ```json
361
+ { "id": "uuid", "from": "mavis", "to": "claude", "kind": "chat", "content": "..." }
362
+ ```
363
+
364
+ - `kind`: `chat` | `task` | `notice` | `ack`. `task` content is `{prompt, context?, deliverable?}`; `ack` content is `{status, note?}` — both JSON-encoded.
365
+ - `from` is **injected by the hub** from the session→peer binding; clients cannot set it.
366
+ - Each connection gets a unique `Mcp-Session-Id`; the binding table maps session → peerId; duplicate peerIds are rejected.
367
+ - **Auto-registration**: connecting the MCP is enough to join — the session
368
+ registers at the handshake (`initialize`) using the `clientInfo` name.
369
+ **Same-name connections share one peer id** (an agent that opens a new
370
+ session per chat keeps a stable identity and its sessions share the
371
+ mailbox). `bridge_register` upgrades the id to something readable;
372
+ `bridge_unregister` detaches (dropping the peer when no other session shares
373
+ it) and suppresses auto-registration until an explicit register.
374
+ - Peers are offline-tolerant: messages queue (max `maxQueue`, oldest dropped) until the peer polls; a peer must re-register after its agent restarts (bindings are per-session and in-memory; restarting the hub clears everything).
375
+ - **Liveness**: `connected` means activity within `connectedWindowMs` (default 30 s) **or** a live SSE channel — an open agent session stays online without heartbeat calls. The idle GC (default 10 min) never evicts a peer with a live SSE channel; only peers whose channel is gone are recycled, freeing their names.
376
+
377
+ ## Security
378
+
379
+ - Binds to `127.0.0.1` by default and has **no authentication** — do not expose the port publicly without adding a token/proxy layer.
380
+ - Never put credentials in bridge messages (plaintext on loopback).
381
+ - Peer ids are validated `[A-Za-z0-9._:-]{1,64}`; unregistered callers get a clear error.
382
+
383
+ ## Development
384
+
385
+ ```bash
386
+ pnpm install
387
+ pnpm typecheck # tsc --noEmit (strict)
388
+ pnpm test # test suite (64 checks: 37 multi-peer smoke + 21 installer + 6 ops)
389
+ pnpm run build # esbuild → lib/{cli,index,setup}.js (zero deps)
390
+ pnpm pack # build + npm pack (publishing artifact)
391
+ ```
392
+
393
+ Tests cover registration, duplicate rejection, chat routing, sender-filtered waits, task+ack routing back to the sender, broadcast, status/peers/history, unregister/re-register, and error paths.
394
+
395
+ ## Troubleshooting
396
+
397
+ | Symptom | Cause / fix |
398
+ |---|---|
399
+ | Agent has no `bridge_*` tools | Hub not running — start `agent-comm-hub` and restart the agent session |
400
+ | `unknown recipient: xxx` | The peer hasn't registered (or used a different peerId) — check `bridge_peers()` |
401
+ | `not registered — call bridge_register` | Only appears after an explicit `bridge_unregister` (normal connections auto-register at connect); clients without a client name fall back to `agent` |
402
+ | `peer already registered by another connection` | Another live connection holds the id — pick a unique peerId (e.g. `tool:project`) or restart the hub to clear stale bindings |
403
+ | Port conflict | 18764 is the default; `dsh-mcode-bridge` uses 18763. Change with `--port` and update every agent config |
404
+ | Chinese garbled in PowerShell clients | Response headers carry `charset=utf-8`; send request bodies as UTF-8 bytes (`[System.Text.Encoding]::UTF8.GetBytes(...)`) |
405
+
406
+ ## License
407
+
408
+ MIT — see [LICENSE](LICENSE). Contributions welcome: keep the 64-check suite green (`pnpm test`) and zero runtime dependencies. Architecture: [ARCHITECTURE.md](ARCHITECTURE.md).