MCP server for teams of coding agents

The work is parallel. The awareness is not.

When two of your team's agents are about to write the same files, or build the same login page under two different names, they are told inside their own tool responses, while changing course is still cheap.

An MCP server every teammate's coding agent connects to. Each one says what it is about to do, before it does it.

Never blocks anyone No AI provider key, ever Open source
Two agents' paths crossing into an eyeA coral path enters from the top left and an indigo path from the bottom right. They run into each other and share the same outline; where they overlap the stroke turns violet, and the overlap forms an eye watching out of the page.
one agent the other where they cross
The queue

Three agents can write code at once. Three people cannot watch each other do it.

Hour three of any hackathon. Not a discipline problem — a visibility one.

01 · the bottleneck

Everyone is waiting on one person

The endpoint four people are blocked on is ninth on the backend list, because nobody can see that it is the one thing four people are blocked on.

02 · the blind spot

Git is the first place you find out

Two agents spend forty minutes in the same file. The merge is where that becomes information, and by then one of them is throwing work away.

03 · the drift

The decision you made at nine is gone by eleven

Somebody agreed to cookie sessions in a conversation an agent was not in. It writes a token to local storage — correctly, from everything it can see.

The work is parallelizable. The awareness is not — and awareness is the part that was never anybody's job. metiche makes it the agents' job. They are already narrating what they are about to do — they just say it somewhere the rest of the team can hear.

How it works

One server, one shared picture, and findings delivered in the call the agent was already making.

One person with three agents, or five people with two each. Both from day one.

1

Every agent declares

Before it edits, your agent calls declare_intent with one sentence and the paths it is about to touch. It calls update_intent as the work moves and heartbeat about once a minute.

That is the whole obligation. No CLI, no git hooks, no clone of your repo.

2

The server keeps it as live state

Sessions, intents and the paths each one claims — per team, per repo. Detection runs inside the same transaction that records the claim, so there is no window in which two agents both see a clean world and both proceed.

The path check is mechanical and runs on the server, which is why metiche needs no API key.

3

The other agents are told

MCP has no push, so metiche does not pretend to. Findings ride back on the next call an agent makes — including a bare heartbeat. The agent that caused the collision is told synchronously, before it has started.

what comes back · every tool, every time
// the response to the declare_intent your agent just made
{
  "ok": true,
  "key": "INT-83",
  "sequence": 417,
  "revision": 88,
  "pending": { "instructions": 1, "conflicts": 1, "reviews": 0 },
  "conflicts": [
    {
      "key": "CF-14",
      "kind": "path_overlap",
      "severity": "high",
      "paths": ["api/router.go"],
      "suggested_action": "Mara/api holds api/router.go
        (write, 4m, feat/booking-api). Take api/bookings.go and
        let the router land first."
    }
  ]
}
the whole setup · one line, never in your repo
// ~/.cursor/mcp.json — written by the installer,
// one entry per assistant, each with its own token
{
  "mcpServers": {
    "metiche": {
      "type": "http",
      "url":  "https://mcp.metiche.xyz/v1/mcp",
      "headers": {
        "Authorization": "Bearer mtk_…"
      }
    }
  }
}

The tools come in seven groups. The three highlighted are the ones you will notice your agent calling:

session
start_sessionheartbeatend_session
claims
declare_intentupdate_intentcheck_paths
team
create_teamjoin_teamlist_teamscreate_invitelist_invitesrevoke_invite
contracts
publish_contract
decisions
record_decisionget_review_contextreport_judgement
board
open_boardsign_out_browsers
instructions
get_instructionsreport_back

Coming next A tool to dismiss a finding.

What it catches

What it actually catches today

Two agents about to write the same file, two sides of an interface that disagree, including a side nobody is building, a plan that breaks a decision the team already recorded, and two agents about to build the same thing under different words.

path overlap works today

Two agents about to write the same file

Mara's agent holds api/router.go open for a rewrite of the middleware chain. Forty seconds later Devesh's agent declares an intent that adds a route to the same file. Neither of them knows, and neither of them is wrong.

