mcp-coordinator

mcp-coordinator

Prevents AI coding agents from conflicting by coordinating file claims and resolving conflicts in real-time across multiple sessions.

Category
Visit Server

README

<div align="center">

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.

License: MIT npm Tests E2E

Getting started · Problem · How It Works · MCP Tools · CLI · Auth · Dashboard · Config · Usage guide →

</div>


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/dashboard

Requires 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.md for 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 npm install -g mcp-coordinator mcp-coordinator <cmd>
npx (zero install) One-shot try, CI scripts (none) npx mcp-coordinator <cmd>
Local to a project Pinning a version per repo cd your-project && npm install mcp-coordinator npx mcp-coordinator <cmd> from project root
Docker (multi-arch) Container-first deployments, k8s docker pull ghcr.io/swoofer/mcp-coordinator:0.11.0 docker run ghcr.io/swoofer/mcp-coordinator:0.11.0 <cmd>
Single-file binary No Node available, easiest deploy GitHub Release tarball ./mcp-coordinator <cmd>

<sub>† Local installs require a package.json in the working directory — if you're just trying it out, prefer -g or npx.</sub>

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
ghcr.io/swoofer/mcp-coordinator:0.11.0 Pinned exact version — recommended for production
ghcr.io/swoofer/mcp-coordinator:0.11 Auto-bumps within the 0.11.x patch series
ghcr.io/swoofer/mcp-coordinator:latest 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 appropriate

Research 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:

  1. Announce — A client calls announce_work with target files, depends_on_files, and target modules before coding.
  2. Detect — The coordinator scores impact against all online agents and opens a thread if a score ≥ 90 matches.
  3. Consult — MQTT pushes the new thread to every affected agent. Each agent posts context, constraints, or proposes a resolution.
  4. 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 1883 (bind 127.0.0.1 by default) Local / LAN agents, best latency
WebSocket /mqtt on the coordinator HTTP port (default 3100) 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 target_files ∩ their target_files
0b They modify a file you depend on 80 depends_on_files ∩ their target_files
0c You modify a file they depend on 80 target_files ∩ their depends_on_files
1 Same file recently edited 100 File tracker conflict (last 60s)
2 Dependency file recently edited 80 depends_on_files recently touched
3 Same module prefix 30 target_modules overlap
4 Git co-change history (opt-in) 40-60 Files historically modified together — requires COORDINATOR_REPO_ROOT + git on PATH

Scores are categorized into three outcomes:

Score Category Action
≥ 90 concerned Thread opened, consultation required
30–89 gray_zone Thread auto-resolved, introspection recommended
< 30 pass 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). With announce_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 coordinatormcp-coordinator server start, that's the whole setup
  • Conflict 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

<details> <summary><b>Opt-in for teams and self-hosting</b> — auth, IdPs, audit, admin UI</summary>

Concern Opt-in
Authentication Phase 1 JWT (COORDINATOR_AUTH_ENABLED) OR Phase 2 OAuth (COORDINATOR_OAUTH_ENABLED) — see Authentication
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 users.idp_access_token + users.idp_refresh_token, key fingerprint guard at boot
Admin UI Browser console at /dashboard/admin.html for org/user/allowlist management
Audit log Tier-1 (never-drop) + Tier-2 (batched) + SHA-256 hash chain for tamper-evidence
Prometheus / Grafana 29 metrics on /metrics/auth, Grafana dashboard JSON, alert rules YAML
Database backend SQLite (default) → Postgres (planned, see design spec)

</details>

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
announce_work The main entry point. Call before coding — describes target files, dependencies, modules. Returns a thread_id if a conflict is detected.
coordinator_status Full snapshot — online agents, open threads, hot files, MQTT topics, Anthropic quota. Use it as a heartbeat poll.
wait_for_peers 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.

<details> <summary><b>All 26 tools</b> — agent registry, consultation, file tracking, dependency map, MQTT, status</summary>

Agent registry

Tool Description
register_agent Register as online with name and module list
list_agents List all registered online agents
heartbeat Update last-seen and derive activity status
agent_activity Get activity status for all online agents
wait_for_peers Block until N peers online, or timeout (prevents race before first announce)

Consultation

