zahadun
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zahadun@bob audit the SEO of example.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
zahadun
A self-hosted mesh of full-peer AI agents — Claude Code and OpenCode talking across your machines over A2A, with real mTLS identity and no API keys.
Every machine is an equal peer: it can ask (an MCP bridge inside Claude
Code / OpenCode) and answer (an A2A server executing tasks with the local
claude CLI, OpenCode, or plain scripts). There is no controller node, no
cloud relay, and no per-token billing — the Claude track runs on your existing
subscription via claude -p.
you, on machine A machine B
┌───────────────────────┐ ┌───────────────────────┐
│ Claude Code / OpenCode│ A2A JSON-RPC │ reverse proxy :8443 │
│ │ MCP bridge │ ──────────────────────▶│ mTLS, CN → identity │
│ ▼ │ over WireGuard mesh │ ▼ │
│ "@bob audit the SEO │ (NetBird/Tailscale) │ A2A server :9990 │
│ of example.com" │ │ ├─ script │
│ │◀── task id, then ──────│ ├─ claude -p │
│ zahadun_task(id) │ artifacts │ └─ opencode │
└───────────────────────┘ └───────────────────────┘Why this exists
Multi-machine agent collaboration is a
frequently requested
capability. The pieces all exist — A2A↔MCP bridges, WireGuard meshes,
workload identity (SPIFFE), agent memory servers — but as separate,
mostly cloud- or Kubernetes-shaped projects. zahadun is the whole thing in
~1,500 lines of Python with two dependencies (httpx, mcp), sized for
one operator and a handful of machines.
What's different here
Subscription, not API keys. The Claude executor is the CLI in
-pmode. If you pay for Claude Code, your mesh costs nothing extra.One conversation, two machines. The A2A
contextIdis the Claude session UUID on every machine in a task's path.claude --resume <id>on either end shows that machine's half of the same conversation.Deterministic
@peeraddressing. AUserPromptSubmithook parses mentions before the model sees the prompt. Routing is code, not an LLM decision: unknown peer → hard block with the roster; unreachable peer → the prompt never reaches the local model (you can't mistake a local answer for the peer's).Conflict-free mesh memory, no database. Shared memory is a git-synced directory of markdown files named
<peer>-<timestamp>.md. A peer only ever creates its own files, so replication can't conflict —git pull --rebasenever meets a merge.Real identity, home-lab sized. mTLS everywhere; each machine's cert is signed by your own root CA (an OpenBao PKI mount works well — see docs/CA-RUNBOOK.md). CSR authenticity is attested with an SSH signature (
ssh-keygen -Y) from the operator's personal key. Client-only machines getclientAuth-only certs: even a stolen key can't impersonate a server.Honest cards. A peer's AgentCard lists only skills that work today. A planned skill is a promise the caller can't distinguish from a working one — they just get
FAILED.
Related MCP server: claudemesh
Architecture in five decisions
The router is a human. Pure A2A: addressing means choosing a peer. No broadcasts, no capability matching. You say
@bob, code delivers to bob.Tracks are pure end-to-end. A task submitted from Claude Code executes in Claude on the target; OpenCode-to-OpenCode likewise. Mixing tracks would orphan the session history that makes
--resumework.The bridge has no model. The MCP server is an HTTP client plus a file layer. All intelligence lives in the tool that loaded it or on the target peer. It detects its own track from the MCP handshake's
clientInfo.The risky part is code; the convenient part is the model. Delivery and addressing: hook, deterministic. Result pickup, catalogs, memory: MCP tools, model-driven.
Peer input is untrusted. The Claude executor runs headless with no tools by default (permission prompts auto-deny). You grant tools per skill, explicitly, in
skills.json. Loops are cut by anX-Zahadun-Traceheader; caller identity comes from the client cert's CN via the proxy — never from the request body.
Quick start
See INSTALL.md. The short version, per machine:
# module
python3 -m venv /opt/zahadun-a2a/venv
/opt/zahadun-a2a/venv/bin/pip install zahadun-a2a # or from a checkout
# client side (every machine): MCP bridge + @peer hook
claude mcp add zahadun --scope user -- /opt/zahadun-a2a/venv/bin/python -m zahadun_a2a.mcp
# + hook in ~/.claude/settings.json, + block in opencode.json → INSTALL.md
# server side (machines that answer): systemd unit + reverse proxy with mTLS
# examples/ has units and nginx/Apache/Caddy configsEverything runs as a regular user. No dedicated system account, no root
services — the Claude executor needs the user's ~/.claude anyway.
MCP tools exposed to your agent
tool | purpose |
| who is in the mesh, what they can do (live AgentCards) |
| delegate; returns a task id |
| poll result / status |
| live model catalog of the local OpenCode engine |
| shared mesh memory |
Status
Working: the full client+server loop, three executors (script /
claude -p --session-id / OpenCode prompt_async with a model-fallback
ladder), task persistence across restarts, audit log, loop detection.
Not yet: SSE streaming (cards honestly say streaming: false),
input-required pauses (skills marked as needing human confirmation are
refused, not hung), per-caller rate limits.
Security model
Read SECURITY.md before exposing anything. Summary: designed for a single operator's machines on a private WireGuard mesh; peers are semi-trusted (authenticated, but their task content is not); it is not a multi-tenant system and was never designed as one.
A note on language
The project was built for a Polish-speaking mesh: code comments, error
messages and some config keys (drabina = model ladder, wykonawca =
executor, potwierdzenie_czlowieka = human confirmation) are Polish. The
docs you're reading, the wire protocol (A2A v1.0) and the MCP tool names are
English. Translating internals is on the table if anyone actually needs it —
open an issue.
License
Apache-2.0.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityBmaintenanceEnables peer-to-peer communication, discovery, shared state, and file coordination between AI coding agents across machines and sessions.1118Elastic 2.0
- Alicense-qualityAmaintenanceEnables Claude Code agents to communicate and share context across sessions via a peer-to-peer mesh, allowing them to ask for help from other agents without human interruption.8MIT
- Alicense-qualityCmaintenanceEnables AI agents to orchestrate a heterogeneous machine fleet via SSH, with unified command execution, file transfer, and dispatch of coding agents across platforms.1Apache 2.0
- AlicenseBqualityCmaintenanceAgent-native SSH control plane with a local Web Terminal, human-in-the-loop secret input, keychain-backed profiles, and user-confirmed uploads for Codex, Claude Code, and MCP-compatible coding agents.181Apache 2.0
Related MCP Connectors
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
The team layer for AI coding agents: shared contracts, collision alerts, E2EE sessions.
Operate your Linux servers from your LLM. Every action runs through an auditable allowlist.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/medelin/zahadun'
If you have feedback or need assistance with the MCP directory API, please join our Discord server