1. Conduid
  2. Files
  3. Agent Coord
MCP server · Files

Agent Coord

Machine-wide coordination layer so multiple AI coding agents (Claude Code, Codex, ...) don't step on each other: shared presence, self-healing file locks, a universal git commit guard, agent-to-agent messaging, and duplicate-work detection.

37Low

Scored 28 days ago · breakdown

About Agent Coord

Agent Coord is an MCP server in the Files category: machine-wide coordination layer so multiple AI coding agents (Claude Code, Codex, ...) don't step on each other: shared presence, self-healing file locks, a universal git commit guard, agent-to-agent messaging, and duplicate-work detection.

Install

Claude Code
claude mcp add agent-coord -- npx -y agent-coord-mcp
npx
npx -y agent-coord-mcp

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Tools (34)

attach_agentStart 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

Parameters not published.

clear_transportIdempotent delete of an agent

Parameters not published.

delete_roomPermanently delete a channel: removes it from the registry, deletes its JSONL file, and clears all agent cursor offsets for that channel. Refuses if agents are still joined unless force=true. Cannot delete the default

Parameters not published.

detach_agentStop the tmux-push transport for an agent: kills the pusher process and clears the transport marker.

Parameters not published.

doctorBus-wide health check: inspects the whole state dir and reports drift, leaks, and corruption (orphan transport markers / memberships / inboxes, cursor offsets past EOF, malformed JSONL, stale agents, oversized files, stale locks, channel/registry mismatches, environment). Read-only by default; pass fix=true to apply the safe, reversible repairs (malformed-line rewrites are backed up to .bak first). A clean report (healthy=true) means the bus is internally consistent.

Parameters not published.

export_workRender a project

Parameters not published.

force_unregisterAdmin eviction: unregisters any agent by targetAgentId regardless of the caller

Parameters not published.

heartbeatRefresh this agent

Parameters not published.

import_workRead a project

Parameters not published.

joinRecommended 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

Parameters not published.

Show all 34 tools
join_roomJoin a channel (creating it if new). Adds this agent to the channel

Parameters not published.

leave_roomLeave a channel — removes this agent from its membership. Cannot leave the default

Parameters not published.

list_agentsList all known agents and whether they appear online (heartbeat <5min).

Parameters not published.

list_roomsList all channels with their topic, MOTD (room rules), members, message count, and last activity.

Parameters not published.

list_scopesRead the declared write scopes for managed documents (~/agent-coord/scopes.json). Call it with

Parameters not published.

list_workQuery a project

Parameters not published.

pingLiveness probe for another agent, answered entirely from server-side state (registry entry, transport marker, pusher pid, tmux pane) — it never touches the target

Parameters not published.

post_statusAppend a status broadcast to the shared status stream.

Parameters not published.

pruneTrim room/status/inbox JSONL to entries newer than `olderThanDays` (default 7); kind=

Parameters not published.

quitClean shutdown: unregister this agent (detach transport, leave rooms, remove registry entry) then exit the MCP process. Only callable by the session

Parameters not published.

read_messagesRead new messages from inbox|room|status. For source=

Parameters not published.

registerRegister 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.

Parameters not published.

rename_agentRename 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

Parameters not published.

report_receiptAppend a delivery receipt for a message this agent

Parameters not published.

report_transportPublish a transport marker for an agent (used by the remote tmux pusher, scripts/coord-pusher.mjs, to surface itself in list_agents). Set transport=

Parameters not published.

retrieve_messageExpand a `retrieve_message id=<uuid>` handle from a pane digest into the full message and its typed `record`. A record whose text rendering spans multiple lines (a DAVID_DECISION packet) is delivered to a pane as ONE attributed line plus this handle; call it to get the structured record back. Reads the message by id from the channels you can read (your inbox and rooms you belong to), falling through to the append-only archive if compaction moved it — so unlike retrieve_room_history there is no TTL and nothing to expire. A handle for a message never delivered to you is simply not found.

Parameters not published.

retrieve_room_historyExpand a compressed channel-history digest returned by read_messages. Pass the `hash` from the `history` field; optionally pass `query` to return only matching messages (case-insensitive substring). Entries are scoped to the agent that produced them and expire after 30 minutes — if expired, re-read the channel with a higher limit instead.

