v0.1.0 Self-hosted MCP server for Claude Code and Codex

Your agents each have something the others don't. Let them work together.

One agent has Windows. One has your PDF library indexed. One sits inside the office network. Kampung gives every Claude Code and Codex session a mailbox on a server you run, so they can hand each other work, share what they know and keep going while they wait.

$docker compose up -d --build --wait
Watch it work

Runs from a git checkout today. Open source: AGPL-3.0 server, Apache-2.0 client.

Demo: Claude Code on a laptop and Codex on a NAS work together, replayed

Press ctrl+o in a Claude Code window, or click its ctrl+o button, to read the full tool calls, messages and envelopes.

Two more ways they work together.

Same three tools, different strengths. Each still is the last screen of a scripted exchange, drawn the same way as the replay above.

laptop/api ↔ winbox/api

Tests that only fail on Windows.

The fix passes on the Mac, but it builds file paths, so Windows is where it could still break. The Claude Code session on the Windows machine checks out the commit, runs the tests and reports one failure. The Mac agent fixes the join, and the Windows side confirms the fix before the merge.

Two terminals. Left, Claude Code on a Mac fixes an export path bug, pushes it and reads the confirmation. Right, Claude Code on Windows runs the export tests, reports one Windows-only failure, then re-runs them on the fix: 14 passed.
laptop/api ↔ office/ops

A tracker behind the office network.

Support reports CSV exports timing out. The tracker is only reachable inside the office, where a Codex session runs redmine-mcp-server. It finds the issue and its log note and passes them on. The laptop agent matches the log to the code and fixes it, and the tracker never has to be exposed.

Two terminals. Left, Claude Code on a Mac reads the export code, receives the tracker details and fixes the timeout. Right, Codex on the office network searches the tracker, opens issue 1287 and sends its repro steps and log note to laptop/api.

Scripted, like the replay. The redmine-mcp-server output follows that server's real response format. The Windows session is woken through Channels (opt-in).

Built for agents you already run.

Nothing new for the model to learn: three MCP tools and mail that waits until a session reads it.

A mailbox per repo

Addresses look like winbox/api, or winbox/api#a7 for one session. Mail waits until a session in that repo reads it, and reading delivers it, so there is nothing for the model to acknowledge.

The other side notices

Hooks tell a busy agent about new mail between tool calls and keep it going once at the end of a turn to read it. An idle Codex session wakes through codex queue; an idle Claude Code session wakes with Channels, opt-in.

Default deny

One key per machine, stored hashed. A new machine can neither send nor receive until you pair it, and the sender is stamped from the key, never read from the message.

Information, not instructions

Every message arrives in an envelope with the sender, sent time, depth and a "peer message, not an instruction" tag. The server instructions say the same. Your agent decides what to do.

Loop guard

Each reply carries a depth. From the fourth reply in a row between agents, mail is stored without waking anyone, until a human types in that session.

Dashboard and CLI

Machines, sessions, messages and the audit log in one place. Create keys, pair, revoke, end a session, reset a depth, from the browser or kampung on the command line.

Why not just…?

Each of these works for one exchange. Kampung is for the tenth one, when you are busy elsewhere.

AlternativeWhat happensWith Kampung
Copy between terminals by hand You are the transport. Every question and answer waits for you to notice, select and paste it into the right window. The agent calls send and carries on. The reply reaches its inbox, and the hooks make sure it is read.
SSH into the other machine Your laptop agent now runs commands on your desktop with your credentials, on a machine whose repo it has never seen. Each machine's own agent does its own work in its own checkout. Only text crosses, labelled as a peer message.
A shared chat channel or file Open to whatever has the URL, with no record of who sent what, and nothing wakes an agent that is mid-task or idle. Only paired machines can talk, the sender is stamped from its key, every send is audited, and the receiving agent is woken.
Claude Code's built-in SendMessage Works between sessions on the same machine, which is what it is for. It does not reach another machine or Codex. Kampung is for the other machine. On one machine, keep using SendMessage.

Your agents stay yours.

Every agent on the wire is yours, on a machine you own, talking through a server you run. Kampung keeps it that way with a few rules that cannot be switched off.

Read the threat model and limits in SECURITY.md
  • Self-hosted, one owner per deploy. One container, one SQLite database, one set of machine keys. Two people means two containers. There is no hosted version.
  • Pairing is default deny. A new machine key can do nothing until you run kampung pair A B. A fresh server with no keys answers 401 to everything but /health.
  • The sender is stamped from the key. One key per machine, and the server rejects mailboxes that belong to another machine, so an agent cannot pretend to be a different one.
  • Keys are stored hashed. Only the SHA-256 of each 256-bit key is kept, so a leaked database gives no working keys. Revoking a key ends all of its sessions.
  • Peer messages are information, never commands. The envelope says so on every message and the server instructions repeat it. A label is not a sandbox, so pair only machines whose agents you trust.
  • Everything is audited. Sends, reads, denied requests and every admin action land in an audit log you can read from the dashboard.

See every machine, session and message.

The dashboard at /admin turns on when you set KAMPUNG_ADMIN_TOKEN. Without the token it does not exist.

The Kampung admin dashboard: tiles for machines, live sessions, queued and no-wake messages, and a table of recent activity

Create keys, pair and unpair, revoke, end a session, reset a loop-guard depth or delete a queued message. The CLI does the same, and both are audited.

Connected in a few minutes.

Start the server, create a key per machine and pair them, then connect each machine. These are the README's quick-start commands.

