# 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 ```powershell 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: 1. **Manual.** `claude-mailbox serve` in a terminal. 2. **Startup shortcut.** Shortcut to `claude-mailbox serve` in `shell:startup`. 3. **Windows Service (recommended).** See below. ### Windows Service Install (admin shell): ``` claude-mailbox install-service [--port 47822] [--bind 127.0.0.1] [--db-path ] ``` This: - Creates `%ProgramData%\ClaudeMailbox\` with ACLs for `LocalService` - Seeds `mailbox.json` with the defaults (or your flag overrides) — only on first install - Registers the service via `sc.exe create`, running as `NT AUTHORITY\LocalService` with `start= 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): ```json { "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 --from --body [--url http://127.0.0.1:47822] claude-mailbox peek --name [--url ...] claude-mailbox check --name [--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=` | no | read-only status | | `POST` | `/v1/check-inbox?name=` | 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.