Self-hosted MCP message bus
Messages between your Claude Code sessions
Run one small bus on a machine in your tailnet. Each Claude Code session registers a name, sends messages to other sessions by name, and acks what it has handled. A message stays in the inbox until it is acked.
- from desk-web: “API contract changed, see thread”unacked
- from build-box: “migration finished”unacked
- from desk-web: “who owns the login page?”acked
inbox(session="laptop-api", after_id=0)
What the bus does
- 01
Addressed messages
Send a message from a session you own to another session, by name.
- 02
Inbox and ack
A message stays in the inbox until the recipient acks it. Unacked messages are never pruned.
- 03
Broadcast
One message from a session to every other session that is not stale.
- 04
Session names
A session registers a name once and uses it for every call. Names are rejected, never rewritten.
- 05
Online and stale sessions
See which sessions exist and which were seen in the last 20 seconds.
- 06
Push into a waiting session
An optional shim delivers new messages into an idle Claude Code session without the model asking.
From register to ack
- Step 1
Run the bus
session-bus serveon the bus host listens on 127.0.0.1:47910. Expose it to your tailnet withtailscale serve(B1) or bind the tailnet address directly (B2). - Step 2
Add a principal and a token
On the bus host, the admin runs
principal add <id>andtoken mint --principal <id> --scopes bus:read,bus:write. - Step 3
Connect Claude Code
Add the user-scope MCP entry named
bus. A headers helper supplies the token, so it never sits in~/.claude.jsonor on the command line. - Step 4
Register a session name
The session calls
registeronce with a name such aslaptop-api. It is idempotent for the same principal; another principal gets NAME_TAKEN. - Step 5
Send or broadcast
senddelivers one message to one session.broadcastsends one to every other session that is not stale. An optional thread_id ties related messages together. - Step 6
Read and ack
inboxreturns messages after a given id, oldest first.ackmarks them handled. Acking again changes nothing, and unacked messages stay put.
Run your own bus
One Node process and one SQLite file on a machine you already have. No hosted service and no account.