How severity is decided

Two writes on the same exact file are critical; other write-against-write overlaps are high, and a read against a write is medium. Two reads are never a conflict at all. A claim covering a whole top-level directory is capped at low, and paths your project ignores, generated code among them, never become claims.

in Devesh's agent's tool response
▲ high CF-14 · path overlap
api/router.go — held by Mara/api (write, 4m, feat/booking-api)
→ Take api/bookings.go and let the router land first,
   or rebase on her branch before you start.
contract mismatch works today

Nobody is building this, or the two sides disagree

Mara's agent publishes the POST /api/bookings it is building. Devesh's agent publishes the same endpoint as something it calls, and it reads an eta the handler does not return. Devesh is told before the form is written, and Mara is told what to add. When nobody publishes the endpoint a frontend is coding against, the team is told that nobody is building this.

How it is decided

metiche reads both shapes itself. A response field the caller requires and the builder does not return is high, and the builder is the side to change; a request field the builder requires and the caller does not send is high, and the caller changes. Two types that cannot convert are critical. The same field under another spelling is low and interrupts nobody. A caller with no builder is raised after the project's cadence allows: five minutes in a hackathon. It all closes by itself once the shapes agree, a builder appears or a session ends.

in Devesh's agent's tool response
▲ high CF-21 · contract mismatch
POST /api/bookings — built by Mara/api
missing response field eta (timestamp)
→ Don't build on it yet: Mara was told to add it.
decision contradiction works today

A plan that contradicts what the team already settled

At nine the team settles that sessions are an httpOnly cookie, and Mara's agent records it with record_decision. At eleven Devesh's agent declares a plan that keeps the token in local storage — correct from everything it can see. metiche hands that agent the decision its paths touch, and its own model judges the plan against it.

Who judges it, and what that costs

metiche never judges this itself: the server has no model and no provider key, so nothing about your code is sent anywhere to be judged. It only picks the candidates — by the paths a decision governs, by its words, or because the team marked it always-show — and hands the pair to the agent whose plan it is, which is the side that can still change course. That agent answers with a verdict, a confidence and one line of reasoning, and all three go on the board, because it judged its own plan. No conflict is the usual answer and costs one small call; below 0.7 confidence a conflict is recorded and interrupts nobody. Change the plan and the conflict settles itself. A person is asked only when the two agents have not settled it.

in Devesh's agent's tool response
▲ medium CF-31 · decision contradiction
#auth-jwt-cookie — decided by Mara/api
your plan keeps the session token in local storage
→ Follow the decision and update_intent. You are asked
   once more, and no_conflict settles it.
duplicate work works today

Two agents about to build the same thing, in different words

Hour two of a hackathon, and nobody has a ticket. Mara's agent declares add login page. Ten minutes later Devesh's agent declares build the login screen, in a different file. No path overlaps and there is no issue id, and it is still caught, from the wording alone. Devesh's agent gets the pair in its own response, its own model judges whether it is the same change, and it changes course before it edits.

Who judges it, and what it looks for

metiche never judges this itself: the server has no model and no provider key, so nothing about your plans is sent anywhere to be judged. It only picks the pair. It reads the few words of each live plan in the same repository, folds “screen” into “page” and ignores verbs like “build”. When two plans carry the same issue id, that is simply the strongest signal, and the only one that reaches across repositories. The pair goes to the agent that declared second, which has not started yet. Different parts of one feature, the login form and the login handler, are no conflict, the usual answer. On a conflict it stops or takes a different part. Mara's agent hears about it only if Devesh's did not back off within a couple of minutes, and a person is asked only when the two agents have not settled it.

in Devesh's agent's tool response
▲ medium CF-44 · duplicate work
build the login screen — same work as Mara/ui
“add login page”, active 10m
→ Stop before you edit: mark yours superseded,
   or take a different part and reword it.
The honest part

metiche never blocks anyone.

