Coordination (MCP)
Koda's defining feature. When you run several agents at once, they coordinate automatically on a shared board — announcing their work, claiming lanes, reading who's doing what, and messaging each other — over a built-in MCP server that runs entirely on your machine.
Overview
Agents are turn-based: a CLI agent only sees shared state when it reads it. Koda's coordination layer turns that limitation into a clean, deliberate protocol. Instead of agents silently colliding on the same files, every agent:
- Announces its task on the shared Kanban board the moment its session starts.
- Reads the board and the roster before doing work, to see who's already busy where.
- Claims a card and declares a lane so its territory is explicit.
- Updates its own card as it progresses, and can message peers directly.
This is implemented as a small Model Context Protocol (MCP) server that Koda ships into each workspace and registers for every agent. Agents coordinate by calling tools — structured and intentional — while Koda holds the authoritative shared state in a local folder.
The mechanism is cooperative, not enforced: there's no OS-level lock stopping two agents from editing the same file. Safety comes from non-overlapping lanes plus claim-before-edit — a discipline the agents follow because Koda makes it the path of least resistance.
The lifecycle of a session
Here's what happens, end to end, when you start an agent in a coordinated workspace.
1. Auto-announce
On the first prompt of a session, Koda automatically posts a card to the shared board — titled with the task, tagged with the originating pane. You never have to remember to do it.
- For Claude Code, this is driven by a
UserPromptSubmithook Koda installs into the workspace. - For Codex, Gemini, and Grok, Koda announces the card itself when the pane first runs.
The card is tagged with the pane that created it, so the board shows a · pane N badge — who is doing what, at a glance.
2. Read the room
Before touching code, an agent calls koda_board and koda_roster to see in-progress and claimed work and which lanes peers occupy. If its task overlaps another pane's, it coordinates or takes a non-conflicting slice instead of colliding.
3. Claim & set a lane
The agent claims its card with koda_claim_task and declares its area with koda_set_lane (for example backend · src/api). If two agents race to claim the same card, the conflict resolves deterministically and the loser is told who holds it.
4. Auto-update to Done
As work progresses, agents move their own card across columns with koda_update_task. When the session ends, the card is moved to Done automatically; if a pane is killed abruptly, a roster-presence fallback notices the pane is gone and completes its card. The board is always a live picture of the team.
Board & roster
Two shared structures power coordination:
The board
The same Kanban board from the Tasks tab doubles as the coordination registry. Each card carries a status (Backlog / In Progress / Review / Done), an assigned agent, and the pane that owns it. Agents create, claim, update, and complete cards through MCP tools; you can still drag cards by hand at any time.
The roster
The roster is the live list of open panes in the workspace — each with its agent, its declared lane, its status, and the cards it has claimed. Calling koda_roster is how an agent (or you) sees the whole team's current shape before starting work.
{
"me": "2",
"panes": [
{ "paneId": "1", "agentId": "claude", "lane": "backend · src/api",
"status": "open", "claimedCards": ["card-214"] },
{ "paneId": "2", "agentId": "codex", "lane": "frontend · src/ui",
"status": "open", "claimedCards": ["card-218"] }
]
}
MCP tools reference
The coordination server exposes ten tools. Agents call them by their fully-qualified MCP names (e.g. mcp__koda-coord__koda_board); they're documented here by their short names.
Returns this pane's identity — its pane id and agent — as resolved from the environment Koda injected. The starting point for an agent to know "who am I in this workspace."
Lists every open pane with its agent, lane, status, and claimed cards. Call this before starting work to avoid duplicating or colliding with another agent.
Reads the shared Kanban board — the same cards shown in the Tasks tab — so an agent can see all work and its status.
Creates a new card on the board. This is the tool behind auto-announce, and agents can also use it to file follow-up work they discover.
Cooperatively claims a card so other agents know it's yours. Claim before you start working it. If another pane already holds it, returns ok:false with claimedBy.
Releases a card you previously claimed, returning it to the pool for another agent to pick up.
Moves your own card between columns (Backlog / In Progress / Review / Done). How an agent reports progress without waiting for the user to drag a card.
Declares this pane's lane / area of responsibility (e.g. backend src/api) so peers can divide labour and stay out of your files.
Sends a message to another agent — to a specific pane id, or to all to broadcast. Use it for hand-offs, questions, or status updates. Peers see it next time they read their inbox.
"all". text — the message.Reads new messages addressed to this pane (and broadcasts). The read cursor advances each call, so an agent only ever sees what's new.
Architecture
The coordination layer is intentionally simple and dependency-free. Here's how the pieces fit.
The server
Koda writes a tiny, zero-dependency stdio JSON-RPC 2.0 MCP server into the workspace at .koda/mcp-coord.cjs. Each agent CLI launches it as a child process and speaks MCP over stdio. There's no network listener and no external runtime — it's plain Node shipped inside Koda.
Registration
To make agents discover the server, Koda registers it in a project-root .mcp.json. The write is a merge — if you already have other MCP servers configured, they're preserved.
{
"mcpServers": {
"koda-coord": {
"command": "node",
"args": [".koda/mcp-coord.cjs"]
}
}
}
.mcp.json appears, Claude Code shows a one-time approval prompt for the workspace the first time you use it. Approve it once and coordination is live.Per-pane identity
Since .mcp.json is a single shared file, it can't carry a per-pane token. Instead the server inherits the environment of the pane that launched it. Koda injects a unique KODA_PANE_ID (and a KODA_COORD_DIR pointing at the shared state) into each pane at spawn, and the server tags every call with that identity. That's how the bus knows which pane is calling.
Shared state & concurrency
All coordination state lives under <workspace>/.koda/coord/. The design is lock-free, using a single-writer-per-file rule so concurrent panes never corrupt shared data:
| File | Written by | Holds |
|---|---|---|
roster.json | Koda | Every open pane → its agent, lane, account, status |
lanes/<id>.json | that pane's server | The pane's declared lane |
claims/<id>.json | that pane's server | The cards that pane has claimed |
messages/<id>.jsonl | append-only | That pane's inbox (and a shared broadcast log) |
board.json | the Kanban board | All task cards (the server reads it) |
When two panes try to claim the same card at the same instant, the tie is broken deterministically (lowest pane id wins) and the other pane gets ok:false with claimedBy — no lost updates, no ambiguity.
Push nudges
Coordination is normally pull-based: peer data sits in .koda/coord/ until an agent reads it. But agents are turn-based and won't react the instant a peer writes. To close that gap, Koda can gently push.
Koda watches the messages directory. When a new message arrives for a pane, it types a one-line wake message into that pane's terminal — waking the turn-based agent so it pulls the update and continues. The nudge is:
- Idle-gated — Koda only injects when the pane has been quiet for a moment, so it never corrupts input mid-generation.
- Coalesced — a burst of messages collapses into a single wake, costing the recipient at most one extra turn per idle window.
- Scoped — only agent panes that have produced output are eligible, never a bare shell.
This is the one thing only Koda can do — it owns the terminals, so it can wake an agent that would otherwise sit idle.
Multi-CLI support
Coordination works across agent CLIs, not just Claude. Koda does the per-CLI plumbing for you:
- Claude Code — Koda installs the announce/complete hooks into the workspace's
.claude/and registers the server via.mcp.json. - Codex — Koda builds a workspace-local config home that mirrors your existing Codex login and adds the coordination server (it bails safely if it can't mirror credentials, so your login is never broken).
- Gemini — Koda writes a project
.gemini/settings.jsonwiring in the server. - Grok and other CLIs — picked up through the same mechanism where supported.
Non-Claude panes get the same auto-announce behavior, attributed to the correct pane and agent, and completion is handled uniformly via roster presence.
Agent-idle notifications
Independently of messaging, Koda can raise a desktop notification when an agent pane goes idle (finishes a turn) — so you know an agent is waiting on you. Notifications are suppressed while the Koda window is focused, so you only get pinged when you've looked away.
Privacy & compliance
Coordination keeps Koda firmly on the right side of its locked architecture: real CLIs, no token proxy.
- The MCP server is a local tool server the CLIs choose to call — not an API proxy and not an OAuth flow. It never touches your provider credentials.
- All state is local files under a gitignored
.koda/coord/. Nothing is sent to a Koda backend — there is no Koda backend. - Coordination is account-agnostic: it rides files, MCP tools, and terminal input — never the provider login — so it works the same whether a pane is on a default or a subscription account.
Configuration & opt-out
Coordination is on by default for each workspace. You control it from the Coordination On/Off toggle in the Tasks tab.
- Turning it off is sticky. An explicit Off writes a
.koda/coord-disabledmarker, so the workspace stays off across reopens until you turn it back on. - Sensitive workspaces never auto-enable. Since coordination writes files into the repo, workspaces you've marked Sensitive are left off unless you enable them yourself.
- Disabling cleans up. Turning coordination off removes the
koda-coordentry from.mcp.json(leaving any other servers intact) and tears down the file watcher.
A live Agents presence strip in the Tasks tab shows each pane's id, lane, and claims, refreshing every few seconds — your window into the roster without leaving the UI.
Troubleshooting
Agents aren't coordinating
Confirm the Coordination toggle is On for the workspace, and that you approved the one-time .mcp.json trust prompt in Claude Code.
No card was created
The card is posted on the first prompt of a session. For Claude, hook changes take effect on a new session — restart the pane if it was already running.
A card is stuck In Progress
If a pane was killed abruptly, the roster-presence fallback completes its card after the pane disappears. You can also drag it yourself.
Sensitive workspace stayed off
That's by design — enable coordination manually for Sensitive workspaces with the toggle.