mcp-coordinator
Used as a reverse proxy with automatic TLS in Docker compose deployments to securely expose the coordinator dashboard.
Provides OAuth 2.1 authentication using GitHub as an identity provider for the coordinator dashboard and API.
Click on "Install 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., "@mcp-coordinatorClaim file src/userService.ts for editing"
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.
mcp-coordinator
Stop your AI coding agents from overwriting each other's work.
One daemon. Every Claude Code / Cursor / Cline / Aider session on the same repo announces what it's about to touch, sees what the others are doing, and resolves conflicts before a line of code is written. Zero conflicts, everyone aligned.
Getting started · Problem · How It Works · MCP Tools · CLI · Auth · Dashboard · Config · Usage guide →
Who is this for
You are… | mcp-coordinator gives you |
A solo dev running 2-3 Claude Code sessions in parallel | Zero-config local daemon. Each session sees the others' file claims; no more "wait, Claude already rewrote that." |
A small team where everyone runs their own AI agent on the same repo | One shared coordinator over LAN. Real-time conflict detection across teammates' agents. |
Building a multi-agent orchestrator | A drop-in conflict layer with MQTT push, 26 MCP tools, and an SDK. Bring your own spawn strategy. |
Self-hosting for a regulated org | OAuth 2.1, 4 IdPs, encrypted IdP tokens at rest, SHA-256 audit chain (SOC 2 tamper-evidence), per-org allowlists. |
The Problem
You ask Claude Code to "add an updated_at field to the User type." In another terminal, Cursor is mid-migration on the same schema. Twenty minutes later you're doing git surgery to reconcile the two diffs — and it's not the first time this week.
Specifically:
Regressions — Agent A rewrites a module that Agent B was depending on
Duplicated work — Two agents implement the same feature from different directions
Architectural drift — Agents make local decisions that conflict with each other's designs
Wasted reconciliation time — Hours per week untangling what the agents did to each other
Each agent works in isolation. None of them know what the others are doing.
mcp-coordinator fixes this by giving every agent a shared nervous system over MQTT — they announce intentions before coding, conflicts are detected before a single line is written, and agents see each other's actions in real-time to agree on an approach.
Works with or without an orchestrator. Standalone with any MCP client (Claude Code, Cursor, Cline, Aider) — see the usage guide. Or pair with essaim for pre-composed agent profiles, work-stealing templates, and a behavior catalog.
1740+ tests across 170 files, passing on every release. Feature-flagged auth means Phase 1 deployments stay byte-identical to v0.7.x — proven by a 31-case backcompat suite that runs in CI.
Getting started
The fastest path for running a long-lived coordinator is a global install:
# 1. Install once, get the `mcp-coordinator` command on your PATH
npm install -g mcp-coordinator
# 2. First-time setup — creates ~/.mcp-coordinator/, writes a default config,
# and prints a .mcp.json snippet for your MCP client.
mcp-coordinator init
# 3. Start the server in the background
mcp-coordinator server start --daemon
# 4. Verify
mcp-coordinator server status
mcp-coordinator dashboard # opens http://localhost:3100/dashboardRequires Node.js 20+. Step 2 is idempotent — re-running init won't overwrite an existing config. The snippet it prints goes into your MCP client's config (e.g., ~/.claude/.mcp.json for Claude Code). If you'd rather not copy-paste, run mcp-coordinator init --write-mcp-config <project-path> and the snippet is written to <project-path>/.mcp.json (merging if the file already exists).
After step 4, every Claude Code (or other MCP-compatible) session connected to this coordinator can call all 26 tools (register_agent, announce_work, post_to_thread, coordinator_status, ...). For the full multi-Claude or team setup, see the usage guide.
🔀 Two ways to consume coordination state — agents can either poll the daemon's MCP tools (default, works since v0.6) or accept push events through the Channels sidecar (v0.12+, research preview). Most users start with polling and add Channels later when they want real-time reactivity. See
docs/operating-modes.mdfor the side-by-side comparison and decision guide.
Other install styles
Style | When to use | Install | Invoke as |
Global (default above) | Long-running daemon, ops |
|
|
One-shot try, CI scripts | (none) |
| |
Local to a project | Pinning a version per repo |
|
|
Docker (multi-arch) | Container-first deployments, k8s |
|
|
Single-file binary | No Node available, easiest deploy |
|
† Local installs require a package.json in the working directory — if you're just trying it out, prefer -g or npx.
Running via Docker
The image is published to GitHub Container Registry on every release tag — multi-arch (linux/amd64 + linux/arm64), with provenance and SBOM attestation. Three tag tracks:
Tag | Use case |
| Pinned exact version — recommended for production |
| Auto-bumps within the 0.11.x patch series |
| Tip of releases — fine for trying out, avoid in prod |
A working compose stack (coordinator + Caddy auto-TLS + GitHub OAuth) ships at examples/docker-compose/. For a Kubernetes CronJob example doing JWT secret rotation, see docs/ops/auto-rotation.md.
Real-time push via Claude Code Channels (research preview)
Channels is Anthropic's new push-into-session primitive: an out-of-band subprocess streams <channel> tags into a running Claude Code session, so the agent reacts to coordination events the moment they happen — no polling, no extra tool call. mcp-coordinator channel is a thin bridge over the embedded MQTT broker that emits one channel event per consultation, agent status change, and thread message. It also exposes a post_to_thread MCP tool so Claude can reply into a thread directly from the session.
# 1. Daemon already running? Add the channel server to ~/.claude/.mcp.json
# (see examples/channels-quickstart/.mcp.json.sample)
# 2. Launch Claude Code with channels enabled
claude --dangerously-load-development-channels server:mcp-coordinator-channel
# 3. Watch consultation events arrive as <channel> tags in the session, and
# let Claude reply via post_to_thread when appropriateResearch preview — requires --dangerously-load-development-channels in a Channels-capable Claude Code (v2.1.80+). Phase 3 (permission relay) intentionally deferred.
📖 Choosing between polling and push? See docs/operating-modes.md for a full comparison of the two modes, when to pick each, and how to run them side by side. Full setup walkthrough at examples/channels-quickstart/.
How It Works
Agent A Agent B
│ │
│ announce_work │ announce_work
▼ ▼
┌──────────────┐ ┌──────────────┐
│ MCP client │ ◄── MQTT ────► │ MCP client │
│ (any vendor) │ push-based │ (any vendor) │
└──────┬───────┘ └──────┬───────┘
│ MCP HTTP / SSE │
└──────────────┬────────────────┘
│
┌─────────▼──────────┐
│ mcp-coordinator │
│ 26 MCP tools + DB │
│ Aedes MQTT broker │
└─────────┬──────────┘
│ SSE
┌─────────▼──────────┐
│ Dashboard │
│ live events/quota │
└────────────────────┘The consultation cycle has four steps:
Announce — A client calls
announce_workwith target files,depends_on_files, and target modules before coding.Detect — The coordinator scores impact against all online agents and opens a thread if a score ≥ 90 matches.
Consult — MQTT pushes the new thread to every affected agent. Each agent posts context, constraints, or proposes a resolution.
Resolve — Agents approve, contest, or propose again. The thread closes when consensus is reached, or auto-resolves after timeout / in gray zones.
The server is client-agnostic: any MCP-compatible agent (Claude Code, Cursor, Cline, Aider, custom scripts) can connect over HTTP/SSE or stdio.
MQTT layer
The coordinator ships with an embedded Aedes MQTT broker. Agents subscribe once and receive every coordination event in real-time — no polling, no extra infrastructure.
Transport | Port | Use case |
TCP |
| Local / LAN agents, best latency |
WebSocket |
| Bun binary, remote agents, firewall-friendly |
Topic map: coordinator/consultations/new, coordinator/consultations/{id}/{messages,status,claimed,completed}, coordinator/agents/{id}/status, coordinator/broadcast, coordinator/quota/update. Clients self-filter their own messages and the payloads are small JSON envelopes.
Impact Scoring
Every announce_work call scores all online agents across multiple detection layers. The highest matching layer wins.
Layer | Signal | Score | Trigger |
0a | Same file announced in active thread | 100 |
|
0b | They modify a file you depend on | 80 |
|
0c | You modify a file they depend on | 80 |
|
1 | Same file recently edited | 100 | File tracker conflict (last 60s) |
2 | Dependency file recently edited | 80 |
|
3 | Same module prefix | 30 |
|
4 | Git co-change history (opt-in) | 40-60 | Files historically modified together — requires |
Scores are categorized into three outcomes:
Score | Category | Action |
≥ 90 |
| Thread opened, consultation required |
30–89 |
| Thread auto-resolved, introspection recommended |
< 30 |
| No conflict, proceed immediately |
Layer 0 is critical. Without announced intentions, a two-agent scenario where both work in
src/auth/would score only 30 (gray zone, auto-resolved). Withannounce_work, the same scenario scores 100 and triggers a full consultation.
announce_work accepts an optional target_symbols?: string[] (up to 200 entries, max 256 chars each). When two agents touch the same file with disjoint symbols, the score stays 100 but the reason text enriches with disjoint symbols: you=[X], them=[Y] — tree-sitter extracts symbols server-side from 15 languages (TS, JS, Python, Go, Rust, Java, C#, C/C++, Ruby, PHP, Kotlin, Swift, Bash) via optionalDependencies.
Capabilities at a glance
Out of the box, zero config:
Run the coordinator —
mcp-coordinator server start, that's the whole setupConflict detection — 4-layer impact scoring (announce / file / module / co-change), MQTT push delivery
Dashboard — live timeline, agent panel, scoring breakdown, quota widget
Observability — structured Pino logs, MQTT broker stats,
/livez+/readyz+/metrics
Concern | Opt-in |
Authentication | Phase 1 JWT ( |
Identity providers | GitHub OAuth App + GitHub App + Google + generic OIDC; up to 4 in parallel via picker UI |
Session model | Cookie sessions + Bearer JWT for MCP transport + service tokens for CI/CD |
IdP token encryption at rest | Column-level AES-256-GCM on |
Admin UI | Browser console at |
Audit log | Tier-1 (never-drop) + Tier-2 (batched) + SHA-256 hash chain for tamper-evidence |
Prometheus / Grafana | 29 metrics on |
Database backend | SQLite (default) → Postgres (planned, see design spec) |
Full version-by-version detail in CHANGELOG.md.
MCP Tools
26 tools registered under one HTTP/SSE transport at /mcp (and stdio for stdio-mode clients). The three you'll reach for 90% of the time:
Tool | What it does |
| The main entry point. Call before coding — describes target files, dependencies, modules. Returns a |
| Full snapshot — online agents, open threads, hot files, MQTT topics, Anthropic quota. Use it as a heartbeat poll. |
| Block until N peers come online (or timeout) — useful when an orchestrator spawns a fleet and you need to avoid races before the first announce. |
The in-server introspection tool returns the live schema for every tool — point any MCP client at it for runtime discovery.
Agent registry
Tool | Description |
| Register as online with name and module list |
| List all registered online agents |
| Update last-seen and derive activity status |
| Get activity status for all online agents |
| Block until N peers online, or timeout (prevents race before first announce) |
Consultation
Tool | Description |
| Open a consultation thread — the main entry point before coding |
| Post a message (warning, context, question) to an open thread |
| Submit a resolution proposal for participants to approve |
| Approve the current resolution proposal |
| Reject the proposal with a reason — resets to |
| Close a thread after work is complete |
| Cancel a thread (work abandoned or no longer relevant) |
| Get a thread with all messages and current status |
| Poll for new messages since a timestamp |
| List threads, filterable by status or agent |
| Log a one-liner action summary for the dashboard timeline |
File tracking
Tool | Description |
| List files being edited by multiple agents |
| Get all files edited by an agent in the current session |
| Check whether another agent edited a given file recently |
Dependency map
Tool | Description |
| Load a module dependency graph (JSON) |
| Calculate which other modules are affected by changes |
| Get dependency and dependent info for a module |
MQTT
Tool | Description |
| Block until a coordination message arrives on the agent's topic |
| Drain all queued messages without blocking |
| Publish a raw message to any MQTT topic |
Status
Tool | Description |
| Full system status: agents, threads, file activity, MQTT, quota |
CLI
Command | Description |
| First-time setup — create config dir, default |
| Remove integrations: drop |
| Start the coordinator (foreground or daemon) |
| Stop the coordinator |
| PID, port, online agents, open threads |
| Tail the daemon log at |
| Open |
| Health check: config, server liveness, |
| Print the installed version |
Quick start
# Start the coordinator (embedded MQTT + dashboard)
mcp-coordinator server start --daemon
# Open the dashboard
mcp-coordinator dashboard
# Stop when done
mcp-coordinator server stopIn-process from your own Node app
import { startServer } from "mcp-coordinator";
await startServer({
port: 3100,
dataDir: "./coordinator-data",
});For multi-Claude setups, team deployments, walkthroughs, and debugging recipes, see the usage guide.
Authentication
The coordinator runs in one of three modes, selected by env-var configuration. Single-user / dev local stays zero-config; multi-user deployments opt in to JWT or full OAuth via a single feature flag.
Mode | When | Enable |
Open (default) | Local dev, single user | No env vars needed — synthetic legacy claims |
JWT (Phase 1) | Small team, shared secret |
|
OAuth 2.1 (Phase 2) | Multi-tenant, internet-facing |
|
OAuth mode adds: 4 IdP providers (GitHub OAuth App, GitHub App, Google, generic OIDC) with picker UI, cookie sessions + Bearer JWT + service tokens, refresh-token rotation with stolen-token detection, SHA-256 audit chain (SOC 2 tamper-evidence), and an admin UI at /dashboard/admin.html.
Doc | Topic |
Zero-to-first-signin walkthrough | |
Per-provider setup (GitHub OAuth App, GitHub App, Google, OIDC, Azure AD) | |
OpenAPI 3.1, 17 endpoints | |
STRIDE per asset, residual risks | |
Phase 1 → Phase 2 migration | |
| |
Audit chain runbook + tip-attestation workflow | |
Litestream + NR12 reconciliation | |
GDPR Art. 17 procedures | |
TypeScript SDK reference |
Operational tooling: mcp-coordinator init phase2 (interactive wizard), mcp-coordinator doctor --phase2 (8 health probes), mcp-coordinator service-token {issue,list,revoke}, mcp-coordinator rotate-jwt-secret, tsx scripts/verify-audit-chain.ts.
Anthropic Quota Pre-flight
The coordinator tracks Anthropic workspace quota live and exposes it on MQTT, the dashboard, and the coordinator_status MCP tool — so MCP clients can decide whether to abort, throttle, or proceed before launching expensive turns.
Reads usage from the Anthropic API using the key in the environment.
Threshold via
MAX_QUOTA_PCTenv var (default95).Back-off when the usage endpoint itself returns 429.
Live widget in the dashboard with manual refresh + historical buckets.
coordinator/quota/updateMQTT events stream into the timeline by default.
Orchestrators that spawn N agents at once can read coordinator_status.quota and abort their run if utilization is over a configured threshold — the essaim reference orchestrator does exactly this.
Token Observability
Every MCP tool call and agent turn is logged with token breakdown.
Logs — component logger
tokensemitsinput_tokens,output_tokens,cache_read,cache_creation,thinking, model id, turn index.Dashboard — live per-agent token gauge, cumulative session total, quota widget.
Aggregating across runs (e.g., reports/YYYY-MM-DD-<run-id>.md) is an orchestrator responsibility — the coordinator emits the events, the orchestrator consumes them.
Dashboard
http://localhost:3100/dashboard (or /dashboard on whichever port the coordinator is bound to).
Timeline — all threads +
quota_updateevents with scores and resolution typesAgent panel — online/offline, working/idle/waiting, current file, thread being waited on
Scoring breakdown — which detection layer triggered each conflict
Quota widget — live utilization %, stacked buckets, manual refresh button
Consensus metrics — per session: consensus / timeout / auto-resolved split, token totals
All events arrive via SSE on /api/events. No polling.
Agent activity states
Status | Indicator | Meaning |
working | pulsing blue | Actively editing files |
idle | solid green | Online, no recent activity |
waiting | pulsing yellow | Blocked on a consultation thread |
offline | solid red | Disconnected or session ended |
Configuration
Local data
~/.mcp-coordinator/
├── config.json # persistent configuration
├── data/
│ └── coordinator.db # SQLite database
├── server.pid # PID file (when daemonized)
└── logs/
└── server.log # daemon logsconfig.json
{
"server": { "port": 3100, "data_dir": "~/.mcp-coordinator/data" },
"defaults": { "coordinator_url": "http://localhost:3100" }
}Resolution priority (highest to lowest): CLI flag → env var → config.json → default.
Core env vars
Variable | Default | Description |
|
| HTTP port (also serves MQTT-over-WebSocket on |
|
| Directory for the SQLite database |
|
| TCP port for the embedded broker |
|
|
|
| — |
|
|
| Enable Phase 1 JWT authentication |
|
| Enable Phase 2 OAuth |
|
| Pre-flight abort threshold for Anthropic quota |
The complete annotated env reference (~70 variables including all Phase 2 OAuth / multi-IdP / hardening vars) lives in .env.example — copy-paste and fill in.
Structured Logging
Pino emits JSON per subsystem. Component loggers: http, mcp, mqtt, consultation, conflict, auth, tokens, quota.
{"level":"info","time":1712345678901,"component":"http","msg":"Server started","port":3100}Dev (NODE_ENV=development) renders pretty human-readable lines. Levels controlled via LOG_LEVEL.
SDK
A TypeScript reference client lives in sdk/ (not yet published to npm). Install via npm install file:./sdk from a consumer project.
import { McpCoordinatorClient, FileTokenStore, ProactiveRefresh } from "@mcp-coordinator/sdk-js";
const client = new McpCoordinatorClient({
baseUrl: "https://coordinator.example.com",
store: new FileTokenStore(),
refreshStrategy: new ProactiveRefresh(),
refreshLockPath: process.env.HOME + "/.mcp-coordinator/refresh.lock",
});
await client.loadFromStore();
const me = await client.whoami();See sdk/README.md for the full API.
Integration patterns
Any MCP client — connect to
http://localhost:3100/mcp(HTTP/SSE) or stdio. The server speaks MCP 2024-11-05.Custom orchestrator — spawn agents that connect to the MQTT broker and register via the MCP
register_agenttool. The orchestrator decides spawn count, lifecycle, and quota gating; the coordinator handles the protocol. See essaim for a reference implementation, or write your own.Behavior catalog — coordinator-aware agent behaviors (announce-before-write, work-stealing, conflict resolution) are YAML configs assembled by @swoofer/promptweave. See essaim's behaviors for a curated catalog.
Development
# This repo uses pnpm (>= 9). Run `corepack enable` once.
pnpm install
pnpm test
pnpm dev # HTTP / SSE on port 3100
pnpm dev:stdio # stdio mode
pnpm build # TypeScript build → dist/
# Standalone binary (requires Bun)
bun build --compile cli/index.ts --outfile bin/mcp-coordinatorOpen an issue or PR on GitHub.
Roadmap
v1.0 — Multi-instance: Redis-backed cache invalidation + leader election for the sweeper and rate limiter.
Postgres adapter — for regulated multi-instance workloads. See design spec.
SDK polish — keytar keychain integration, Windows DPAPI for token file, named-profile TOML config.
Per-version detail for everything already shipped lives in CHANGELOG.md.
Related projects
@swoofer/promptweave — YAML composer for assembling agent prompts, hooks, and MCP configs. Use it with mcp-coordinator-aware behaviors from essaim.
essaim — end-to-end orchestrator that spawns N coordinated agents using
@swoofer/promptweave+mcp-coordinator. Ships the reference catalog of coordinator-aware behaviors.
Support
Built and maintained by @swoofer. v0.11.0 shipped with 1740+ tests and a growing list of external contributors.
If this project saves you time:
⭐ Star the repo — it helps other devs find it
🐛 Open an issue if something is broken or missing
License
MIT
This server cannot be installed
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/swoofer/mcp-coordinator'
If you have feedback or need assistance with the MCP directory API, please join our Discord server