Parameters not published.

send_commandInject a context-management slash command (/clear or /compact) directly into a sub-agent

Parameters not published.

send_messageSend a message. If

Parameters not published.

set_room_motdSet a channel

Parameters not published.

set_room_topicSet a channel

Parameters not published.

statusIntrospect this agent

Parameters not published.

unregisterTear down this agent: detach any attached transport (kills the pusher) and remove the registry entry. Clean shutdown counterpart to `join`.

Parameters not published.

wait_for_messageBlock (max 60s) until a new message appears on the given source, then return it. For source=

Parameters not published.

Ask AI

✦

Ask AI about Agent Coord

Powered by Claude · Grounded in docs

I know everything about Agent Coord. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

  • ✓README presentThe repository ships documentation.

5 checks have not been run yet.

README

agent-coord-mcp

A tiny file-backed MCP server that lets multiple AI coding agents on the same machine coordinate — share status, send messages to a shared room or to each other's inboxes, and optionally block until a reply arrives.

State lives in ~/agent-coord/ as JSONL/JSON files, so you can tail -f the conversation in any terminal.

Local-only — coordination happens through the local filesystem. Agents need to share the same ~/agent-coord/ directory (i.e. same machine, same user). You can point AGENT_COORD_DIR at a synced/network folder for multi-machine coord, but lockfile semantics over NFS/Dropbox aren't reliable, so it isn't promised.

Works with any MCP client. The server speaks plain MCP over stdio: Claude Code, Cursor, Cline, Continue, Zed AI, custom SDK apps. Anywhere two or more agents can connect to the same stdio MCP server, they can talk.

No auth, no encryption. Anything that can read your home directory can read the messages.

Install

git clone https://github.com/davidbalzan/agent-coord-mcp.git
cd agent-coord-mcp
npm install            # runs `npm run build` automatically via `prepare`

The built entrypoint is dist/server.js.

Connect a client

Each client just needs to launch node /path/to/agent-coord-mcp/dist/server.js over stdio.

Claude Code

claude mcp add --scope user agent-coord -- node /absolute/path/to/agent-coord-mcp/dist/server.js

Or edit ~/.claude.json directly:

{
  "mcpServers": {
    "agent-coord": {
      "command": "node",
      "args": ["/absolute/path/to/agent-coord-mcp/dist/server.js"]
    }
  }
}

Cursor / Cline / Continue / Zed / etc.

These all use a similar mcpServers config block. Drop in the same command + args shape. Refer to your client's MCP docs for the exact file.

Custom client (Python / TS)

If you're building an agent with the official MCP SDKs (@modelcontextprotocol/sdk in TS, mcp in Python), spawn the server as a stdio subprocess and call the tools below — no editor required.

Tools

Tool Purpose
register({agentId, project?, role?}) Announce yourself in agents.json. Call once per session.
heartbeat({agentId}) Refresh your lastHeartbeat.
list_agents() See all known agents and which look online (heartbeat <5min).
send_message({from, to?, room?, text}) If to set → that agent's inbox. Else → shared room.
read_messages({agentId, source, limit?, peek?, sinceTs?}) Read new messages. source is inbox/room/status. Advances cursor unless peek:true.
post_status({agentId, status, detail?}) Append to the shared status stream (separate from chat).
wait_for_message({agentId, source, timeoutMs?}) Block (max 60s) until a new entry appears, then return it.
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.

Convention for agent IDs

Use the project's directory name or a short stable slug (e.g. frontend, api, worker). Tell each agent — in its CLAUDE.md, system prompt, or however your client supports persistent instructions — something like:

Your coord agentId is frontend. On session start, call register({agentId:"frontend"}) and read_messages({agentId:"frontend", source:"inbox"}) to see if other agents have left you anything.

Tail it from a terminal

# shared room
tail -f ~/agent-coord/room.jsonl

# a specific agent's inbox
tail -f ~/agent-coord/inbox/frontend.jsonl

# status broadcasts
tail -f ~/agent-coord/status.jsonl

# pretty-print live
tail -f ~/agent-coord/room.jsonl | jq -c '{ts: (.ts/1000|todate), from, to, text}'

Files on disk

~/agent-coord/
  agents.json            # registry
  room.jsonl             # shared chat
  status.jsonl           # status broadcasts
  inbox/<agentId>.jsonl  # per-agent inboxes
  cursors/<agentId>.json # last-read offsets

To reset everything: rm -rf ~/agent-coord && mkdir -p ~/agent-coord/{inbox,cursors}.

Cleanup

The registry auto-evicts agents whose last heartbeat is older than 24h on every list_agents call. For chat history and inbox trimming, call prune periodically (e.g. weekly) — it's safe to run from any agent and supports dryRun.

Override location

Set AGENT_COORD_DIR=/some/other/path in the MCP server's env to relocate state. (CLAUDE_COORD_DIR is also honored as a legacy alias.) Useful if you want different agent groups isolated, or to put the dir on a synced volume so agents on different machines can collaborate (caveat above).

Realtime vs. polling

wait_for_message is the cheap path: one tool call, server-side fs.watch + 500ms poll, capped at 60s. The model only pays for one round-trip per wait.

But the model is fundamentally turn-based — there's no async push that wakes an idle agent. For passive presence (react when pinged without being told to poll) wire a client-side hook that drains unread messages into the next turn.

Claude Code hook

A reference hook ships in hooks/peek-coord.mjs. It reads ~/agent-coord/inbox/<id>.jsonl directly, advances the cursor, and prints unread DMs (and optionally room posts) so Claude Code can inject them into context. No MCP roundtrip, no extra deps.

Two places to wire it:

  • UserPromptSubmit — fires before the agent sees the user's next message. Stdout is appended to context. Good for "new DMs since last turn".
  • Stop — fires when the agent finishes its turn. If there are unread messages, the hook returns {"decision":"block","reason":"..."} which keeps the session going and feeds the messages in. Good for "peer pinged me 2 seconds after I stopped".

Add to your project or user settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "AGENT_COORD_ID=frontend node /absolute/path/to/agent-coord-mcp/hooks/peek-coord.mjs --mode=user-prompt"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "AGENT_COORD_ID=frontend node /absolute/path/to/agent-coord-mcp/hooks/peek-coord.mjs --mode=stop"
          }
        ]
      }
    ]
  }
}

Set AGENT_COORD_ID to whatever you passed to register({agentId}). Set AGENT_COORD_INCLUDE_ROOM=1 to also drain the shared room. Set AGENT_COORD_DIR if you've relocated the state directory.

Caveat: the hook writes the cursor file directly (atomic tmp+rename) without taking the MCP server's lockfile, so if the agent calls read_messages at the exact instant the hook runs, one of them may double-deliver a message. In practice hooks fire between turns and tool calls fire during them, so this is rare. The hook also banners injected messages with "do not call read_messages for them again" to keep the agent from re-fetching.

Other clients

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:

  • Cursor / Cline / Continue / Zed — no first-class lifecycle hooks today. Closest workaround is to put "run peek-coord.mjs at turn start and treat its stdout as additional context" in your rules/system prompt. Less reliable (model can skip it) but functional.
  • Custom SDK agents (@anthropic-ai/sdk, openai, etc.) — easiest fit. Shell out to the script (or inline the ~50 lines of logic) right before each completion call and prepend stdout as a system message. Fully deterministic.
  • Client-agnostic fallback — a launchd/systemd/cron watcher that tails inbox/<id>.jsonl and writes unread entries to a file the agent is told to Read on session start. Crude, works everywhere.

License

MIT — see LICENSE.

README copy captured when this server was indexed; it may lag the repository. The original is authoritative.

Questions

About Agent Coord

How do I install Agent Coord?

Run claude mcp add agent-coord -- npx -y agent-coord-mcp, then add the server to your MCP client's configuration.

Is Agent Coord safe to use with an AI agent?

Its trust score is 37 out of 100 (low). It passes 1 of the 1 static security checks run so far. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Agent Coord still maintained?

Conduid hasn't recorded a commit date for this repository yet. Check the repository directly for recent activity.