Tool Description
announce_work Open a consultation thread — the main entry point before coding
post_to_thread Post a message (warning, context, question) to an open thread
propose_resolution Submit a resolution proposal for participants to approve
approve_resolution Approve the current resolution proposal
contest_resolution Reject the proposal with a reason — resets to open
close_thread Close a thread after work is complete
cancel_thread Cancel a thread (work abandoned or no longer relevant)
get_thread Get a thread with all messages and current status
get_thread_updates Poll for new messages since a timestamp
list_threads List threads, filterable by status or agent
log_action_summary Log a one-liner action summary for the dashboard timeline

File tracking

Tool Description
hot_files List files being edited by multiple agents
get_session_files Get all files edited by an agent in the current session
check_file_conflict Check whether another agent edited a given file recently

Dependency map

Tool Description
set_dependency_map Load a module dependency graph (JSON)
get_blast_radius Calculate which other modules are affected by changes
get_module_info Get dependency and dependent info for a module

MQTT

Tool Description
wait_for_message Block until a coordination message arrives on the agent's topic
get_queued_messages Drain all queued messages without blocking
mqtt_publish Publish a raw message to any MQTT topic

Status

Tool Description
coordinator_status Full system status: agents, threads, file activity, MQTT, quota

</details>


CLI

Command Description
mcp-coordinator init [--url <url>] [--write-mcp-config <path>] [--write-claude-md <path>] First-time setup — create config dir, default config.json, print/write the .mcp.json snippet, optionally scaffold a sample CLAUDE.md
mcp-coordinator uninstall [--mcp-config <path>] [--claude-md <path>] [--purge] [--force] Remove integrations: drop coordinator entry from a .mcp.json, strip the coordination section from a CLAUDE.md, or --purge the ~/.mcp-coordinator/ directory entirely
mcp-coordinator server start [--port N] [--data-dir PATH] [--daemon] Start the coordinator (foreground or daemon)
mcp-coordinator server stop Stop the coordinator
mcp-coordinator server status PID, port, online agents, open threads
mcp-coordinator server logs [-n N] [-f] Tail the daemon log at ~/.mcp-coordinator/logs/server.log
mcp-coordinator dashboard Open http://localhost:3100/dashboard
mcp-coordinator doctor [--host H] [--port P] [--mqtt-port P] Health check: config, server liveness, /health, /mcp initialize, dashboard, MQTT broker
mcp-coordinator --version 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 stop

In-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 COORDINATOR_AUTH_ENABLED=true + JWT/registration/admin secrets — see JWT setup
OAuth 2.1 (Phase 2) Multi-tenant, internet-facing COORDINATOR_OAUTH_ENABLED=true + IdP credentials — see onboarding

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
docs/onboarding-self-host.md Zero-to-first-signin walkthrough
docs/idp-providers.md Per-provider setup (GitHub OAuth App, GitHub App, Google, OIDC, Azure AD)
docs/openapi.yaml OpenAPI 3.1, 17 endpoints
docs/security/threat-model.md STRIDE per asset, residual risks
docs/ops/upgrade-phase1-to-phase2.md Phase 1 → Phase 2 migration
docs/ops/key-rotation.md + auto-rotation.md JWT_SECRET rotation procedures
docs/ops/audit-integrity.md Audit chain runbook + tip-attestation workflow
docs/ops/backup-restore.md Litestream + NR12 reconciliation
docs/gdpr.md GDPR Art. 17 procedures
sdk/README.md 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_PCT env var (default 95).
  • Back-off when the usage endpoint itself returns 429.
  • Live widget in the dashboard with manual refresh + historical buckets.
  • coordinator/quota/update MQTT 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 tokens emits input_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_update events with scores and resolution types
  • Agent 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 logs

config.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
PORT 3100 HTTP port (also serves MQTT-over-WebSocket on /mqtt)
COORDINATOR_DATA_DIR ~/.mcp-coordinator/data Directory for the SQLite database
COORDINATOR_MQTT_TCP_PORT 1883 TCP port for the embedded broker
LOG_LEVEL info debug / info / warn / error
NODE_ENV development for pretty logs
COORDINATOR_AUTH_ENABLED false Enable Phase 1 JWT authentication
COORDINATOR_OAUTH_ENABLED false Enable Phase 2 OAuth
MAX_QUOTA_PCT 95 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_agent tool. 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-coordinator

Open 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:


License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured