ClaudeMailbox
A standalone MCP mail server that lets parallel Claude sessions coordinate with each other. Any Claude session (plain terminal, ClaudeDo worktree, anything that consumes .mcp.json) can send messages to a peer session's inbox, check for pending messages, and discover other active mailboxes.
Not a substitute for run_in_background: true — that handles single-session responsiveness. This handles session-to-session coordination.
Architecture
One long-running daemon binds HTTP on loopback, hosts the MCP server at /mcp and a small REST API at /v1/*, and persists state in a single SQLite file. Sessions declare themselves via an X-Mailbox header in their .mcp.json.
session-backend session-frontend external sender
(X-Mailbox: backend) (X-Mailbox: frontend) (CLI / UI / hook)
| | |
| HTTP | |
+--------------+-----------------+--------------------------+
v
claude-mailbox serve (ASP.NET Core + Kestrel)
/mcp MCP tools
/v1/* REST for non-MCP senders
/health
v
~/.claude-mailbox/mailbox.db (SQLite WAL)
Install
dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true
Put the resulting claude-mailbox.exe on your PATH.
Daemon lifecycle
Pick whichever level of automation you want:
- Manual.
claude-mailbox servein a terminal. - Startup shortcut. Shortcut to
claude-mailbox serveinshell:startup. - Windows Service (recommended). See below.
Windows Service
Install (admin shell):
claude-mailbox install-service [--port 47822] [--bind 127.0.0.1] [--db-path <path>]
This:
- Creates
%ProgramData%\ClaudeMailbox\with ACLs forLocalService - Seeds
mailbox.jsonwith the defaults (or your flag overrides) — only on first install - Registers the service via
sc.exe create, running asNT AUTHORITY\LocalServicewithstart= auto
Control:
claude-mailbox start
claude-mailbox stop
claude-mailbox status # prints Running | Stopped | NotInstalled
claude-mailbox uninstall-service [--purge]
--purge additionally removes %ProgramData%\ClaudeMailbox\ (config + database).
Config precedence
CLI flag > mailbox.json > built-in defaults
The service is invoked with serve --config C:\ProgramData\ClaudeMailbox\mailbox.json, so editing that file and restarting the service is enough to change port/bind/db-path.
Interactive (console) runs without --config use %USERPROFILE%\.claude-mailbox\mailbox.db (unchanged from v0).
Manual smoke test
claude-mailbox install-service
sc query ClaudeMailbox
claude-mailbox start
Invoke-WebRequest http://127.0.0.1:47822/health
claude-mailbox uninstall-service --purge
Defaults: port 47822, bind 127.0.0.1, database at %ProgramData%\ClaudeMailbox\mailbox.db (service) or %USERPROFILE%\.claude-mailbox\mailbox.db (console).
Use from a Claude session
Drop this into your project's .mcp.json (one per session, different X-Mailbox values):
{
"mcpServers": {
"mailbox": {
"type": "http",
"url": "http://127.0.0.1:47822/mcp",
"headers": {
"X-Mailbox": "backend"
}
}
}
}
Four MCP tools are exposed:
| Tool | Purpose |
|---|---|
mcp__mailbox__send(to, body) |
Send a message to another mailbox |
mcp__mailbox__check_inbox() |
Pull all pending messages for this mailbox (marks delivered) |
mcp__mailbox__peek_inbox() |
Non-consuming check — returns { pending, oldestAt } |
mcp__mailbox__list_mailboxes() |
Discover known mailboxes and who has mail for you |
Suggested CLAUDE.md snippet for poll discipline
When coordinating with a peer session, call mcp__mailbox__peek_inbox
after each subagent completes. If pending > 0, call mcp__mailbox__check_inbox
and treat the messages as input with priority over the current plan.
CLI client mode
Any external process (scripts, UIs, hooks) can talk to a running daemon without needing MCP:
claude-mailbox send --to <mailbox> --from <mailbox> --body <text> [--url http://127.0.0.1:47822]
claude-mailbox peek --name <mailbox> [--url ...]
claude-mailbox check --name <mailbox> [--url ...]
claude-mailbox list [--url ...]
The CLI subcommands are thin HTTP clients against the /v1/* endpoints.
REST surface
| Method | Path | Requires X-Mailbox |
Purpose |
|---|---|---|---|
GET |
/health |
no | { status, version, dbPath } |
POST |
/v1/send |
yes (sender) | { to, body } |
GET |
/v1/peek?name=<mailbox> |
no | read-only status |
POST |
/v1/check-inbox?name=<mailbox> |
yes (must match name) |
consume inbox |
GET |
/v1/list |
no | list all mailboxes |
Development
dotnet build
dotnet test tests/ClaudeMailbox.Tests/ClaudeMailbox.Tests.csproj
dotnet run --project src/ClaudeMailbox -- serve
Test suite covers end-to-end coordination, concurrent check_inbox race safety, and schema idempotency.
Scope
- Loopback bind only (v1). Cross-machine coordination is a future extension — swap the middleware for token auth and change the bind address.
- No auth on loopback. Local filesystem permissions are the trust boundary.
- No message expiry or cleanup. Delivered messages stay as a timeline/audit log.