agent-comm-hub
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-comm-hubbroadcast a message asking all agents for their current status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
English | 简体中文
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.
Zero runtime dependencies: the MCP streamable-http server is hand-rolled over node:http.
┌────────── agent-comm-hub (127.0.0.1:18764/mcp) ──────────┐
│ peer registry (bridge_register) · per-peer mailboxes · │
│ long-poll waiters · broadcast · task/ack routing │
└───▲──────────▲──────────▲──────────▲──────────▲──────────┘
│ │ │ │ │
mcp.json │ .mcp.json │ opencode.json │ config.toml │ settings.json
┌──────────┴──┐ ┌───────┴───┐ ┌───────┴───┐ ┌──────┴───┐ ┌───────┴───┐
│ MiniMax Code│ │ Claude Code│ │ opencode │ │ Codex │ │Gemini CLI │
└─────────────┘ └───────────┘ └───────────┘ └──────────┘ └───────────┘Highlights
Any agent, one config: every client points at the same
streamable-httpURL — no per-pair wiring.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. Peers carry a profile (client name/version, display alias) and joins/leaves are pushed over SSE.
Real-time by polling:
bridge_waitlong-polls (default 30 s, server ceiling 60 s); messages queue for offline peers.Structured conversations:
chat/task/notice/ackmessage kinds, acks auto-routed back to the original sender,to: "all"broadcast.Hard control via herdr (optional): when the herdr 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.Zero dependencies, one process:
npx agent-comm-hub— no database, no daemon, no external services.Team server (remote mode):
--auth-tokensputs the hub on a LAN/VPS with per-user bearer tokens — one peer per person even when everyone runs the same client, manager roles included. Seeserver/README.md.
Related MCP server: kitty-hive
Quickstart
1. Install the hub
# run without installing (fetches from the npm registry each time)
npx agent-comm-hub
# or install globally and run anywhere
npm install -g agent-comm-hub
agent-comm-hub
# or install into a project
npm install -D agent-comm-hub
npx agent-comm-hubUpdate later without a manual reinstall (files are replaced in place, so an installed auto-start launcher keeps working; restart the hub afterwards):
agent-comm-hub update2. Start the hub
agent-comm-hub
# → agent-comm-hub listening on http://127.0.0.1:18764/mcpFor long-running setups use your preferred supervisor (systemd unit, pm2, Task Scheduler on Windows) — or the built-in one-shot auto-start:
agent-comm-hub service install # Windows: HKCU Run + hidden launcher (no admin)
# Linux: systemd --user unit, enabled
# macOS: launchd LaunchAgent
agent-comm-hub service uninstall # undo
agent-comm-hub status # is the hub up? who is online?status probes the endpoint and prints the hub version plus every registered
peer with its online state (it registers a throwaway probe and cleans up after
itself).
3. Connect your agents (one command)
agent-comm-hub setup
# (agents/install-all.ps1 is deprecated — it forwards to this command)
# undo: agent-comm-hub setup --remove
# list what is installed (no changes): agent-comm-hub discover
# configure a single agent: agent-comm-hub setup --agent codexsetup discovers which agents are installed on this machine (PATH
commands, config paths, npm global packages — no shell, cross-platform) and
merges the agent-hub MCP entry into each one's config (mcode, opencode, Kimi
Code, Gemini CLI, Codex, zcode, DSH, claude-desktop on macOS), plus the English
skill into ~/.agents/skills/ (the cross-agent standard) and each agent's
private skills dir. Which agents are supported is declared in
agents/registry.json — adding a new agent is one
registry record, no code change. Only the agent-hub key is touched, every
file is backed up first, and re-running is a no-op. Claude Code's MCP config
stays manual (see below).
Registration is automatic: once an agent session starts, the MCP handshake
registers it with the hub (client name becomes the peer id) — no manual step.
Optional: bridge_register("tool:project") for a readable id.
4. Verify the endpoint
curl -X POST http://127.0.0.1:18764/mcp \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}'Connect your agents
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/.
One-shot incremental sync (recommended): agent-comm-hub setup merges the
agent-hub entry into every installed agent's MCP config (mcode, opencode,
Kimi Code, Gemini CLI, Codex, zcode, DSH) and installs the skill — it only
touches the agent-hub key, backs up each file, and is idempotent. Claude Code
is manual (below).
Agent | Config file | Template | Skill location |
MiniMax Code (mcode) |
|
| |
opencode |
|
| |
Kimi Code |
|
| |
Gemini CLI |
|
| |
Codex |
|
| |
zcode |
|
| |
Claude Code | project |
| |
DeepSeek Harness (DSH) |
|
|
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.
MiniMax Code (mcode)
Run the installer (backs up both config files first, writes UTF-8 without BOM):
powershell -ExecutionPolicy Bypass -File agents/minimax-code/install-mcode.ps1It 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:
先调用 bridge_register("mavis:myproject"),然后 bridge_peers 看看谁在线Claude Code
Copy agents/claude-code/.mcp.json into your project root (or merge mcpServers.agent-hub into ~/.claude.json):
{
"mcpServers": {
"agent-hub": {
"type": "http",
"url": "http://127.0.0.1:18764/mcp"
}
}
}Copy agents/SKILL.md to ~/.claude/skills/agent-hub/SKILL.md, restart Claude, and have it bridge_register("claude-code:myproject").
opencode
Merge into ~/.config/opencode/opencode.json:
{
"mcp": {
"agent-hub": {
"type": "remote",
"url": "http://127.0.0.1:18764/mcp",
"enabled": true
}
}
}Codex
Append to ~/.codex/config.toml:
[mcp_servers.agent-hub]
type = "streamable-http"
url = "http://127.0.0.1:18764/mcp"Gemini CLI
Merge into ~/.gemini/settings.json:
{
"mcpServers": {
"agent-hub": {
"type": "http",
"url": "http://127.0.0.1:18764/mcp"
}
}
}DeepSeek Harness (DSH)
Auto-configured by agent-comm-hub setup: it discovers
~/.dsh/profiles/*/cordis.patch.yml and appends the @deepseek-ai/dsh-mcp-client
row with serverName: agent-comm-hub (not the generic agent-hub key other
agents use). That name is deliberate: a DSH MCP-manager plugin that dynamically
mounts serverName: "agent-hub" would otherwise collide
(serverName "agent-hub" is already in use by another mcp-client instance) and
fail the whole profile load. DSH sessions expose the tools as
mcp__agent-comm-hub__bridge_* after a dsh restart. Re-running setup rewrites
any older serverName: agent-hub insert to the new key. Manual equivalent:
- insert:
- id: agent-comm-hub
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: agent-comm-hub
transport: streamable-http
url: http://127.0.0.1:18764/mcpIf your MCP manager already owns the hub mount entirely, undo the static insert
with agent-comm-hub setup --remove (or only refresh skills via
setup --agent for other agents) and keep the dynamic mount.
Tools
Tool | Purpose |
| Claim or rename your identity (auto-registered at connect with the client name; optional for a readable id like |
| Set your own display alias; renaming or true-renaming another peer needs manager rights |
| Leave the hub (removes peer, queue, and session binding; stays off until an explicit register). With |
| Send a chat message; |
| Send a system-flavoured notice ( |
| Delegate a structured task ( |
| Acknowledge a task ( |
| Long-poll for the next message (default 30 s). |
| Non-blocking drain of queued messages ( |
| Acknowledge leased messages; uncommitted ones come back when the lease expires |
| Give leased (or dead-lettered) messages back immediately — use when handling failed |
| Hub health: peers with connected/queued/waiting state |
| Who is online, how reachable ( |
| Recent messages (context refresh after reconnect) |
| Task ledger rows you sent or received |
| One task's state, per-assignee rows and the full ack timeline (also carries the A2A aliases |
| Cancel a task — either side may; routed to the other side and terminal |
| Answer an |
| Say what you can do (skills, |
| Find a peer to hand work to, with its current load |
| Named channels for a subset of peers |
That is the full 26 message + group tools; the 11 control tools are below. (37 in total and symmetric on every side — see ARCHITECTURE.md §4.)
Two peer ids are reserved and cannot be registered or renamed into: all (broadcast) and hub (the hub's own drop notices — bridge_wait { from: "hub" } subscribes to them).
herdr control tools (optional)
If the herdr terminal runtime is installed, the hub also
exposes control tools that type into real agent terminals — unlike
bridge_chat (a mailbox message the receiving model may ignore), a prompt
here is physical input: slash commands (/compact, /model, /clear) are
executed by the target's TUI, and waits block on herdr's real agent state
(idle/working/blocked/done), not screen activity.
Tool | Purpose |
| Agent panes herdr detects (paneId, kind, status, cwd, interactive-ready) |
| Live state of one pane |
| Submit text / slash command into the target's input line; with |
| Wait until the agent reaches a state (default idle/done/blocked) |
| Read the pane's recent terminal output (reply of an agent not on the hub) |
| Raw key presses (Enter, esc, ctrl-c, arrows…) to dismiss prompts or interrupt |
herdr pane tools (drive ANY pane — no agent detection)
bridge_agent_* requires herdr to recognize the agent (its built-in
manifest list: claude/codex/opencode/kimi/…). For agents herdr does not know
(e.g. MiniMax Code), the pane tools drive any pane through the herdr local
socket — physical input, read output:
Tool | Purpose |
| Every pane (ids, titles, agent status) |
| Type text into a pane (slash commands execute; Enter submits by default) |
| Raw key presses to any pane |
| Read a pane's recent output |
| Wait for a pane to reach a state (idle / working / blocked / done) |
Verified live: a MiniMax Code session was driven end-to-end through the hub —
prompt injected via bridge_pane_send, reply collected via
bridge_pane_read, no agent-side configuration.
Control tools are gated: herdrControlPeers restricts who may use them
(default 'all', mirroring the hub's loopback-only trust model). They are
hard control — an injected /clear clears the target's context.
Roster management (aliases, kick)
Peers carry a profile: the client name/version reported at connect, plus
an optional display alias (bridge_rename). The alias is cosmetic — it
shows up in bridge_peers / bridge_status and the desktop roster, while
routing, mailboxes, history, and acks keep using the peer id, so a rename
never drops messages. A manager can also truly rename a registered peer
(bridge_rename { peer, peerId }): mailbox, waiters, session bindings, and
history attribution move atomically — queued messages and acks stay
continuous. Renaming yourself is open to everyone; renaming/kicking
another peer (bridge_unregister { peer }) or reading another peer's
history (bridge_history { peer } / peer: "all") requires the manager
role (--manager-peers, default agent-hub-cli,hub-admin — the desktop GUI
and the web console identities).
With no credential configured this is a convention on top of the loopback trust
model, not authentication — the peer id is simply whoever claimed it first. Set
--manager-token <secret> (or drop the secret in <state-file dir>/manager.token)
to make manager PRIVILEGES require it: rename/kick/full-history/task-board and the
SSE relay then need Authorization: Bearer <secret>, and a credential-less client
that claims a manager id gets no power. The id itself is not reserved — the
desktop GUI identifies itself as agent-hub-cli, so reserving it would stop the
GUI from connecting. Note that claiming the id still occupies its identity and
mailbox even without the credential, and that in remote mode (--auth-tokens) the
token table owns the Authorization header, so --manager-token is ignored there.
Rosters persist: --state-file (default ~/.agent-comm-hub/roster.json,
off to disable) keeps aliases and client info across hub restarts.
Roster changes and queued mail are pushed over the SSE channel as
notifications/message events (data.event: "peers_changed" with the full
roster, data.event: "message" hint scoped to the recipient), so GUIs and
skills can react without polling.
Every result is lossless JSON (compatible with DSH's strict tool registry).
CLI reference
agent-comm-hub [options] start the hub
agent-comm-hub setup [options] sync MCP entry + skill to all agents
agent-comm-hub status [options] hub health + online peers
agent-comm-hub service install|uninstall [options] one-shot auto-start
(Windows HKCU Run + hidden launcher,
no admin; Linux systemd --user)
--host <addr> Bind address (default 127.0.0.1)
--port <n> Listen port (default 18764)
--path <p> MCP endpoint path (default /mcp)
--max-queue <n> Queued messages per peer before dropping oldest (default 200)
--history-limit <n> Retained history messages (default 1000)
--wait-timeout-ms <n> Long-poll ceiling for bridge_wait (default 60000)
--default-wait-ms <n> bridge_wait default budget (default 30000)
--connected-window-ms <n> Peer counts as active within this window (default 30000)
--peer-idle-timeout-ms <n> Park (not delete) idle peers after this; 0 disables the GC
entirely (default 600000)
--parked-ttl-ms <n> Drop a parked mailbox after this; 0 disables expiry
(default 604800000 = 7 days)
--rate-per-min <n> Per-peer mailbox rate limit (messages per minute); 0 (default)
is unlimited. Guards a recipient against a broadcast storm;
excess is counted as `droppedRate` in the roster
--db <path> SQLite state file for history/mailboxes/roster/groups/tasks
(default ~/.agent-comm-hub/state.db; "off" = memory + JSON roster)
--auth-tokens <file> REMOTE MODE: require `Authorization: Bearer <token>`; the token,
not the client name, decides the peer id. Also refuses a
non-loopback --host unless this is set.
--allow-join (remote mode) accept token-less walk-in peers, each on a unique
id; LAN/VPN only — keep it off on the public internet.
--heartbeat-ms <n> SSE heartbeat cadence (default 20000)
--runner <json> Executor for a peer that is NOT polling: one JSON object
or an array, e.g. {"peer":"codex","kind":"cli",
"command":"codex","args":["exec","{prompt}"]} or
{"peer":"mcode","kind":"herdr"}. Off by default; the
runner's outcome is written back as that peer's ack.
--herdr-bin <path> herdr CLI binary for bridge_agent_* control tools
(default herdr, resolved via PATH)
--herdr-timeout-ms <n> Default cap for one herdr call in ms (default 30000)
--manager-peers <ids> Comma-separated roster managers, or "all"
(default agent-hub-cli,hub-admin — desktop GUI + web console)
--manager-token <secret> Require this secret (Authorization: Bearer <secret>) for hub
manager PRIVILEGES (rename/kick/full history/relay); otherwise
<state-file dir>/manager.token is read when present. The peer
id itself is not reserved. Ignored with --auth-tokens.
--allow-origins <list> Comma-separated browser origins allowed to call the MCP
endpoint (e.g. https://hub.example.com). Requests without
an Origin header and loopback origins are always allowed;
anything else gets 403 (the MCP spec's DNS-rebinding rule).
--insecure Allow --host to bind a non-loopback address with NO token
table. Refused by default: without --auth-tokens the hub
would trust every client that can reach the port.
--state-file <path> Roster persistence file
(default ~/.agent-comm-hub/roster.json; "off" = memory only)
--url <u> / --server-name <n> / --remove / --dry-run (setup/service/status)
-h, --help Show help
-V, --version Show versionRunning & resource usage
agent-comm-hub is a foreground process: it keeps listening once started
and stops on Ctrl+C. It does NOT auto-start at boot or daemonize — keep it
alive with your own supervisor:
# pm2 (cross-platform)
npm i -g pm2
pm2 start agent-comm-hub --name agent-comm-hub
pm2 save && pm2 startup # boot persistence
# or the built-in one-shot auto-start (no admin needed)
agent-comm-hub service install # Windows: HKCU Run + hidden VBS launcher
# Linux: systemd --user unit, enabled
agent-comm-hub service uninstallMeasured footprint (Windows / Node 24, idle):
Metric | Value |
Idle CPU | ≈ 0 (event-driven; the only timer is a once-a-minute idle-GC check) |
Memory over an idle Node baseline | ~ +8 MB WorkingSet (the ~100+ MB baseline is the Node runtime itself) |
Disk | None (no database; nothing written besides logs) |
Each online agent adds one SSE keep-alive socket; mailboxes/history are in-memory with configurable caps. Negligible impact.
Programmatic API
import { startHub, DEFAULT_CONFIG } from 'agent-comm-hub'
const hub = startHub({ port: 18764 }, console) // returns { hub, registry, server, mcp, close }
// hub.close() to stopstartHub(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().
Message protocol & identity
{ "id": "uuid", "from": "mavis", "to": "claude", "kind": "chat", "content": "..." }kind:chat|task|notice|ack.taskcontent is{prompt, context?, deliverable?};ackcontent is{status, note?}— both JSON-encoded.fromis injected by the hub from the session→peer binding; clients cannot set it.Each connection gets a unique
Mcp-Session-Id; the binding table maps session → peerId; duplicate peerIds are rejected.Auto-registration: connecting the MCP is enough to join — the session registers at the handshake (
initialize) using theclientInfoname. Same-name connections share one peer id (an agent that opens a new session per chat keeps a stable identity and its sessions share the mailbox).bridge_registerupgrades the id to something readable;bridge_unregisterdetaches (dropping the peer when no other session shares it) and suppresses auto-registration until an explicit register.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).Liveness:
connectedmeans activity withinconnectedWindowMs(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.
Security
Binds to
127.0.0.1by default and has no authentication — do not expose the port publicly without adding a token/proxy layer.Never put credentials in bridge messages (plaintext on loopback).
Peer ids are validated
[A-Za-z0-9._:-]{1,64}; unregistered callers get a clear error.
Development
pnpm install
pnpm typecheck # tsc --noEmit (strict)
pnpm test # test suite (314 checks: 169 smoke + 46 setup + 11 ops + 35 herdr + 33 discover + 20 e2e)
npm run build:admin # admin/ workspace (npm) → single-file assets/admin.html
pnpm run build # esbuild → lib/{cli,index,setup}.js (zero deps)
pnpm pack # build + npm pack (publishing artifact)Desktop GUI
A companion desktop GUI is shipped as a separate npm package: agent-comm-hub-app. It is a standalone Tauri 2 + React app, lives in app/, and depends on the MCP HTTP API rather than on this package's source. It does NOT relax the dependencies: {} constraint of the main package — workspace isolation is enforced via app/pnpm-workspace.yaml.
English | 简体中文 |
|
|
cd app
pnpm install
pnpm tauri:dev # dev with hot reload
pnpm tauri:build # produces NSIS / MSI / dmg / AppImage / deb installersHighlights:
Hub lifecycle in one window: auto-spawn on launch (4-tier PATH fallback), start / stop / restart, live log panel with stderr filter + expandable viewer, and an external-hub reuse mode with health probing
Real-time messaging:
bridge_waitlong-poll keeps the UI live; optimistic send shows your messages instantly;/historymerges hub memory with the SQLite archive (survives hub restarts)Peer conversations (PRD US-2): click any peer to view its full conversation, not just yours; unread badges per peer
Message details: raw JSON view, task prompt/context/deliverable, ack state-machine timeline
Slash commands:
/peers /broadcast /history /clear /help— from the palette or typed directlyMarkdown rendering with rehype-sanitize, multi-peer cc, drag-drop attachments (≤5 MB), virtual scrolling
Theme system: dark / light / system-follow, brand-blue palette, persisted
Frameless window: custom titlebar (drag region, double-click maximize), close dialog with minimize-to-tray / quit / cancel
Hub tools in Settings: install / version / check update / update the hub CLI, one-click
setupto detect local agents and install the SKILL + MCP config, auto-start service installSystem tray with brand logo and status tooltip; i18n (zh-CN default, en-US)
See app/README.md for the full feature list and architecture.
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.
Troubleshooting
Symptom | Cause / fix |
Agent has no | Hub not running — start |
| The peer hasn't registered (or used a different peerId) — check |
| Only appears after an explicit |
| Another live connection holds the id — pick a unique peerId (e.g. |
Port conflict | 18764 is the default; if it is taken, change with |
Chinese garbled in PowerShell clients | Response headers carry |
License
MIT — see LICENSE. Contributions welcome: keep the 314-check suite green (pnpm test) and zero runtime dependencies. Architecture: ARCHITECTURE.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP Server for an Agent Task Marketplace
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server connecting AI agents to non-custodial staking data across 130+ networks.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables AI agents to communicate, coordinate, and collaborate on complex tasks through a local MCP server.3 npm8ISC
- AlicenseNot gradedqualityAmaintenanceMCP server for multi-agent collaboration enabling AI agents to communicate, delegate tasks, and share artifacts across clients and machines with federation support.11 npm1MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that enables AI coding agents to communicate, share state, and coordinate work in real time via MCP tools or REST API.107 npm9MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that enables AI agents to run a deterministic orchestration loop with decomposition, subagent execution, and review feedback across multiple LLM backends.60MIT