Claims are advisory and they expire. Two agents are allowed to hold the same file — that is not an error state, it is a conflict, raised the moment it happens.

Nothing waits for a lease. Ordering assigns responsibility, not permission — and a tool that pretended to be a lock would be worse than no tool, because you would be waiting on a session that crashed twenty minutes ago.

noise You and Mara both hold api/router.go.
signal Mara holds api/router.go (write, 4m, feat/booking-api) — take api/bookings.go and let the router land first.
  • ·Nothing is ever surfaced without a next action. A finding with no suggestion is noise, and noise is how a tool teaches a model to ignore it. Low-severity findings are recorded without interrupting anyone.
  • ·Two reads never conflict. Paths your project ignores, generated code among them, never become claims at all.
  • ·A claim on half the repo gets capped, not amplified. Over-broad claims are recorded at low severity with a “narrow this” nudge.
  • ·Same branch, or one person's idle agent, counts for less. Severity comes down a step. Two of your own agents working at the same moment still get full severity, because that is when you know least about what each one is touching.
  • ·One conflict per pair. Re-detection bumps a counter; the other agent is not told again unless the severity climbs.
  • ·Claims expire. There is a time-to-live, and a hard four-hour ceiling that heartbeats cannot push past, so a crashed agent cannot haunt the board.
  • ·Coming next Dismissals. An agent will be able to dismiss a finding as a false positive, and a rule dismissed too often will demote itself to record-only.
The board

And one page where a person can see the whole team at once.

The agents coordinate with each other. The board is for the human who wants to know where the team actually is — a lane per person, their agents underneath, and the one line that says what each of them is doing right now. It repaints over SSE; there is nothing to refresh.

An illustration of the demo recording that ships in the repo — metiche has no users yet, so there is nothing else it could honestly be.

boardWho is live, what each agent is doing, the paths it holds, and a badge the moment one of them is contested.
conflictsEvery finding with its suggested action and the paths it is about; a duplicate shows the two plans side by side, why they were paired and what the judge said. Read-only: nobody settles a finding from the board.
runsEvery session end to end, replayed from the event log, so “what did that agent actually do” has an answer.
contractsProduces against consumes, with the verdict on each interface: unclaimed, mismatched, contested or converged.
decisionsWhat the team has settled and the code must obey, how many plans have been judged against each one, and the ones since superseded or revoked.
Getting on it

Getting your team on it takes one line and four steps.

Create the team, invite someone, they join, and anyone opens the board.

  1. Create the team

    The first person runs this line and chooses create:

    once, per machine
    curl -fsSL https://metiche.xyz/install.sh | sh

    It makes the team and shows you a join code once. It finds the assistants you already have — Claude Code, Cursor, Windsurf, Codex — and installs the skill your agent reads.

  2. Invite a teammate

    Any time later, ask your assistant to create a metiche invite. It calls create_invite and hands back a code that works once and lasts seven days by default. Send it privately — team chat, not your repository.

  3. They join

    Your teammate runs the same line, chooses join, and pastes the code when it asks:

    join code: <paste the code you were sent>

    The installer configures each of their assistants with its own token. It joins over the network before it configures anything, then proves the token works on a fresh connection. If that fails, nothing is written at all: no config, no half-set-up machine that looks finished.

  4. Open the board

    Open your board signed in: say yes at the end of the installer, or ask your assistant to open the metiche board. Either way you get a sign-in link that works once, for ten minutes. A private board opens only for its signed-in members; to everyone else it is a 404.

About the join code

A join code is an invite you redeem once, not a credential your agent carries. What each assistant keeps afterwards is a token the server minted for it, in that assistant's own config in your home directory.

Just looking? See the live demo →

The manual route is written down →

what your agent then does · on its own, every loop
// once per piece of work, read from git
start_session(repo_url, project_key, branch, goal)

// before touching anything; paths from the git root
declare_intent("add the booking form", paths, mode)
→ conflicts[] comes back in the same response

// as the work moves, and about once a minute
update_intent(status_line, add_paths, drop_paths)
heartbeat()