agent-coord-mcp 0.5.3 → 0.7.1
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 +95 -7
- package/dist/server.js +235 -25
- package/dist/server.js.map +1 -1
- package/dist/store.js +50 -1
- package/dist/store.js.map +1 -1
- package/dist/tools.js +53 -2
- package/dist/tools.js.map +1 -1
- package/package.json +4 -3
- package/scripts/coord-pusher.mjs +288 -0
- package/src/server.ts +270 -26
- package/src/store.ts +56 -1
- package/src/tools.ts +67 -1
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# agent-coord-mcp
|
|
2
2
|
|
|
3
|
-
A tiny file-backed [MCP](https://modelcontextprotocol.io) server that puts multiple AI coding agents — and you — into a shared chat room
|
|
3
|
+
A tiny file-backed [MCP](https://modelcontextprotocol.io) server that puts multiple AI coding agents — and you — into a shared chat room. Agents register themselves, DM each other, post to channels (`#general`, plus any they create), broadcast status, and optionally block until a reply arrives. A bundled `coord-chat` TUI lets a human join the same room as a first-class participant.
|
|
4
4
|
|
|
5
|
-
It's an IRC-style backplane for human-and-agent collaboration where everyone — the human, your Claude Code session, a Cursor agent, a worker built on the Agent SDK — is just another row in the same JSONL files. `tail -f ~/agent-coord/room.jsonl` to spectate
|
|
5
|
+
It's an IRC-style backplane for human-and-agent collaboration where everyone — the human, your Claude Code session, a Cursor agent, a worker built on the Agent SDK — is just another row in the same JSONL files. `tail -f ~/agent-coord/room.jsonl` to spectate; run `coord-chat` to participate.
|
|
6
6
|
|
|
7
|
-
> **
|
|
7
|
+
> **State is file-backed.** Coordination happens through `~/agent-coord/` JSONL/JSON. On one machine, every agent shares those files directly. Cross-machine, the same server is reachable over **Streamable HTTP** with a bearer token — remote agents call the same MCP tools over the wire (no NFS/Dropbox file-syncing required).
|
|
8
8
|
>
|
|
9
|
-
> **Works with any MCP client — and across client types.** The server speaks plain MCP
|
|
9
|
+
> **Works with any MCP client — and across client types.** The server speaks plain MCP: stdio for local Claude Code / Cursor / Cline / Zed / custom SDK apps, or Streamable HTTP over the network. A Claude Code session, a Cursor agent, a Python SDK worker on a different host, and a human at `coord-chat` can all share the same room and DM each other.
|
|
10
10
|
>
|
|
11
|
-
> **Real-time push, opt-in.** If an agent is running inside tmux, `join({agentId:"me"})` attaches a tiny daemon that types incoming DMs into its pane within ~1s
|
|
11
|
+
> **Real-time push, opt-in.** If an agent is running inside tmux, `join({agentId:"me"})` attaches a tiny daemon that types incoming DMs (and joined channels) into its pane within ~1s. Cross-machine, `coord-pusher` is the same idea over the wire — see [Remote agents](#remote-agents-streamable-http).
|
|
12
12
|
>
|
|
13
|
-
>
|
|
13
|
+
> **Auth.** Local stdio inherits filesystem permissions (anything that can read your home directory can read the messages). HTTP mode requires a bearer token and binds to `127.0.0.1` by default; expose more broadly only behind TLS (Tailscale / reverse proxy). v0.7.0 adds per-agent token binding via `~/agent-coord/tokens.json` so the bus authenticates *who* the caller is (the `from`/`agentId` fields), not just *that* they're allowed — see [Identity binding](#identity-binding-v070).
|
|
14
14
|
|
|
15
|
-
> **Where this is going.** See [ROADMAP.md](./ROADMAP.md)
|
|
15
|
+
> **Where this is going.** See [ROADMAP.md](./ROADMAP.md). Phase 6 (Remote MCP) shipped in v0.6.0. The Phase 5 IRC layer is parked — IRC is still a good fit for the "human on weechat" audience, but for agents Phase 6's Streamable HTTP is the right answer.
|
|
16
16
|
|
|
17
17
|
## Install
|
|
18
18
|
|
|
@@ -76,6 +76,8 @@ If you're building an agent with the official MCP SDKs (`@modelcontextprotocol/s
|
|
|
76
76
|
| `rename_agent({agentId, newAgentId})` | NICK: migrate registry, inbox, cursor, transport, and channel memberships to a new id, then broadcast a rename notice. |
|
|
77
77
|
| `attach_agent({agentId, tmuxTarget?, includeRoom?, allowlist?, debounceMs?})` | Start the **tmux-push transport** for this agent — spawns `hooks/tmux-pusher.mjs` so peer DMs get typed into the agent's tmux pane in real time. `tmuxTarget` defaults to the MCP server's own `$TMUX_PANE` if it's running inside tmux, so the most common call is just `attach_agent({agentId:"me"})`. Updates `list_agents` to show `transport: "tmux-push"`. See [tmux push](#active-push-via-tmux-any-cli-agent). |
|
|
78
78
|
| `detach_agent({agentId})` | Stop the tmux-push transport: kill the pusher and clear the transport marker. |
|
|
79
|
+
| `report_transport({agentId, transport, host?, tmuxTarget?, since?})` | Publish a transport marker for an agent. Used by the **remote** pusher (`coord-pusher`, see [Remote agents](#remote-agents-streamable-http)) to surface itself in `list_agents`. Local tmux push uses `attach_agent` instead. |
|
|
80
|
+
| `clear_transport({agentId})` | Idempotent delete of an agent's transport marker — wire-callable counterpart to `detach_agent` for the remote pusher. Removes the marker only; nothing local to kill. |
|
|
79
81
|
| `prune({olderThanDays?, removeOrphanInboxes?, dryRun?})` | Trim room/status/inbox JSONL to entries newer than N days (default 7). Removes inbox files for agents no longer in the registry. Pass `dryRun:true` to preview. |
|
|
80
82
|
|
|
81
83
|
## First session checklist
|
|
@@ -291,6 +293,92 @@ Under the hood: [`hooks/tmux-pusher.mjs`](./hooks/tmux-pusher.mjs) is the daemon
|
|
|
291
293
|
- Untrusted peer messages become real prompts with full agent privileges. Use `--allowlist` to restrict who can talk to a given agent; the pusher also refuses anything starting with `/` to block injected slash commands.
|
|
292
294
|
- Bursts get coalesced (1s default) into a single paste so 5 rapid DMs become one prompt rather than five.
|
|
293
295
|
|
|
296
|
+
## Remote agents (Streamable HTTP)
|
|
297
|
+
|
|
298
|
+
Same MCP server, same tools — exposed over the network with a bearer token. Lets agents on other machines join the same bus as if they were local. Local stdio is unchanged; HTTP is opt-in via env.
|
|
299
|
+
|
|
300
|
+
### Run the server as an HTTP daemon
|
|
301
|
+
|
|
302
|
+
```sh
|
|
303
|
+
AGENT_COORD_HTTP_PORT=8765 \
|
|
304
|
+
AGENT_COORD_TOKEN=$(openssl rand -hex 24) \
|
|
305
|
+
AGENT_COORD_DIR=~/agent-coord \
|
|
306
|
+
agent-coord-mcp
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Defaults to `127.0.0.1`. To bind to a LAN address (Tailscale, WireGuard, etc.) set `AGENT_COORD_BIND=10.x.y.z`; the process logs a warning if it binds to anything non-loopback so you don't accidentally serve unauthenticated traffic. `GET /healthz` is unauthenticated (for reverse-proxy probes); everything else requires `Authorization: Bearer <AGENT_COORD_TOKEN>`. TLS is out of scope — front with Caddy/nginx, or skip TLS entirely on a private overlay network.
|
|
310
|
+
|
|
311
|
+
The server can run as a long-lived daemon on one machine (the "host") while local agents on that host keep using stdio per-session; the two modes don't conflict — they're separate processes.
|
|
312
|
+
|
|
313
|
+
### Point a Claude Code session at the remote server
|
|
314
|
+
|
|
315
|
+
In `~/.claude.json`:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"mcpServers": {
|
|
320
|
+
"agent-coord": {
|
|
321
|
+
"type": "http",
|
|
322
|
+
"url": "http://host:8765/mcp",
|
|
323
|
+
"headers": { "Authorization": "Bearer <AGENT_COORD_TOKEN>" }
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Then `join({agentId:"me"})` and call any tool exactly as you would locally. `send_message`, `read_messages`, `wait_for_message`, `list_rooms`, `join_room`, etc. all work identically.
|
|
330
|
+
|
|
331
|
+
### `coord-pusher` — real-time push, cross-machine
|
|
332
|
+
|
|
333
|
+
The local `attach_agent` / `tmux-pusher` path can't reach across machines (it needs filesystem access to the inbox + a local tmux pane). The remote equivalent is **`coord-pusher`**: a daemon you run **on each remote machine** that consumes the bus over MCP and pastes incoming peer messages into the local tmux pane. Same paste pipeline as `tmux-pusher`; the only thing that changes is the data source (RPC instead of files).
|
|
334
|
+
|
|
335
|
+
```sh
|
|
336
|
+
coord-pusher --server http://host:8765/mcp \
|
|
337
|
+
--token <AGENT_COORD_TOKEN> \
|
|
338
|
+
--agent me \
|
|
339
|
+
--tmux $TMUX_PANE
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Or via env (`AGENT_COORD_SERVER` / `AGENT_COORD_TOKEN` / `AGENT_COORD_ID` / `AGENT_COORD_TMUX_TARGET`). Flags: `--no-room` (DMs only), `--allowlist a,b` (drop messages from other peers), `--debounce-ms 1000`, `--refresh-ms 30000` (how often to re-check channel membership). The pusher registers + publishes a `tmux-push-remote` transport marker (so `list_agents` shows it attached), heartbeats once a minute, and clears the marker on `SIGINT`/`SIGTERM`. Run it under your supervisor of choice (systemd / launchd / a tmux session of its own).
|
|
343
|
+
|
|
344
|
+
### Identity binding (v0.7.0 / TOFU in v0.7.1)
|
|
345
|
+
|
|
346
|
+
By default the bearer authenticates the *channel* — any session can post under any `from`/`agentId`. The bus closes the spoof gap in two layers:
|
|
347
|
+
|
|
348
|
+
**v0.7.1 — Trust-on-first-use (zero config).** Each session is initially unbound. The first tool call that carries an `agentId`/`from` field becomes the session's bound identity; subsequent calls in that session cannot switch to a different name. Mid-session identity switching (the PR #45 spoof shape) is rejected:
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
identity bound to 'alice'; rejected attempt to act as 'bob'
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
TOFU stops mid-session switching. It does *not* stop a fresh session claiming an unbound name — for that, layer one of the stronger configs below.
|
|
355
|
+
|
|
356
|
+
**v0.7.0 — Pre-binding (when you want sessions identified at connect-time).** Drop a `~/agent-coord/tokens.json` (mode 600) mapping agentId → bearer:
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{ "alice": "tk_$(openssl rand -hex 24)",
|
|
360
|
+
"bob": "tk_$(openssl rand -hex 24)" }
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Each remote client uses its agent's token in the `Authorization: Bearer …` header. The server reverse-looks-up the bearer to bind the session and enforces the binding on every tool that takes a caller identity (`from` on `send_message`, `agentId` everywhere else). Renames rotate the token entry atomically so the same bearer keeps working after a NICK. `kill -HUP <pid>` reloads the file without a restart.
|
|
364
|
+
|
|
365
|
+
**For local stdio agents**, set `AGENT_COORD_BOUND_AGENT=<your-id>` in the MCP launch env (the `env` block in `~/.claude.json`) to bind the spawned subprocess to that identity. Without it, stdio runs in advisory mode (current behavior — a startup warning is logged).
|
|
366
|
+
|
|
367
|
+
Backward-compat: if `tokens.json` is absent, the legacy single shared `AGENT_COORD_TOKEN` still works as channel-only auth (the session falls back to TOFU). The server refuses to start in HTTP mode with no auth configured at all. Malformed `tokens.json` is fatal.
|
|
368
|
+
|
|
369
|
+
**Posture summary:**
|
|
370
|
+
|
|
371
|
+
| Config | Mid-session switch | Fresh-session impersonation |
|
|
372
|
+
|---|---|---|
|
|
373
|
+
| None (default after v0.7.1) | ❌ blocked (TOFU) | ⚠️ possible (no pre-binding) |
|
|
374
|
+
| `AGENT_COORD_BOUND_AGENT` env | ❌ blocked (pre-bound) | ❌ blocked (env is process-local) |
|
|
375
|
+
| `tokens.json` | ❌ blocked (pre-bound) | ❌ blocked (bearer ↔ id) |
|
|
376
|
+
|
|
377
|
+
### Auth posture, briefly
|
|
378
|
+
|
|
379
|
+
- Threat model: misbehaving / buggy / compromised same-LAN cooperator can no longer assert another agent's identity. Not a hostile-attacker model (TLS + per-message signing is a separate, larger task).
|
|
380
|
+
- Don't bind to a public address without TLS. The server prints a warning if you do anyway.
|
|
381
|
+
|
|
294
382
|
### Other clients
|
|
295
383
|
|
|
296
384
|
The script itself is plain Node — no Claude-specific deps — so it ports anywhere you can run a shell command around the agent loop. The MCP protocol doesn't standardize client-side hooks, so the wiring varies:
|
package/dist/server.js
CHANGED
|
@@ -1,40 +1,250 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { createServer } from "node:http";
|
|
2
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
7
|
+
import { ensureDirs, readTokenMapSync } from "./store.js";
|
|
8
|
+
import { attachAgentSchema, attachAgentTool, clearTransportSchema, clearTransportTool, detachAgentSchema, detachAgentTool, heartbeatSchema, heartbeatTool, joinRoomSchema, joinRoomTool, joinSchema, joinTool, leaveRoomSchema, leaveRoomTool, listAgentsSchema, listAgentsTool, listRoomsSchema, listRoomsTool, postStatusSchema, postStatusTool, pruneSchema, pruneTool, readMessagesSchema, readMessagesTool, registerSchema, registerTool, renameAgentSchema, renameAgentTool, reportTransportSchema, reportTransportTool, sendMessageSchema, sendMessageTool, setRoomMotdSchema, setRoomMotdTool, setRoomTopicSchema, setRoomTopicTool, statusSchema, statusTool, unregisterSchema, unregisterTool, waitForMessageSchema, waitForMessageTool, } from "./tools.js";
|
|
6
9
|
function jsonResult(data) {
|
|
7
10
|
return {
|
|
8
11
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
9
12
|
};
|
|
10
13
|
}
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
// Build a fully-configured McpServer with every tool registered. Returns a
|
|
15
|
+
// fresh instance each call — in HTTP mode we need one server per session so
|
|
16
|
+
// transports don't share Protocol state.
|
|
17
|
+
//
|
|
18
|
+
// Identity binding (v0.7.0 + TOFU in v0.7.1):
|
|
19
|
+
// - `initialBound` (when set) pre-binds the session — from a bearer token
|
|
20
|
+
// (HTTP/tokens.json) or AGENT_COORD_BOUND_AGENT env (stdio).
|
|
21
|
+
// - Otherwise the session starts unbound. The first tool call that carries
|
|
22
|
+
// an agentId/from field captures that value as the session's binding —
|
|
23
|
+
// trust-on-first-use. Subsequent calls must match; mid-session identity
|
|
24
|
+
// switching (the PR #45 spoof shape) is rejected.
|
|
25
|
+
// - rename_agent updates the binding to the new id on success so the
|
|
26
|
+
// renamed session keeps working.
|
|
27
|
+
function buildServer(initialBound) {
|
|
28
|
+
let bound = initialBound;
|
|
29
|
+
// Gate every tool that takes a caller identity. `field: null` (list_agents,
|
|
30
|
+
// list_rooms, prune) bypasses the check entirely.
|
|
31
|
+
function gate(field, handler) {
|
|
32
|
+
return async (args) => {
|
|
33
|
+
if (field) {
|
|
34
|
+
const claimed = args[field];
|
|
35
|
+
if (typeof claimed === "string") {
|
|
36
|
+
if (bound === undefined) {
|
|
37
|
+
bound = claimed; // TOFU: first claim wins, then sticky.
|
|
38
|
+
}
|
|
39
|
+
else if (bound !== claimed) {
|
|
40
|
+
throw new Error(`identity bound to '${bound}'; rejected attempt to act as '${claimed}'`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return jsonResult(await handler(args));
|
|
45
|
+
};
|
|
46
|
+
}
|
|
13
47
|
const server = new McpServer({
|
|
14
48
|
name: "agent-coord",
|
|
15
49
|
version: "0.1.0",
|
|
16
50
|
});
|
|
17
|
-
server.tool("join", "Recommended session-start call. Does register + auto-attach (if running inside tmux) + read inbox in one round-trip. Pass attach=false to skip the transport, attach={...overrides} to customize, or omit it to let the server auto-detect $TMUX_PANE. Returns the registration, attach result, any unread inbox messages, and the default channel's topic + MOTD (room rules) so you see them on connect.", joinSchema,
|
|
18
|
-
server.tool("register", "Register this agent in the shared registry. Lower-level than `join` — does not attach a transport or drain the inbox. Prefer `join` unless you need explicit control.", registerSchema,
|
|
19
|
-
server.tool("unregister", "Tear down this agent: detach any attached transport (kills the pusher) and remove the registry entry. Clean shutdown counterpart to `join`.", unregisterSchema,
|
|
20
|
-
server.tool("status", "Introspect this agent's coord state: registration, attached transport, inbox depth and unread count, and whether this MCP server is running inside tmux. Useful for debugging 'why isn't my DM landing'.", statusSchema,
|
|
21
|
-
server.tool("heartbeat", "Refresh this agent's lastHeartbeat timestamp.", heartbeatSchema,
|
|
22
|
-
server.tool("list_agents", "List all known agents and whether they appear online (heartbeat <5min).", listAgentsSchema,
|
|
23
|
-
server.tool("send_message", "Send a message. If 'to' is set, goes to that agent's inbox (DM); otherwise to a channel — pass 'room' (e.g. 'seo' or '#seo') to target a specific channel, or omit it for the default 'general' channel.", sendMessageSchema,
|
|
24
|
-
server.tool("read_messages", "Read new messages from inbox|room|status. For source='room', pass 'room' to read a specific channel (default 'general'). Advances the per-channel cursor unless peek=true.", readMessagesSchema,
|
|
25
|
-
server.tool("post_status", "Append a status broadcast to the shared status stream.", postStatusSchema,
|
|
26
|
-
server.tool("prune", "Trim room/status/inbox JSONL to entries newer than `olderThanDays` (default 7). Removes inbox files for agents no longer in the registry unless removeOrphanInboxes=false. Pass dryRun=true to preview.", pruneSchema,
|
|
27
|
-
server.tool("wait_for_message", "Block (max 60s) until a new message appears on the given source, then return it. For source='room', pass 'room' to wait on a specific channel (default 'general').", waitForMessageSchema,
|
|
28
|
-
server.tool("list_rooms", "List all channels with their topic, MOTD (room rules), members, message count, and last activity.", listRoomsSchema,
|
|
29
|
-
server.tool("join_room", "Join a channel (creating it if new). Adds this agent to the channel's membership so the notification hooks push its messages, and returns the channel's topic, MOTD, members, and unread count.", joinRoomSchema,
|
|
30
|
-
server.tool("leave_room", "Leave a channel — removes this agent from its membership. Cannot leave the default 'general' channel.", leaveRoomSchema,
|
|
31
|
-
server.tool("set_room_topic", "Set a channel's topic (a short one-line description). Posts a system notice to the channel.", setRoomTopicSchema,
|
|
32
|
-
server.tool("set_room_motd", "Set a channel's MOTD / room rules (shown to agents on join). Posts a system notice to the channel.", setRoomMotdSchema,
|
|
33
|
-
server.tool("rename_agent", "Rename an agent (NICK): migrates its registry entry, inbox, cursor, and channel memberships to the new id, then broadcasts a rename notice to its channels. If a live tmux-push transport is attached it is detached first (the pusher is bound to the old id) — re-attach as the new id (join/attach_agent) to restore real-time delivery; the response sets detachedTransport + a warning when this happens.", renameAgentSchema,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
server.tool("join", "Recommended session-start call. Does register + auto-attach (if running inside tmux) + read inbox in one round-trip. Pass attach=false to skip the transport, attach={...overrides} to customize, or omit it to let the server auto-detect $TMUX_PANE. Returns the registration, attach result, any unread inbox messages, and the default channel's topic + MOTD (room rules) so you see them on connect.", joinSchema, gate("agentId", joinTool));
|
|
52
|
+
server.tool("register", "Register this agent in the shared registry. Lower-level than `join` — does not attach a transport or drain the inbox. Prefer `join` unless you need explicit control.", registerSchema, gate("agentId", registerTool));
|
|
53
|
+
server.tool("unregister", "Tear down this agent: detach any attached transport (kills the pusher) and remove the registry entry. Clean shutdown counterpart to `join`.", unregisterSchema, gate("agentId", unregisterTool));
|
|
54
|
+
server.tool("status", "Introspect this agent's coord state: registration, attached transport, inbox depth and unread count, and whether this MCP server is running inside tmux. Useful for debugging 'why isn't my DM landing'.", statusSchema, gate("agentId", statusTool));
|
|
55
|
+
server.tool("heartbeat", "Refresh this agent's lastHeartbeat timestamp.", heartbeatSchema, gate("agentId", heartbeatTool));
|
|
56
|
+
server.tool("list_agents", "List all known agents and whether they appear online (heartbeat <5min).", listAgentsSchema, gate(null, listAgentsTool));
|
|
57
|
+
server.tool("send_message", "Send a message. If 'to' is set, goes to that agent's inbox (DM); otherwise to a channel — pass 'room' (e.g. 'seo' or '#seo') to target a specific channel, or omit it for the default 'general' channel. The 'from' field is enforced against the session's bound identity when binding is configured.", sendMessageSchema, gate("from", sendMessageTool));
|
|
58
|
+
server.tool("read_messages", "Read new messages from inbox|room|status. For source='room', pass 'room' to read a specific channel (default 'general'). Advances the per-channel cursor unless peek=true.", readMessagesSchema, gate("agentId", readMessagesTool));
|
|
59
|
+
server.tool("post_status", "Append a status broadcast to the shared status stream.", postStatusSchema, gate("agentId", postStatusTool));
|
|
60
|
+
server.tool("prune", "Trim room/status/inbox JSONL to entries newer than `olderThanDays` (default 7). Removes inbox files for agents no longer in the registry unless removeOrphanInboxes=false. Pass dryRun=true to preview.", pruneSchema, gate(null, pruneTool));
|
|
61
|
+
server.tool("wait_for_message", "Block (max 60s) until a new message appears on the given source, then return it. For source='room', pass 'room' to wait on a specific channel (default 'general').", waitForMessageSchema, gate("agentId", waitForMessageTool));
|
|
62
|
+
server.tool("list_rooms", "List all channels with their topic, MOTD (room rules), members, message count, and last activity.", listRoomsSchema, gate(null, listRoomsTool));
|
|
63
|
+
server.tool("join_room", "Join a channel (creating it if new). Adds this agent to the channel's membership so the notification hooks push its messages, and returns the channel's topic, MOTD, members, and unread count.", joinRoomSchema, gate("agentId", joinRoomTool));
|
|
64
|
+
server.tool("leave_room", "Leave a channel — removes this agent from its membership. Cannot leave the default 'general' channel.", leaveRoomSchema, gate("agentId", leaveRoomTool));
|
|
65
|
+
server.tool("set_room_topic", "Set a channel's topic (a short one-line description). Posts a system notice to the channel.", setRoomTopicSchema, gate("agentId", setRoomTopicTool));
|
|
66
|
+
server.tool("set_room_motd", "Set a channel's MOTD / room rules (shown to agents on join). Posts a system notice to the channel.", setRoomMotdSchema, gate("agentId", setRoomMotdTool));
|
|
67
|
+
server.tool("rename_agent", "Rename an agent (NICK): migrates its registry entry, inbox, cursor, and channel memberships to the new id, then broadcasts a rename notice to its channels. When tokens.json identity binding is on, the caller's bearer token is atomically rotated to the new id so the same session keeps authenticating after rename. If a live tmux-push transport is attached it is detached first (the pusher is bound to the old id) — re-attach as the new id (join/attach_agent) to restore real-time delivery; the response sets detachedTransport + a warning when this happens.", renameAgentSchema,
|
|
68
|
+
// Special: after a successful rename we update the session's bound id
|
|
69
|
+
// too, so the same session can keep operating under the new name without
|
|
70
|
+
// the next call being rejected as a binding mismatch.
|
|
71
|
+
async (args) => {
|
|
72
|
+
const claimed = args.agentId;
|
|
73
|
+
if (typeof claimed === "string") {
|
|
74
|
+
if (bound === undefined)
|
|
75
|
+
bound = claimed;
|
|
76
|
+
else if (bound !== claimed) {
|
|
77
|
+
throw new Error(`identity bound to '${bound}'; rejected attempt to act as '${claimed}'`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const result = await renameAgentTool(args);
|
|
81
|
+
if (result && typeof result === "object" && result.ok === true) {
|
|
82
|
+
const to = result.to;
|
|
83
|
+
if (typeof to === "string")
|
|
84
|
+
bound = to;
|
|
85
|
+
}
|
|
86
|
+
return jsonResult(result);
|
|
87
|
+
});
|
|
88
|
+
server.tool("attach_agent", "Start the tmux-push transport for an agent: spawns hooks/tmux-pusher.mjs as a background process so peer DMs (and optionally room messages) get typed into the agent's tmux pane in real time. tmuxTarget defaults to the MCP server's own $TMUX_PANE if this server is running inside tmux. allowlist restricts which peer agentIds can push. Updates list_agents to show transport=tmux-push.", attachAgentSchema, gate("agentId", attachAgentTool));
|
|
89
|
+
server.tool("detach_agent", "Stop the tmux-push transport for an agent: kills the pusher process and clears the transport marker.", detachAgentSchema, gate("agentId", detachAgentTool));
|
|
90
|
+
server.tool("report_transport", "Publish a transport marker for an agent (used by the remote tmux pusher, scripts/coord-pusher.mjs, to surface itself in list_agents). Set transport='tmux-push-remote' and optionally host/tmuxTarget. Liveness for remote markers is heartbeat-based — keep calling heartbeat or this marker gets GC'd after staleness.", reportTransportSchema, gate("agentId", reportTransportTool));
|
|
91
|
+
server.tool("clear_transport", "Idempotent delete of an agent's transport marker. The wire-callable counterpart to detach_agent for remote pushers: it only removes the marker — there's no local process to kill.", clearTransportSchema, gate("agentId", clearTransportTool));
|
|
92
|
+
return server;
|
|
93
|
+
}
|
|
94
|
+
// Lazy-loaded token map for HTTP identity binding. Hot-reloaded on SIGHUP so
|
|
95
|
+
// operators can rotate / add agents without a server restart.
|
|
96
|
+
let tokenMap = null;
|
|
97
|
+
function loadTokenMap(initial) {
|
|
98
|
+
try {
|
|
99
|
+
tokenMap = readTokenMapSync();
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
// On initial load a bad file is fatal — refuse to start in a known-bad
|
|
103
|
+
// auth state. On SIGHUP, log and keep the previous (valid) map.
|
|
104
|
+
if (initial) {
|
|
105
|
+
console.error(e.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
console.error(`[agent-coord-mcp] SIGHUP: ${e.message} (keeping previous map)`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (!initial) {
|
|
112
|
+
console.error(`[agent-coord-mcp] SIGHUP: token map reloaded (${tokenMap?.size ?? 0} agents)`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function main() {
|
|
116
|
+
ensureDirs();
|
|
117
|
+
loadTokenMap(true);
|
|
118
|
+
process.on("SIGHUP", () => loadTokenMap(false));
|
|
119
|
+
// Transport selector. AGENT_COORD_HTTP_PORT set → run as a long-lived HTTP
|
|
120
|
+
// daemon (Streamable HTTP transport + bearer-token auth). Otherwise the
|
|
121
|
+
// historical stdio behavior (per-client subprocess spawned by Claude Code).
|
|
122
|
+
const httpPort = process.env.AGENT_COORD_HTTP_PORT;
|
|
123
|
+
if (httpPort) {
|
|
124
|
+
await startHttp(parseInt(httpPort, 10));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const boundAgent = process.env.AGENT_COORD_BOUND_AGENT;
|
|
128
|
+
if (!boundAgent) {
|
|
129
|
+
console.error("[agent-coord-mcp] bus identity unbound (stdio) — falling back to TOFU: the " +
|
|
130
|
+
"first tool call's agentId/from claim becomes this session's bound identity " +
|
|
131
|
+
"and subsequent calls cannot switch. For stricter pre-binding, set " +
|
|
132
|
+
"AGENT_COORD_BOUND_AGENT=<your-id> in the MCP launch env.");
|
|
133
|
+
}
|
|
134
|
+
const server = buildServer(boundAgent);
|
|
135
|
+
const transport = new StdioServerTransport();
|
|
136
|
+
await server.connect(transport);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async function startHttp(port) {
|
|
140
|
+
const sharedToken = process.env.AGENT_COORD_TOKEN;
|
|
141
|
+
const bound = tokenMap !== null;
|
|
142
|
+
if (!bound && !sharedToken) {
|
|
143
|
+
console.error("[agent-coord-mcp] HTTP mode needs auth: either set AGENT_COORD_TOKEN (legacy " +
|
|
144
|
+
"shared bearer, advisory identity) or create ~/agent-coord/tokens.json (per-agent " +
|
|
145
|
+
"tokens, enforced identity). Refusing to start an unauthenticated network listener.");
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
if (bound && sharedToken) {
|
|
149
|
+
console.error("[agent-coord-mcp] note: tokens.json is present — AGENT_COORD_TOKEN is ignored " +
|
|
150
|
+
"(per-agent tokens take precedence).");
|
|
151
|
+
}
|
|
152
|
+
if (!bound) {
|
|
153
|
+
console.error("[agent-coord-mcp] bus identity unbound (HTTP) — shared bearer auths the channel; " +
|
|
154
|
+
"per-session identity falls back to TOFU (the first agentId/from claim becomes " +
|
|
155
|
+
"the session's bound id, can't switch mid-stream). Create ~/agent-coord/tokens.json " +
|
|
156
|
+
"to pre-bind sessions to identities at connect time.");
|
|
157
|
+
}
|
|
158
|
+
const bindAddr = process.env.AGENT_COORD_BIND ?? "127.0.0.1";
|
|
159
|
+
const sharedExpected = sharedToken ? `Bearer ${sharedToken}` : null;
|
|
160
|
+
// One transport+server pair per client session. The SDK exposes session
|
|
161
|
+
// affinity via the `mcp-session-id` header: a new request without it is
|
|
162
|
+
// an init (create new pair); follow-ups carry the id (look up the pair).
|
|
163
|
+
// We cannot share one stateful transport across clients (it errors with
|
|
164
|
+
// "Server already initialized"), and stateless mode rejects reuse.
|
|
165
|
+
const sessions = new Map();
|
|
166
|
+
async function makeSessionTransport(boundAgent) {
|
|
167
|
+
// `let` + explicit type lets the SDK callbacks close over the binding
|
|
168
|
+
// before it's assigned — they only fire after construction completes.
|
|
169
|
+
let transport;
|
|
170
|
+
transport = new StreamableHTTPServerTransport({
|
|
171
|
+
sessionIdGenerator: () => randomUUID(),
|
|
172
|
+
onsessioninitialized: (id) => { sessions.set(id, transport); },
|
|
173
|
+
});
|
|
174
|
+
transport.onclose = () => {
|
|
175
|
+
if (transport.sessionId)
|
|
176
|
+
sessions.delete(transport.sessionId);
|
|
177
|
+
};
|
|
178
|
+
const server = buildServer(boundAgent);
|
|
179
|
+
await server.connect(transport);
|
|
180
|
+
return transport;
|
|
181
|
+
}
|
|
182
|
+
// Reverse-lookup: extract bearer from header, map → bound agent. Returns
|
|
183
|
+
// undefined if no map is configured (advisory mode); throws-like return of
|
|
184
|
+
// null if the bearer doesn't match any known agent (caller responds 401).
|
|
185
|
+
function resolveBoundAgent(authHeader) {
|
|
186
|
+
if (!authHeader || !authHeader.startsWith("Bearer "))
|
|
187
|
+
return { ok: false };
|
|
188
|
+
const bearer = authHeader.slice("Bearer ".length);
|
|
189
|
+
if (tokenMap) {
|
|
190
|
+
const agent = tokenMap.get(bearer);
|
|
191
|
+
return agent ? { ok: true, agent } : { ok: false };
|
|
192
|
+
}
|
|
193
|
+
// Advisory mode: only check the shared bearer matches.
|
|
194
|
+
return sharedExpected && authHeader === sharedExpected ? { ok: true } : { ok: false };
|
|
195
|
+
}
|
|
196
|
+
const http = createServer(async (req, res) => {
|
|
197
|
+
try {
|
|
198
|
+
// Unauthenticated liveness probe so reverse proxies / orchestrators can
|
|
199
|
+
// health-check without needing a credential.
|
|
200
|
+
const url = req.url ?? "/";
|
|
201
|
+
if (req.method === "GET" && (url === "/healthz" || url === "/health")) {
|
|
202
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
203
|
+
res.end("ok\n");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Auth gate. In bound mode the bearer also tells us *which* agent the
|
|
207
|
+
// session is bound to; in advisory mode it just gates entry. Constant-
|
|
208
|
+
// time compare isn't worthwhile here — the attacker model for the
|
|
209
|
+
// LAN/personal case is "someone on the same network" who can already
|
|
210
|
+
// observe traffic; TLS termination is the answer to that.
|
|
211
|
+
const resolved = resolveBoundAgent(req.headers.authorization);
|
|
212
|
+
if (!resolved.ok) {
|
|
213
|
+
res.writeHead(401, { "Content-Type": "text/plain", "WWW-Authenticate": "Bearer" });
|
|
214
|
+
res.end("unauthorized\n");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// Session routing. Existing session id → reuse its transport; new client
|
|
218
|
+
// (no id, POST init) → mint a fresh transport+server pair bound to the
|
|
219
|
+
// bearer's agent; anything else is a protocol error.
|
|
220
|
+
const sid = req.headers["mcp-session-id"];
|
|
221
|
+
let transport = typeof sid === "string" ? sessions.get(sid) : undefined;
|
|
222
|
+
if (!transport) {
|
|
223
|
+
if (req.method !== "POST") {
|
|
224
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
225
|
+
res.end("missing or unknown mcp-session-id\n");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
transport = await makeSessionTransport(resolved.agent);
|
|
229
|
+
}
|
|
230
|
+
await transport.handleRequest(req, res);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
console.error("[agent-coord-mcp] http request failed:", err);
|
|
234
|
+
if (!res.headersSent) {
|
|
235
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
236
|
+
res.end("internal error\n");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
http.listen(port, bindAddr, () => {
|
|
241
|
+
const mode = bound ? `pre-bound (${tokenMap?.size ?? 0} agents)` : "TOFU";
|
|
242
|
+
console.error(`[agent-coord-mcp] http listening on ${bindAddr}:${port} — identity ${mode}`);
|
|
243
|
+
if (bindAddr !== "127.0.0.1" && bindAddr !== "localhost") {
|
|
244
|
+
console.error(`[agent-coord-mcp] WARNING: bound to ${bindAddr} without TLS. Front with a TLS reverse proxy ` +
|
|
245
|
+
`(or restrict to a private network e.g. Tailscale/WireGuard) before exposing publicly.`);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
38
248
|
}
|
|
39
249
|
main().catch((err) => {
|
|
40
250
|
console.error("[agent-coord-mcp] fatal:", err);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { promises as fs, existsSync, mkdirSync } from "node:fs";
|
|
1
|
+
import { promises as fs, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import lockfile from "proper-lockfile";
|
|
@@ -20,6 +20,13 @@ export const LOG_DIR = path.join(ROOT, "logs");
|
|
|
20
20
|
export const ROOMS_DIR = path.join(ROOT, "rooms");
|
|
21
21
|
export const ROOMS_FILE = path.join(ROOT, "rooms.json");
|
|
22
22
|
export const DEFAULT_ROOM = "general";
|
|
23
|
+
// Per-agent token map for identity-bound bus auth (v0.7.0). Shape on disk:
|
|
24
|
+
// { "alice": "tk_<random-secret>", "bob": "tk_<another-secret>" }
|
|
25
|
+
// HTTP transport reverse-looks-up the bearer to bind the session to an
|
|
26
|
+
// agentId, then enforces that bound id against every tool call's
|
|
27
|
+
// from/agentId field. Absent → advisory mode (legacy behaviour, with a
|
|
28
|
+
// startup warning). Should be mode 600; operator-managed.
|
|
29
|
+
export const TOKENS_FILE = path.join(ROOT, "tokens.json");
|
|
23
30
|
export function ensureDirs() {
|
|
24
31
|
for (const d of [ROOT, INBOX_DIR, CURSOR_DIR, TRANSPORT_DIR, PID_DIR, LOG_DIR, ROOMS_DIR]) {
|
|
25
32
|
if (!existsSync(d))
|
|
@@ -30,6 +37,48 @@ export function ensureDirs() {
|
|
|
30
37
|
mkdirSync(path.dirname(f), { recursive: true });
|
|
31
38
|
}
|
|
32
39
|
}
|
|
40
|
+
// Synchronous, deliberate. The result feeds the server's bearer→agent
|
|
41
|
+
// reverse-lookup map; we want startup to fail loudly on a malformed file
|
|
42
|
+
// rather than silently degrade to advisory mode. Returns null if the file
|
|
43
|
+
// is absent (operator hasn't configured binding yet).
|
|
44
|
+
export function readTokenMapSync() {
|
|
45
|
+
if (!existsSync(TOKENS_FILE))
|
|
46
|
+
return null;
|
|
47
|
+
const raw = readFileSync(TOKENS_FILE, "utf8");
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
throw new Error(`[agent-coord-mcp] ${TOKENS_FILE} is not valid JSON: ${e.message}. ` +
|
|
54
|
+
`Fix or remove the file (the bus refuses to start with a broken token map).`);
|
|
55
|
+
}
|
|
56
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
57
|
+
throw new Error(`[agent-coord-mcp] ${TOKENS_FILE} must be a JSON object mapping agentId → token.`);
|
|
58
|
+
}
|
|
59
|
+
const out = new Map();
|
|
60
|
+
for (const [agentId, token] of Object.entries(parsed)) {
|
|
61
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
62
|
+
throw new Error(`[agent-coord-mcp] ${TOKENS_FILE}: agent "${agentId}" has a non-string/empty token.`);
|
|
63
|
+
}
|
|
64
|
+
out.set(token, agentId);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
// Atomically rotate the token entry for an agent rename (used by
|
|
69
|
+
// rename_agent so the same bearer continues to authenticate the renamed
|
|
70
|
+
// identity). No-op if the file is absent or the old id isn't in the map.
|
|
71
|
+
export async function rotateAgentToken(oldAgentId, newAgentId) {
|
|
72
|
+
if (!existsSync(TOKENS_FILE))
|
|
73
|
+
return;
|
|
74
|
+
await updateJson(TOKENS_FILE, {}, (current) => {
|
|
75
|
+
if (current[oldAgentId] !== undefined) {
|
|
76
|
+
current[newAgentId] = current[oldAgentId];
|
|
77
|
+
delete current[oldAgentId];
|
|
78
|
+
}
|
|
79
|
+
return current;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
33
82
|
// Normalize a channel name: strip leading '#', lowercase, restrict to a safe
|
|
34
83
|
// charset, empty → the default channel. Display layers re-add the '#'.
|
|
35
84
|
export function normalizeRoom(name) {
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|