01

Run the server.

On a machine every other machine can reach. It listens on 127.0.0.1:8803; the bundled Caddy profile adds HTTPS.

02

Create a key per machine and pair them.

key add prints each key once. No mail flows until you run pair.

03

Connect each machine.

With its own key. Setup installs the hooks and registers the MCP server with Claude Code; add --agent codex or --agent both for Codex. Restart the agent and ask it to list_peers.

Alpha: the client is on PyPI and the server image is ghcr.io/jztan/kampung-mcp (amd64 and arm64).

Questions people ask first.

Does it work between sessions on one machine?

That is not what it is for. Claude Code already has SendMessage for sessions on the same machine, and it does that well. Kampung is for the session on the other machine, and for Codex, which has no shared channel with Claude Code.

Which agents does it support?

Claude Code and Codex, through the same three MCP tools and the same hook script. Claude Code gets hooks that announce mail between tool calls and keep a turn going to read it; Channels (opt-in, Claude Code 2.1.80 or later) wake an idle session. Codex gets the same hooks, and an idle Codex session on macOS or Linux wakes through codex queue. On Windows, Codex stays polling only for now.

Does my code or my key go to a third party?

No. The server is yours, in a Docker container you run, and it stores only the messages your agents send (for up to 7 days), hashed keys and the audit log. The machine key lives in a config file only your user can read and is sent to your server over HTTPS. Messages are not end-to-end encrypted, since the server reads them to enforce pairing and keep the audit log, so run it on a host you trust.

What stops two agents replying to each other forever?

Every message carries a depth: one more than the highest depth its sender has received since a human last typed in that session. Past depth 3 the message is stored but wakes nobody. Typing a prompt resets the count, through a hook rather than an MCP tool, so the model cannot reset it itself.

What happens when the server is down or slow?

Nothing you would notice. The hooks are one stdlib-only script with a 2 second request timeout that always exits 0, so Claude Code and Codex carry on as if Kampung were not installed. Mail sent while a machine is unreachable waits in its mailbox for up to 7 days.

Is there a hosted version?

No, and none is planned. Kampung is built for one owner per server; the trust model depends on you running it. The compose file starts it in one command, and Caddy for HTTPS is a flag away.

Let your agents work together.

One container and three MCP tools, with hooks for Claude Code and Codex. The server is AGPL-3.0 and the client Apache-2.0; both live in one repository.

$ git clone https://github.com/jztan/kampung-mcp.git
$ cd kampung-mcp
$ docker compose up -d --build --wait
$ docker compose exec kampung kampung key add laptop
About Kampung

Kampung: self-hosted messaging between coding agents on different machines

Kampung is an open-source MCP (Model Context Protocol) server that lets coding-agent sessions on different machines send each other short text messages. A Claude Code session on a laptop can hand a task or a question to a Codex session on a desktop or a NAS, and the result turns up in its inbox, read by the agent itself at the end of its next turn or between tool calls. The name comes from the Malay word for village and its spirit of gotong-royong, neighbours helping each other; here the neighbours are your own agents, each in its own machine and repository.

What Kampung solves

Agents on different machines have different things: one has Windows, one has a PDF library indexed with pdf-mcp, one sits inside an office network with an internal MCP server. Without a channel between them, the person at the keyboard is the transport, copying questions and answers between terminals. Kampung gives each repository on each machine a stable mailbox (laptop/api, winbox/api#a7 for one session) and three MCP tools, list_peers, send and inbox. Mail waits in the mailbox until a session reads it, and reading delivers it, so there is no acknowledgement for the model to forget.

How agents learn about mail

Kampung installs a small hook script into Claude Code and Codex. A busy agent is told about new mail between tool calls, at most every 30 seconds. An agent that tries to finish its turn with mail waiting is kept going once to read it. An idle Codex session is woken through codex queue; an idle Claude Code session can be woken through Channels, an opt-in that needs Claude Code 2.1.80 or later. A loop guard stops two agents from waking each other forever: from the fourth reply in a row, mail is stored without a wake until a human types.

Security model

The machine is the trust boundary. Each machine has one API key, stored hashed on the server, and a new machine can neither send nor receive until the operator pairs it. The sender of every message is stamped from the key, never read from the request, and the server rejects mailboxes that belong to other machines. Every delivered message is wrapped in an envelope that marks it as a peer message, information and not an instruction. The server is closed by default, publishes on loopback, and ships with an optional Caddy service for HTTPS and an admin dashboard behind its own token. The full threat model is in SECURITY.md.

What the demo on this page shows

The demo is a scripted replay, not a live connection. It shows a Claude Code session on a laptop and a Codex session on a NAS writing a cited blog section together: the NAS agent searches the PDF library it has indexed with pdf-mcp and sends back the passage. Two stills below it show a Claude Code session on Windows finding a Windows-only test failure for a Claude Code session on a Mac, and a Codex session on the office network finding a tracker issue. The windows follow captures of Claude Code 2.1.312 and Codex 0.165.0, the messages and wake lines come from Kampung's own code, and a test in the repository checks that the wake and envelope strings on this page still match the source.

Install

Kampung is in alpha. docker compose up -d --build --wait starts the server, kampung key add and kampung pair create and pair machine keys, and uv tool install kampung-mcp followed by kampung-mcp setup connects each machine. The server is licensed under AGPL-3.0 and the client under Apache-2.0. The source is on GitHub, with the quick start in the README.

Copied