claude-mailbox
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., "@claude-mailboxwho is the current leader?"
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.
claude-mailbox
An MCP server that lets concurrently-running Claude Code sessions cross-talk.
Each session registers its project / worktree / branch / objective; sessions can
see each other, broadcast over channels, DM, and coordinate under a single
leader (the session on main). All state is backed by the shared
beads (bd) database beads_global,
so it works across projects and — via the existing Dolt remote — the fleet.
Why beads
bd already gives us a persistent, Dolt-synced, event-logged store with the exact
primitives a mailbox needs: labels (channels/identity), set-state (status/role/
heartbeat), assignees (DMs/delegations), ephemeral beads (transient messages),
gates (request/response), and a shared machine-wide DB (--global). The server is
a thin, typed wrapper around the bd CLI — no schema of our own.
Related MCP server: claude-connect-nats-mcp
Layout
src/claude_mailbox/
bd.py # `bd --global -C <workspace>` wrapper (+ --json)
identity.py # session id + git project/branch/worktree detection
model.py # label/state naming conventions + heartbeat math
leader.py # main-branch leader election over a singleton slot bead
server.py # FastMCP server: tools + background heartbeat + atexit deregister
cli.py # `mailbox` shim (who / leader / say / inbox)
skills/ # `mailbox` + `mailbox-leader` Claude skills
docs/DESIGN.md # full design (data model, protocol, risks)The server resolves its bd workspace from the repo itself, via
WORKSPACE = Path(__file__).parents[2] in bd.py — overridable with the
MAILBOX_WORKSPACE env var. This is why the invocation below runs it with
uv run --project <repo>; a bare wheel install (no repo checkout alongside
it) would need MAILBOX_WORKSPACE set explicitly.
Run
uv run claude-mailbox # start the MCP server (stdio)
uv run mailbox who # list live sessions (CLI, no agent)Prereq: the global mailbox DB must exist once per machine:
bd init --global # creates/initializes beads_global on the shared dolt serverWire into Claude Code / codex
Add to ~/.claude/mcp_servers.json (and it mirrors to codex):
"mailbox": { "command": "uv", "args": ["run", "--project",
"/path/to/claude-mailbox", "claude-mailbox"] }HTTP mode (standalone service, local database)
By default the server runs over stdio, one process per Claude Code session,
sharing the machine-wide beads_global database — this is unchanged. Set
MAILBOX_TRANSPORT=http to instead run it as a standalone network service, for
example hosting one authoritative instance in a remote pod that a Claude Code
session on a different machine reaches as an http-type MCP server entry, or
that a plain Python daemon (not a Claude session) calls directly as an MCP
client. This mode is meant to be paired with MAILBOX_GLOBAL=0 so the pod gets
its own dedicated local database instead of the shared machine-wide one.
Environment variables:
Var | Default | Purpose |
|
|
|
|
| Bind host when |
|
| Bind port when |
|
|
|
Run it as a standalone HTTP service backed by its own local database:
cd /path/to/claude-mailbox # WORKSPACE — where the local .beads/ will live
bd init --non-interactive # one-time: creates the local embedded db
MAILBOX_TRANSPORT=http MAILBOX_HTTP_HOST=0.0.0.0 MAILBOX_HTTP_PORT=8000 \
MAILBOX_GLOBAL=0 uv run claude-mailboxThen add it to a Claude Code session on another machine as an http-type MCP
server entry pointing at http://<pod-host>:8000/mcp, or point any MCP-capable
HTTP client (including a non-Claude Python daemon) at the same URL.
Note: on a machine that already sets BEADS_DOLT_SHARED_SERVER=1 globally
(a machine-wide bd default, independent of this server), MAILBOX_GLOBAL=0
still resolves through that shared server unless the pod environment leaves
BEADS_DOLT_SHARED_SERVER unset — the pod deployment should simply not set it.
Per-connection session isolation: one HTTP-mode process can serve many
concurrent connections, and each gets its own sid/git-context/bead_id/
objective, keyed off FastMCP's Context.session_id (the mcp-session-id
header) — they never collide, and proactive <channel> push (see below)
delivers to every connection, not just the first one to register. Residual
limitation: cleanup of a connection that disconnects without calling
deregister is time-based (idle for 15 minutes with no tool call), not a true
liveness check against the underlying transport — a connection that stays
open but genuinely idle that long gets treated as abandoned. See
server.py's _hb_tick_once docstring for the tradeoff. Stdio mode (one
process per session) is unaffected either way — idle reap only ever applies
under MAILBOX_TRANSPORT=http.
Docker
A published image runs the server in HTTP mode with its own local database out
of the box (MAILBOX_TRANSPORT=http, MAILBOX_GLOBAL=0 are baked in as
defaults — override via -e if you need something else). Images are built by
.github/workflows/docker-publish.yml for linux/amd64 and linux/arm64 and
published to GHCR:
docker pull ghcr.io/<owner>/claude-mailbox:latest # latest tagged release
docker pull ghcr.io/<owner>/claude-mailbox:edge # latest main/data is MAILBOX_WORKSPACE (and $HOME) inside the container — mount a
volume there for the local database to survive restarts, and initialize it
once before the first start (bd needs git init to succeed, which needs an
already-writable, already-owned directory — the named volume gets that from
the image's useradd --create-home on first use):
docker volume create mailbox-data
docker run --rm -v mailbox-data:/data --user mailbox \
--entrypoint bd ghcr.io/<owner>/claude-mailbox:latest init --non-interactive
docker run -d --name claude-mailbox -p 8000:8000 \
-v mailbox-data:/data ghcr.io/<owner>/claude-mailbox:latestThen wire it into a Claude Code session elsewhere as an http-type MCP server
entry pointing at http://<host>:8000/mcp (see "HTTP mode" above for the
non-Docker equivalent and the per-connection isolation notes, which apply
here too).
Build notes (low-CVE build): multi-stage — build tooling never reaches the
final image, which installs only git + ca-certificates on top of the
official python:3.11-slim base (distroless was evaluated and rejected: bd
hard-shells out to git, which needs a shell environment distroless doesn't
provide) and runs as a non-root user. The bd binary is fetched as a pinned,
checksum-verified release tarball rather than trusted implicitly. CI scans
every build with Trivy and uploads results to the repo's Security tab
(report-only — see the Dockerfile header for the residual CVE clusters this
repo can't fully resolve on its own, and why) and rebuilds weekly so upstream
Debian/Python security patches land automatically. Build it yourself with:
docker build -t claude-mailbox .Push delivery via Claude Code channels
The server is also a Claude Code channel:
it declares the claude/channel capability and pushes peer messages into the
session as <channel source="mailbox" kind="dm|request|delegation|broadcast" from_sid="…">…</channel> events — so a peer's DM or info-request interrupts the
session instead of waiting for a poll_inbox call. A background thread
(CHANNEL_POLL_SECONDS, default 4s) watches beads_global for new inbound
addressed to this session (and broadcasts on subscribed channels: general,
<project>, leader) and emits the notification. The existing send_dm /
respond_info / broadcast tools are the reply side.
To actually receive channel pushes, start Claude Code with the research-preview dev flag so it loads the mailbox as a channel (custom channels aren't allowlisted yet):
claude --dangerously-load-development-channels server:mailboxWithout the flag the mailbox still works fully as a normal MCP server (pull-based:
poll_inbox, read_channel); you just don't get proactive <channel> interrupts.
Channels are also gated by the org channelsEnabled policy on Team/Enterprise.
Status: beyond-MVP — presence, channels, DMs, leadership+failover, delegation,
blocking request_info, and channel push delivery. All committed, unit- + live-tested.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/zach-source/claude-mailbox'
If you have feedback or need assistance with the MCP directory API, please join our Discord server