Skip to main content
ClaudeWave

Swarm coordination MCP: file claims, agent presence, postboard intentions — the shared brain for teams of coding agents.

MCP ServersOfficial Registry0 stars0 forks● RustMITUpdated today
ClaudeWave Trust Score
87/100
✓ Trusted
Passed
  • ✓Open-source license (MIT)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Documented (README)
Last scanned: 10/13/2026
Install in Claude Code / Claude Desktop
Method: Manual · zoanthrope
Claude Code CLI
git clone https://github.com/spuentesp/zoanthrope
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "zoanthrope": {
      "command": "zoanthrope"
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Install the binary first: cargo install zoanthrope (or build from https://github.com/spuentesp/zoanthrope).

MCP Servers overview

# zoanthrope

> The Tyranid creature that relays the Hive Mind's will to the swarm —
> zoanthrope is the coordination relay: who works where, what was
> promised, what happened.

**A swarm coordination MCP server.**
zoanthrope answers one question — *who is working on what?* — for a
workspace of collaborating agents. File claims with read/edit intents,
agent presence, a public postboard of intentions, per-path filesystem
leases against clobbering, a rejoin path for agents that went away and
came back, and a capped audit ring. It keeps a team of agents out of
each other's way and leaves a trail of who promised what.

## What it is

- a small MCP server (`zoanthrope mcp`) over stdio JSON-RPC
- a hook-facing CLI (`zoanthrope claim` / `release` / `rejoin` / `status`)
- a state registry at `.zoanthrope/state.json` plus filesystem leases at
  `.zoanthrope/locks/` — zero daemons, nothing to install and keep alive

## Tool surface

All tools take and return JSON objects. Success bodies carry
`"ok": true`; a refused claim is a *successful* call whose body has
`"ok": false` plus the conflict shape.

| Tool | Arguments | Returns |
|---|---|---|
| `claim_files` | `agent_id`, `mode` (`claim` \| `release` \| `list`, default `claim`), `files` (paths or `{path, purpose?}`), `purpose?`, `intent?` (`edit` default \| `read`) | claim: `{ok, granted: [{path, claimed_at, purpose, intent}]}` or the conflict shape; release: `{ok, released: [path]}`; list: `{ok, claims}` |
| `list_claims` | `agent_id?` | `{ok, claims: [{path, agent, intent, claimed_at, purpose, held_by_stale}]}` |
| `who_am_i` | `agent_id` | `{ok, agent_id, name, kind, last_seen, stale, claims, posts}` |
| `list_active_agents` | `include_stale?` | `{ok, agents: [{agent_id, name, kind, last_seen, stale, claims_count}]}` |
| `register_agent` | `name`, `kind?` | `{ok, agent_id, name, kind, last_seen}` |
| `post_intention` | `agent_id`, `title`, `note`, `files?` | `{ok, post_id, post: {post_id, agent_id, title, files, note, status, created_at, updated_at}}` |
| `list_posts` | `agent_id?`, `status?` | `{ok, posts: [...]}` newest-updated first |
| `update_post` | `agent_id`, `post_id`, `status?` (`open`\|`taken`\|`done`\|`dropped`), `title?`, `note?`, `files?` | `{ok, post_id, post}` |
| `remove_post` | `agent_id`, `post_id` | `{ok, post_id, removed: true}` |
| `rejoin_agent` | `agent_id`, `files?` | `{ok, agent_id, claims_kept, claims_at_risk, view_epoch, board}` |
| `get_audit_log` | `limit?` (default 200), `since_unix?` | `{ok, events: [{ts, agent, action, path?, purpose?}]}` |

### The conflict shape

The heart of the product: a claim that clashes with another agent's
recorded intent is refused *all-or-nothing* and says exactly who is in
the way:

```json
{"ok": false, "holder": "beta", "path": "a.rs", "claimed_at": 1791780567.1, "purpose": "fix the parser", "holder_stale": false, "intent": "edit"}
```

### Claim semantics

A claim carries an intent (`read` or `edit`):

- an **edit** claim conflicts with anything another agent holds on the
  path — exactly one writer at a time;
- a **read** claim conflicts with another agent's **edit**, but readers
  co-hold happily with each other;
- an agent's recorded intent on a path is the **strongest** it holds —
  a later weaker claim never hides a stronger one. Only release (then
  re-claim) downgrades.

Claims are all-or-nothing per call: one conflict in a batch means
nothing is granted. A holder silent past the presence TTL is `stale`,
its claims are `held_by_stale`, and they still **block** — claims are
never auto-released; forcing one open is a policy this product did not
make.

A claim also binds the file's **content**: at claim (or re-claim) time
it records a content fingerprint — `mtime+size` always, plus `sha256`
for files ≤ 256 KiB, so same-size rewrites on coarse filesystems are
still caught. Every guarded write (the hook family) checks the file
against the claim's fingerprint first: if the file changed under the
claim — an out-of-band append, a generator run — the write is refused
with a `stale-claim` denial (holder is self) telling the agent to
re-read and re-claim. Re-claiming re-binds the fingerprint to the
current content; `release` drops it. No deliberate takeover exists: a
claim lock is a content promise, not just a writer lock.

### Filesystem leases (anti-clobbering)

A granted **edit** claim also takes a filesystem lease under
`.zoanthrope/locks/`: a nonce-named sentinel file per path, acquired
under a short `O_EXCL` guard (so concurrent acquirers cannot both pass
the holder scan), released by move-aside-and-verify (so a delayed
release can never delete a replacement holder's file). A live foreign
lease refuses a claim even when the registry is free — a lease-only
writer (an editor's save, a stray process) still gets the file to
itself. Read claims take no lease.

Leases carry a heartbeat mtime; one older than 60s
(`ZOANTHROPE_LEASE_TTL_SECS` overrides) is stale and may be taken
over, again move-aside-and-verify. `status` prints the lease layer so
orphaned sentinels are easy to spot.

### Postboard

Posts are the agents' public intentions — one line a human can read
while debugging a swarm. `post_intention` opens one (`status: open`);
`update_post` moves it through `taken` → `done`, or `dropped` if the
plan changed. Posts do not replace each other; an agent may carry
several. Only the posting agent may edit or remove its post.

### Rejoin

An agent that went away and came back (restart, sleep, disconnect)
calls `rejoin_agent`. It refreshes presence, re-asserts the agent's own
claims (filesystem lease refreshed or re-taken), republishes the board,
and reports — never rewrites. A claim the registry still credits to the
caller but where another agent now holds a live lease comes back as
`claims_at_risk`: reported, not stolen back, not released. Rejoin never
breaks claims, own or foreign.

## Quickstart

```console
$ cargo build --release
$ ./target/release/zoanthrope mcp
```

Then, over stdio (one JSON-RPC message per line):

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"demo","version":"0"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"claim_files","arguments":{"agent_id":"alpha","files":[{"path":"src/a.rs","purpose":"fix the parser"}]}}}
```

Point another agent at the same file and its call returns the conflict
shape above with `"holder": "alpha"`.

Pre-edit hooks use the CLI mirror instead of MCP (see `hooks/`):

```console
$ zoanthrope claim --files a.rs,b.rs --agent alpha --purpose "fix bug" --intent edit
$ zoanthrope release --files a.rs,b.rs --agent alpha
$ zoanthrope rejoin --agent alpha
$ zoanthrope status [--workspace DIR]
```

Exit codes: `0` granted/ok, `1` conflict (or `ok: false`), `2` usage or
IO error. `--workspace` is optional everywhere; without it the root is
found by walking up from the current directory for `.git`.

### Wire the hooks (Claude Code)

The guard family claims every file a tool call would mutate and, in
blocking mode, turns conflicts into tool-call denials. This is the
exact wiring that ran the recorded collision experiments — copy it
into your workspace's `.claude/settings.json` (adjust the paths to
where you keep the repo):

```json
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Edit|Write|MultiEdit|Bash",
        "hooks": [{ "type": "command", "command": "/path/to/zoanthrope/hooks/claude-code/claim-guard.sh" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit|Write|MultiEdit|Bash",
        "hooks": [{ "type": "command", "command": "/path/to/zoanthrope/hooks/claude-code/release-guard.sh" }] },
      { "matcher": ".*",
        "hooks": [{ "type": "command", "command": "/path/to/zoanthrope/hooks/claude-code/watch.sh" }] }
    ]
  }
}
```

Each agent needs its identity in the environment (`ZOANTHROPE_AGENT=alpha`,
…) — see `hooks/README.md` for the identity resolution order and how
to port the hooks to other agent frameworks.

**One wiring, both modes.** Advisory vs blocking is a runtime mode,
not a different hook: this wiring serves both. `claim-guard.sh`
resolves the mode per tool call, highest priority wins:

1. `ZOANTHROPE_MODE` env var (`advisory` | `blocking`) — the
   per-agent override, so a swarm can block its bots and leave one
   advisory actor;
2. `.zoanthrope/config.json` at the workspace root (found by walking
   up to the git toplevel, like the CLI; the file is optional):

   ```json
   {"mode": "advisory"}
   ```

3. default: `blocking` (the experiment-proven behavior).

In `advisory` mode the guard claims the file, prints the
claim/conflict JSON to stderr, and always exits 0 — it never emits a
`permissionDecision: deny`. In `blocking` mode a conflict denies the
tool call: exit 2, reason naming the holder (unchanged). An invalid
mode value falls back to `blocking` with one warning line on stderr —
a hook never crashes. `pre-edit.sh` remains as the legacy advisory
alias; `release-guard.sh` and `watch.sh` never deny, so the mode does
not apply to them.

## Instructions for agents

Paste this into your swarm's prompt or `AGENTS.md` — it is the protocol
the collision experiments validated:

```text
A coordination service (zoanthrope) is active in this workspace.
- Before touching shared files, post your intention (`post_intention` /
  `zoanthrope claim --files … --agent <you> --purpose "…"`).
