Architecture overview
One Node 24 process (session-bus serve) owns one SQLite database and exposes 7 MCP tools over Streamable HTTP. Claude Code connects to it as an HTTP MCP server. An optional per-session stdio shim polls it and pushes new mail into an idle session.
Components
| Component | What it is | Writes |
|---|---|---|
serve | HTTP MCP server, stateless: one MCP server object per request. | bus.db, bus.db.lock |
| Admin CLI | principal, token, session release, doctor, backup, restore. Runs on the bus host and opens the DB directly. | bus.db |
channel (shim) | stdio MCP server for one session. HTTP client of the bus. | shim-<name>.lock, shim-<name>.json |
scripts/bus-headers.sh | Claude Code headersHelper. Prints the Authorization header. | nothing |
Two ways to reach the bus
- Tailscale serve (default).
servelistens on127.0.0.1:47910.tailscale serveexposes it ashttps://<bus-host>.<tailnet>.ts.net:8443/mcp. Needs HTTPS certificates enabled on the tailnet. - Direct tailnet bind (fallback).
BUS_HOST=$(tailscale ip -4)makesservelisten on the host's tailnet address. Reached athttp://<bus-host>.<tailnet>.ts.net:47910/mcp. Traffic is still inside the tailnet's WireGuard tunnel.
Any other bind address is refused. See Security model.
Dependencies
Runtime: @modelcontextprotocol/sdk, zod and @cogs/auth (token minting and verification). Storage is the built-in node:sqlite. There is no web framework and no external database.
Sizes, for orientation
src/ is about 1,600 lines of TypeScript across 16 files. bash scripts/gate.sh 6 runs the typecheck, build, the Vitest suite, scripts/smoke.sh, scripts/e2e.sh and the documentation checks.