AxonRelay MCP server
Commit Nov 4, 2026Provides a governance ledger and coordination board to track approvals and prevent collisions in mixed human and AI agent teams.
Also known as AxonRelay/core
- Stars
- 0
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Nov 4, 2026
- License
- MIT
What is AxonRelay MCP?
AxonRelay provides a governance ledger and coordination board to track approvals and prevent collisions in mixed human and AI agent teams.
Summary generated from the project's README
About AxonRelay MCP server
Managing mixed teams of humans and AI agents across multiple machines and repositories is what core enables. It provides a tamper-evident governance ledger and a coordination board to track approvals and prevent work collisions. This is designed for developers running several agents like Claude Code or Codex in parallel who need a durable paper trail of who approved which specific draft version.
Users interact with the server through an MCP interface using 26 tools and 3 resources. The system requires Docker and Python 3.12 for the board and ledger read side. While it does not require API keys for initial setup, a LangGraph Platform deployment is used if agents need to run tasks through it. The server maintains a persistent record of actors, task assignments, and versioned drafts, ensuring that decisions are bound to exact content commitments via SHA-256 hashes.
Beyond simple logging, the coordination board manages presence and advisory territory claims to stop agents from overwriting each other. It includes specialized tools for managing git resources and sending durable messages between actors. The architecture supports a content-blind mode for enhanced privacy, where only opaque identifiers and structured codes are processed.
What you can do with it
- 1Binding approvals to specific artifactsThe system ensures that an approval is only valid if it refers to the exact draft version and content commitment intended.
- 2Coordinating across distributed environmentsA developer can use the coordination board to manage presence and territory claims across different laptops and desktops.
Written from the project's README. Every use case is checked against a quote from it.
README
View on GitHubAxonRelay / core
日本語 | English
A governance ledger and coordination board for mixed human + AI teams, exposed as an MCP server.
In thirty seconds
- What it is - an MCP server your coding agent talks to. It keeps a tamper-evident record of who approved what, and a shared board of who is editing what right now - across machines, repositories and clones.
- Who it is for - one person running several agents (Claude Code, Codex, ...) in parallel, who wants them to stop overwriting each other and wants a paper trail a human actually signed.
- What it needs - Docker and Python 3.12 for the board and the ledger's read side. A LangGraph Platform deployment only if agents should run tasks through it. No API keys for the first part - see Quick Start.
- What it is not - an agent runtime, an approval UI, or a message bus. Those are delegated to LangGraph Platform, MCP elicitation and AG-UI on purpose - why.
AxonRelay records who — human or AI — did what, on which draft version, and who approved or rejected it with what comment, and when. It also answers the question that comes before the decision, once several agents work at once across several machines and several clones of one repository: who is working where, on what, and are we about to collide?
The agent runtime, the human-in-the-loop pause, and the UI are all delegated to standards (LangGraph Platform, MCP, AG-UI). What AxonRelay keeps for itself is the durable, cross-session, cross-actor ledger and the shared board — the parts those standards do not provide.
Status: personal PoC (post-pivot). Originally a general-purpose "AI Agent Orchestration" stack; that layer has been commoditized by LangGraph Platform + MCP + AG-UI, so AxonRelay was re-scoped to the one thing still worth owning: the governance ledger. The backend (Actor model, ledger, MCP server, Platform client) is migrated. The old Next.js auth/projects UI and AWS infra are being removed — see Current state.
Why this exists (mid-2026 context)
By mid-2026 the agentic stack settled into three layers — MCP for tools,
A2A for agent-to-agent, AG-UI for agent↔UI — and "pause to ask a human"
became a native MCP primitive (elicitation). Pausing for approval is no longer
a differentiator.
What none of those layers give you is a persistent record of accountability: elicitation is ephemeral and per-session; observability tools log runs, not who approved what.
Regulation points the same way, but later and more narrowly than is often stated. The EU AI Act's requirements for high-risk systems include automatic event logging (Article 12) and human oversight (Article 14), which overlap in theme with what an approval ledger records. Those high-risk obligations were not in force on 2026-08-02: that date is the Act's general application date and the start of its transparency rules (Article 50), while the Digital Omnibus on AI (Regulation (EU) 2026/1744, in force 2026-07-27) deferred the high-risk obligations to 2027-12-02 (Annex III systems) and 2028-08-02 (Annex I systems). Dates, primary sources and the day they were last checked are in docs/regulatory-positioning.md.
AxonRelay is not a compliance product and not a certification mechanism. It certifies nothing and makes nothing conform to the EU AI Act or any other regulation; the ledger is tamper-evident, not legally probative. What it preserves and dogfoods is one idea those requirements share with plain good engineering: the human is a first-class Actor in a durable ledger, not an exception at the interrupt boundary.
Architecture
Claude @ clone A Codex @ clone B Claude @ another repo
(laptop) (desktop) (laptop)
│ │ │
└───────────────────────┼───────────────────────┘
MCP (stdio locally · Streamable HTTP over Tailscale/Tunnel)
▼
AxonRelay Backend (FastAPI + MCP server, co-located)
│ - MCP: 26 tools + 3 resources (primary interface)
│ - REST: /tasks /agents /coordination (read-heavy)
│ - Postgres: the ledger + the coordination board
│
└──▶ LangGraph Platform (runtime / checkpoint / observability)
└──▶ writer → reviewer → [interrupt] → finalize
└──▶ LLM (Claude / GPT)
| Component | Role |
|---|---|
| MCP server | Primary interface. Drive tasks / approvals from the IDE. Co-located with the backend (backend/app/mcp/). |
| Backend (FastAPI) | Thin REST layer + the SQLAlchemy service layer that owns the ledger. |
| PostgreSQL | The ledger (Actor / TaskAssignment / Draft / Approval / ExternalLink — a projection of Platform thread state) and the coordination board (Workspace / Session / Claim / Relay). |
| Coordination board | Presence, advisory territory claims, and durable messages between agents (app/coordination.py). Pull-based: nothing interrupts a peer. |
| LangGraph Platform | Agent runtime, checkpointing, observability. Graph lives in axonrelay-graph/. (Now branded LangSmith Deployment; self-hostable, e.g. via Aegra.) |
The backend is read-heavy by design: writes (create / approve / reject) come through MCP; the REST API is mostly for reading the ledger from a dashboard.
Data model — the ledger
| Model | Purpose |
|---|---|
Actor |
Unified abstraction for humans and AI. A single human Actor (name="self") is the operator; AI actors are 1:1 with AgentDefinition. |
TaskAssignment |
Binds an Actor to a Task with a role: executor / reviewer / approver / observer. |
Draft |
Versioned history of a task's output — the artifacts approvals bind to. (task_id, version) is unique; each version carries a commitment (SHA-256 of its bytes) and, when known, the producer_actor_id. |
Approval |
Append-only record: action (approved/rejected), comment, reviewer_actor_id, timestamp, and the artifact it decided on (artifact_ref / artifact_version / artifact_commitment / producer). Tamper-evident via a per-task SHA-256 hash chain (prev_hash / entry_hash) that covers the binding too — see app/ledger.py and ADR-009. |
ExternalLink |
Link to an external artifact (e.g. a future MCP resource URI). |
State machine:
DRAFT → WAITING_REVIEW → WAITING_APPROVAL → APPROVED → COMPLETED
│ │
└─► NEEDS_REVISION ◄─┘ ─► DRAFT / CANCELLED
The ledger is safe for concurrent writers: record_approval locks the task row
before reading the chain head, so two agents approving the same task cannot fork
its hash chain. The same lock covers the draft append, so an approval that
carries an edited draft creates the new version first and binds to it.
Three guarantees that are easy to conflate:
- Tamper-evident events — an edited or reordered approval, including any of
its artifact-binding fields, fails
verify_task_ledger. - Artifact identity — each new approval names the exact draft version and
content commitment it decided on; a decision made against a superseded draft
is refused (
409/stale_decision). Whether the stored draft bytes still match that commitment is a separate check; the ledger never stores external artifact contents. Entries recorded before this binding existed verify as what they are and are reported asnot artifact-bound. - Regulatory-grade signing, timestamping and non-repudiation — out of scope; see docs/regulatory-positioning.md.
Data model — the coordination board
| Model | Purpose |
|---|---|
Workspace |
One checkout of one repo on one machine, identified by (host, repo, clone_path). Two clones of the same repo are two workspaces. |
Session |
An Actor working inside a Workspace over a stretch of time. Holds claims, receives relays. Re-registering resumes it, so an agent restart loses nothing. |
Claim |
An advisory, expiring lease — on paths within a repo, or on a shared git resource (worktree / stash / refs / remote) that no path pattern can describe. Overlapping claims are refused by default (force overrides, and the override is recorded). |
Relay |
A durable message addressed by audience — one actor, one clone, one repo, or the whole fleet. Delivered by pull. Carries a structured code beside its prose. |
RelayReceipt |
Per-recipient read/ack state, so one peer acking a broadcast does not hide it from the others. |
Every response about the board passes a disclosure policy
(ADR-012): in content-blind mode it
carries opaque references, structured codes and counts, not host names,
absolute paths or prose. Operational rows expire on a documented schedule
(python -m app.retention); the ledger never does.
Design, semantics, and the per-turn protocol agents follow: docs/coordination-spec.md.
Interfaces
MCP server (primary)
Ledger — 14 tools: list_tasks, create_task, get_task, run_task,
list_pending_approvals, approve_task, reject_task, review_pending_task
(interactive approval via MCP elicitation, in whichever shape the negotiated
protocol revision uses — see docs/mcp-server.md), verify_task_ledger, get_drafts,
list_agents, create_agent, update_agent, get_self_actor.
Evidence Clips — 5 tools: capture_evidence_clip, list_evidence_clips,
get_context_pack, evaluate_evidence_clip, validate_evidence_references.
The ledger records a clip's SHA-256 and source only; the excerpt stays local
and Context Packs resolve it there
(ADR-014).
Coordination — 12 tools: register_session, heartbeat_session,
end_session, get_board, check_conflicts, claim_territory,
release_territory, claim_git_resource, check_git_resource, send_relay,
read_inbox, ack_relay.
refs/stash is a per-repository ref, so sibling git worktrees share one stash
stack and git stash pop in one can consume work parked in another — with no
path to guard. tools/gitsafe enforces the guard mechanically:
it tags stashes with their owning session (which works offline) and consults the
board before destructive git.
3 resources: axonrelay://board, axonrelay://tasks/{id},
axonrelay://tasks/{id}/drafts/{version}.
Safe Envelope — 2 tools: ingest_safe_envelope, list_safe_events. With
AXONRELAY_SAFE_MODE=1 the instance is content-blind: every tool above that
accepts free text refuses with a fixed message, and the envelope — opaque
identifiers, closed enums, a source-produced artifact commitment, timestamps,
nothing else — is the only write path (ADR-010,
schema). Without the flag this is the
full-text local PoC.
Identity and scopes. With AXONRELAY_REQUIRE_AUTH=1 every HTTP caller
presents a credential (python -m app.credentials issue) that names the Actor
the server records for it and carries scopes; every tool and every REST route is
mapped to one, and a structural test refuses an unmapped surface
(ADR-011). Unset, and over stdio, calls run as
the operator.
Full tool reference and Claude Code setup: docs/mcp-server.md.
Requires mcp>=2.1,<3 — the 2.0 release renamed FastMCP to MCPServer, so the
dependency is pinned.
REST API (read-heavy, for the dashboard)
Interactive OpenAPI docs at http://localhost:8000/docs once the backend is up
(docker compose up -d backend, or uvicorn app.main:app --reload from backend/).
| Method | Path | Description |
|---|---|---|
GET |
/ |
Health check |
GET |
/actors /actors/{id} /actors/me |
Actors |
GET/POST/PUT/DELETE |
/agents /agents/{id} |
AI agent definitions |
GET/POST/PUT/DELETE |
/tasks /tasks/{id} |
Tasks |
POST/GET |
/envelopes |
Safe Envelope ingestion and listing (content-blind; the only write path under AXONRELAY_SAFE_MODE) |
POST |
/tasks/{id}/run |
Run on Platform until interrupt/completion |
GET |
/tasks/pending/approvals |
The unified approval inbox |
POST |
/tasks/{id}/approve /tasks/{id}/reject |
Approve / reject |
GET |
/tasks/{id}/drafts |
Draft history |
GET |
/tasks/{id}/ledger/verify |
Verify the tamper-evident approval hash chain |
GET/POST/DELETE |
/tasks/{id}/assignments |
Task assignments |
GET |
/coordination/board |
Active sessions, live claims, open relays |
GET |
/coordination/sessions /coordination/claims |
Who is working where; what is claimed |
GET |
/coordination/sessions/{id}/inbox |
A session's relay inbox |
Writes are also exposed via MCP and are the primary path from the IDE.
Quick Start
What you need
| To do this | You need |
|---|---|
The coordination board and the ledger's read side - register_session, claim_territory, send_relay, list_tasks, verify_task_ledger, the dashboard |
Docker (for Postgres) and Python 3.12. No API keys. |
Create and run tasks, approve and reject drafts - create_task, run_task, approve_task, reject_task |
A LangGraph Platform deployment of axonrelay-graph/ plus an LLM key: LANGGRAPH_* and ANTHROPIC_API_KEY in .env |
Creating a task allocates a Platform thread and approving one resumes it, so
those four tools fail with an explicit PlatformNotConfiguredError until
Platform is set up. Everything else works from the first minute.
Five commands
cp .env.example .env # works as-is on a laptop; add LANGGRAPH_* later
docker compose up -d postgres # Postgres on 127.0.0.1:5432
python -m venv .venv && source .venv/bin/activate
pip install -r backend/requirements.txt
(cd backend && alembic upgrade head) # migrations through 012; seeds the "self" Actor
Or, with the venv active, make dev runs the last three and starts the MCP
server; make help lists the rest (api, test, lint, frontend).
.env is read automatically. Its DATABASE_URL points at localhost; the
compose network's postgres hostname is only used inside the containers.
Connect Claude Code
The repository ships a project-scoped .mcp.json. Start Claude
Code from the repository root with the venv active, and it offers to enable the
axonrelay server:
claude
Other clients, the Streamable HTTP transport for several devices, and the full
tool reference: docs/mcp-server.md. Several devices must
share one instance for the coordination board to mean anything; serve
--http and reach it over Tailscale. The transport has no per-caller auth, so
it must stay on a private network (deploy/DEPLOYMENT.md).
To run the LangGraph graph locally before deploying to Platform:
cd axonrelay-graph && pip install -e . && langgraph dev
Environment Variables
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
postgresql://axonrelay:axonrelay_dev@postgres:5432/axonrelay |
Postgres connection string |
POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD |
axonrelay / axonrelay / axonrelay_dev |
Postgres bootstrap (change password outside local) |
LANGGRAPH_API_URL |
— | LangGraph Platform endpoint (required to run tasks) |
LANGGRAPH_API_KEY |
— | Platform API key |
LANGGRAPH_ASSISTANT_ID |
axonrelay |
Deployed graph / assistant id |
LLM_PROVIDER |
anthropic |
anthropic or openai (used by the graph) |
ANTHROPIC_API_KEY / OPENAI_API_KEY |
— | LLM credentials |
WRITER_MODEL / REVIEWER_MODEL |
claude-sonnet-4-6 / claude-haiku-4-5-20251001 |
Per-role models |
DISCORD_* |
— | Mobile approval via Discord (Phase 2.6, not yet wired) |
AXONRELAY_REQUIRE_AUTH |
— | 1 requires a per-caller credential on every HTTP call and records the credential's Actor (ADR-011); stdio stays loopback-trusted |
AXONRELAY_SAFE_MODE |
— | 1 runs the instance content-blind: free-text surfaces refuse, the Safe Envelope is the only write path (ADR-010) |
AXONRELAY_SAFE_PUBLIC_IDENTIFIERS |
— | 1 accepts envelopes with identifier_policy: public (owner/repo slugs); otherwise identifiers must be opaque |
AXONRELAY_REQUEST_STATE_KEY |
— | 32+ bytes keying the sealed handle that resumes a half-finished interactive approval on MCP 2026-07-28 (ADR-013); unset, the key is process-local and a restart makes the client ask again |
See SETUP_POSTGRES.md for database setup and migrations.
Current state
The pivot is complete; Phase 3 (coordination) is in:
- ✅ Backend: Actor-based ledger, MCP server (34 tools / 3 resources), LangGraph Platform client, migrations through 014. Approval ledger is tamper-evident (per-task SHA-256 hash chain, verifiable via
verify_task_ledger) and safe under concurrent writers — the single-writer limitation recorded in delta-mvp-spec §11.6 is lifted. - ✅ Coordination (Phase 3): Workspace / Session / Claim / Relay, driven from MCP, read via
/coordination/*. Lets several agents across machines, repos and sibling clones see each other, avoid editing the same paths, and leave each other durable messages — docs/coordination-spec.md. - ✅ Graph:
axonrelay-graph/(writer → reviewer → human_approval → finalize) ready for Platform. - ✅ Frontend: a thin read-only dashboard (Vite + React + TS,
frontend/) — task list with status filter, draft history, the approval timeline, and a per-task ledger-verification badge. Write actions stay in the MCP/IDE path. (CopilotKit/AG-UI deferred — a read-only audit viewer doesn't need agent↔UI streaming.) - 🚧 Infra: legacy
infra/(AWS EC2 DNS) andCaddyfileremoved. The cutover to Cloudflare Tunnel + Tailscale + Vercel/Pages is templated and documented in deploy/DEPLOYMENT.md; the account-side steps (DNS switch, EC2 decommission) remain a manual operator action. - 🚧 Tests: 396 SQLite cases (ledger invariants, concurrent-writer safety, projection idempotency, the coordination layer, path-overlap rules, git resource claims, the MCP tool surface) plus 36 Postgres schema-parity cases that apply the real migration chain and race real connections on the approval ledger and on resource claims. Both run in CI; the Postgres job uses a
postgres:16service. Run it locally withAXONRELAY_TEST_POSTGRES_URL=... pytest tests/test_postgres_schema.py.
Roadmap and migration plan: docs/step2-plan.md. Pivot rationale and scope: docs/delta-mvp-spec.md. Coordination design: docs/coordination-spec.md.
Docs
- docs/delta-mvp-spec.md — pivot spec (Actor model, scope, dogfood scenarios)
- docs/regulatory-positioning.md — what AxonRelay is not (no compliance or certification claims), the EU AI Act application dates with primary sources and the date they were checked, and the docs review checklist
- docs/coordination-spec.md — Phase 3: presence, territory claims, relays
- docs/adr-006-no-message-broker.md — why the coordination layer has no message broker
- docs/adr-007-gitsafe-enforcement-path.md — why
gitsafestays opt-in instead of shadowinggiton PATH - docs/adr-009-artifact-commitment.md — why every approval names the draft version and content commitment it decided on, and what that does not prove
- docs/adr-010-safe-envelope.md — the content-blind mode: what the Safe Envelope admits, what every other surface refuses, and how rejected values stay out of storage, logs and errors
- docs/adr-011-caller-identity.md — per-caller credentials and the six scopes: how the recorded Actor stops being a request parameter, and why stdio stays loopback-trusted
- docs/adr-012-metadata-minimization.md — what a shared board may say about a machine, the retention windows, and a threat model naming what stays observable
- docs/adr-013-mcp-2026-interaction.md — the two MCP interaction models an approval can travel on, how the decision stays bound to the draft that was shown across rounds, and why a replayed round cannot append twice
- docs/step2-plan.md — migration plan (Phase 2.1–2.6)
- docs/mcp-server.md — MCP server connection guide & tool reference
- docs/discord-setup-guide.md — Discord mobile-approval setup (account side only; the backend side is not built yet)
- deploy/DEPLOYMENT.md (日本語) — hosting cutover and the shared MCP endpoint the coordination board needs (Cloudflare Tunnel / Tailscale / Vercel)
- SETUP_POSTGRES.md — PostgreSQL setup & migrations
License
MIT - see LICENSE. This is a personal proof of concept: the MCP transport has no per-caller authentication and is meant to stay on a private network. Run it accordingly.
AxonRelay MCP questions
What is AxonRelay?
It is an MCP server that acts as a governance ledger and coordination board for mixed human and AI teams, keeping a tamper-evident record of approvals and current work.
Does it require API keys?
For the initial setup, no API keys are required.
What are the system requirements?
You need Docker and Python 3.12 for the coordination board and the read side of the ledger.
Is AxonRelay a compliance product?
No, it is not a compliance product or a certification mechanism; the ledger is tamper-evident but not legally probative.