- An edit may be DENIED with a reason naming the holder. That means
  another agent owns the file right now: wait briefly, then retry
  (up to 3 times). If still denied, work on something else and record
  it — never work around the lock (no out-of-band writes).
- Prefer append/insert on shared files; if you must rewrite a file
  whole, read it back after writing and merge anything that appeared.
- Post what you plan to do on the postboard before you start, and
  update the post when done (`update_post`).
- If you return after being away, call `zoanthrope r

What people ask about zoanthrope

What is spuentesp/zoanthrope?

+

spuentesp/zoanthrope is mcp servers for the Claude AI ecosystem. Swarm coordination MCP: file claims, agent presence, postboard intentions — the shared brain for teams of coding agents. It has 0 GitHub stars and its last recorded update is dated 2026-10-12.

How do I install zoanthrope?

+

You can install zoanthrope by cloning the repository (https://github.com/spuentesp/zoanthrope) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is spuentesp/zoanthrope safe to use?

+

Our security agent has analyzed spuentesp/zoanthrope and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains spuentesp/zoanthrope?

+

spuentesp/zoanthrope is maintained by spuentesp. The last recorded GitHub activity is dated 2026-10-12, with 0 open issues.

Are there alternatives to zoanthrope?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy zoanthrope to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: spuentesp/zoanthrope
[![Featured on ClaudeWave](https://claudewave.com/api/badge/spuentesp-zoanthrope)](https://claudewave.com/repo/spuentesp-zoanthrope)
<a href="https://claudewave.com/repo/spuentesp-zoanthrope"><img src="https://claudewave.com/api/badge/spuentesp-zoanthrope" alt="Featured on ClaudeWave: spuentesp/zoanthrope" width="320" height="64" /></a>

More MCP Servers

zoanthrope alternatives