╭──────────────────────────────────╮
│ ╔╗ ╔═╗╔═╗╔═╗╔═╗╦═╗╔╗ ╔═╗ ╦ ╦ │
│ ╠╩╗╠╣ ╠╣ ╠═╝╠╣ ╠╦╝╠╩╗║ ║ ╚╦╝ │
│ ╚═╝╚═╝╚═╝╩ ╚═╝╩╚═╚═╝╚═╝ ╩ ╩ │
│ one agent ──→ 50+ messengers │
╰──────────────────────────────────╯
Plug your AI agent into 50+ messengers through a single MCP endpoint — in Docker, or as a one-line npx.
WhatsApp, iMessage, Signal, Telegram, Discord, Slack, Messenger, Instagram, LinkedIn, Google Messages, Matrix — everything Beeper bridges, reachable from one HTTP or MCP endpoint instead of 50 per-platform SDKs, OAuth dances, and rate-limit quirks. If you only need Telegram, this is overkill — use openclaw or any BotFather library. If you need reach across many networks from one agent, keep reading.
Same MCP server, same 12 tools, same serverInfo.version — by construction, because both modes run the same single file. Pick by where Beeper lives:
| Container | Lite (npx) |
|
|---|---|---|
| Beeper Desktop | bundled, headless, in Docker | you supply it (already open on your machine) |
| Needs | Docker + compose | just Node 18+ |
| Start | docker compose up -d |
npx beeperbox |
| Best for | always-on, VPS, headless | laptop users with Beeper already running |
| First-run login | noVNC at :6080 |
already done in your local Beeper |
The container is the full appliance (headless Beeper + raw API + MCP). Lite mode is just the MCP verb layer pointed at a Beeper you already run — no Docker, no Electron, no Xvfb. New in v0.8.0.
Prereqs: Docker + compose plugin, ~1 GB disk, ~600 MB RAM, a Beeper account.
1. Pull and run
curl -LO https://raw.githubusercontent.com/hamr0/beeperbox/master/docker-compose.yml
docker compose up -dPulls the pre-built multi-arch image (ghcr.io/hamr0/beeperbox:latest, linux/amd64 + linux/arm64). No clone, no build. Pin a version with BEEPERBOX_IMAGE_TAG=0.8.0 docker compose up -d, or track master with :edge (may break).
2. Log in once
Open http://localhost:6080/vnc.html, sign into Beeper, then Settings → Developers → enable the API and create an access token. Save it:
echo "BEEPER_TOKEN=abc123..." > .env
docker compose up -dLogin and bridge state persist in a named volume — you won't log in again after restarts, and docker restart recovers cleanly (the entrypoint clears the stale display lock that used to wedge a restarted container).
3. Talk to it
# Raw Beeper Desktop API
curl -H "Authorization: Bearer $BEEPER_TOKEN" http://localhost:23373/v1/info
# MCP server (HTTP transport)
curl -X POST http://localhost:23375 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'For stdio MCP, point any MCP client at docker exec -i beeperbox node /opt/mcp/server.js --stdio. Works with Claude Code, Cursor, Cline, Continue, bareagent, or anything that speaks Model Context Protocol.
Done.
| Host | Purpose | Bound to |
|---|---|---|
6080 |
noVNC web UI — first-run login only | 127.0.0.1 |
23373 |
Raw Beeper Desktop HTTP API | 127.0.0.1 |
23375 |
Opinionated 12-tool MCP server | 127.0.0.1 |
All three are env-overridable (BEEPERBOX_NOVNC_PORT, BEEPERBOX_HOST_PORT, BEEPERBOX_MCP_PORT) so you can run multiple instances on one VPS. For remote access use SSH tunnel, Tailscale, or a TLS reverse proxy — never drop the 127.0.0.1 prefix.
Lite mode runs only the MCP verb server against a Beeper Desktop you already run locally — no Docker, no Electron, no Xvfb. It's the same single file the container runs, so the tool surface and serverInfo.version are identical by construction.
Prereqs: Beeper Desktop running locally, with the Developer API enabled — Settings → Developers → enable the API and create an access token (the same token the container uses).
Run it:
BEEPER_TOKEN=your-token-here npx beeperboxMCP HTTP server comes up on http://127.0.0.1:23375, pointed at the local Beeper API on http://127.0.0.1:23373. On boot it logs a one-line reachability verdict so a bad token or unreachable API is obvious immediately:
[beeperbox-mcp] preflight OK: http://127.0.0.1:23373 reachable, token accepted, 4 account(s)
For stdio transport (Claude Code, Cursor, Cline, Continue, bareagent), add --stdio:
BEEPER_TOKEN=your-token-here npx beeperbox --stdioEnv contract:
| Env | Meaning | Default |
|---|---|---|
BEEPER_API |
Local Beeper Desktop API base | http://127.0.0.1:23373 |
BEEPER_TOKEN |
Beeper dev token (Settings → Developers) | — (required) |
MCP_PORT |
MCP HTTP port | 23375 |
MCP_AUTH_TOKEN |
Optional bearer guard on the MCP endpoint | unset (open on loopback) |
MCP_ALLOWED_HOSTS |
Host/Origin allowlist | localhost,127.0.0.1,::1 |
MCP_BIND_ADDR |
Interface the MCP server binds | 127.0.0.1 (loopback) |
Security: lite mode binds loopback only (127.0.0.1) by default, so it's safe with no auth — only processes on your machine (your agent, Claude Code) can reach it. Do not just flip it to 0.0.0.0: a same-network attacker can spoof the Host header past the allowlist and reach the full tool surface (read every message, send across every network) unauthenticated. To expose it deliberately, set MCP_BIND_ADDR=0.0.0.0 and MCP_AUTH_TOKEN, and front it with a tunnel (SSH / Tailscale / TLS reverse proxy) — never raw on a public interface. (The container binds 0.0.0.0 on purpose because Docker publishes it on 127.0.0.1 — that loopback publish is its boundary; lite mode has no such layer, which is why its bind is loopback.)
Supervision: no Docker restart policy here — for an always-on lite setup, run it under systemd or pm2.
What lite mode is not: it does not bundle or headless-run Beeper (that's the container's job). No new verbs, no transport changes — it's the same server, packaged and safe to run standalone.
Not a thin proxy over Beeper's raw API — an opinionated 12-tool verb layer built for an LLM to drive. Every tool returns one normalized Chat / Message schema (so the agent never learns a second shape), propagates chat_id + network onto every message (no second lookup to know where a hit came from), and is documented in-schema for the model. Reach across all 50+ networks; the agent never knows which bridge it's talking to.
Read / triage
| Tool | What it does |
|---|---|
list_accounts |
Which networks are connected (WhatsApp, Telegram, Discord …) — slug + label + display name |
list_inbox |
Most recently active chats, with unread counts and last-activity time |
list_unread |
The "what needs me right now?" view — only chats with unread_count > 0 |
get_chat |
One chat's current metadata by ID |
read_chat |
Recent messages of a chat, chronological, normalized |
search_messages |
Full-text search across every chat |
Write / act
| Tool | What it does |
|---|---|
send_message |
The headline write — reply or initiate; markdown, reply_to_message_id, returns the new message ID |
note_to_self |
The agent's private command/control channel — recorded, excluded from every inbox view |
react_to_message |
Lightest "I saw it" — a unicode emoji, visible to the sender on every network |
archive_chat |
The "done with this conversation" primitive (Beeper exposes no mark-as-read) |
Watch / reach — the last two releases
| Tool | What it does |
|---|---|
poll_messages |
Read-only watch primitive: "what arrived since this cursor?" Seed once, persist the opaque cursor, poll with zero side effects. The cursor is restart-safe — survives a container/process restart with no missed or duplicated messages. Each message carries a source field ("api" for beeperbox's own sends, "external" otherwise) so a poll loop never answers itself. (v0.6.0) |
download_asset |
The MCP-only way to reach attachment bytes (base64). Every Message now carries attachments[] ({type, file_name, mime_type, src_url, size, is_voice_note}); fetch by src_url or by chat_id+message_id. Byte-capped and timeout-bounded; a defense-in-depth guard refuses file:// paths outside Beeper's media cache. (v0.7.0) |
Reliable echo-suppression (source + the optional client_tag idempotency tag) means an agent on a poll loop can send and watch the same chat without mistaking its own messages for inbound — the wiring that lets multis drop its text-prefix hacks.
Only if you're hacking on the image itself or running air-gapped:
git clone https://github.com/hamr0/beeperbox.git && cd beeperbox
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build- docs/GUIDE.md — human walkthrough: first-run login, multi-instance VPS pattern, read-only vs read-write tokens, troubleshooting
- beeperbox.context.md — drop-in integration guide for AI assistants: MCP tools, schemas, wiring snippets for Claude Code / Cursor / Cline / bareagent, error codes
- CHANGELOG.md — version history and versioning policy. tl;dr MINOR = new runtime behavior (new MCP tool, new architecture, new transport), PATCH = bug fixes + packaging + docs.
MAJORheld at0until the MCP tool set and HTTP API are declared stable.
Local-first, composable agent infrastructure. Same API patterns throughout — mix and match, each module works standalone.
Core — the brain, the gate, the memory.
- bareagent — the think→act→observe loop. Goal in → coordinated actions out. Replaces LangChain, CrewAI, AutoGen.
- bareguard — the single gate every action passes through. Action in → allow / deny / ask-a-human out. Replaces hand-rolled allowlists and scattered policy code.
- litectx — tree-sitter code + memory graph with activation decay, plus lightweight context engineering (write · select · compress · isolate). Query in → ranked context out.
Optional reach — give the agent hands.
- barebrowse — a real browser for agents. URL in → pruned snapshot out. Replaces Playwright, Selenium, Puppeteer.
- baremobile — Android + iOS device control. Screen in → pruned snapshot out. Replaces Appium, Espresso, XCUITest.
- beeperbox — 50+ messaging networks via one MCP server (headless Beeper Desktop in Docker). Chat in → unified message stream out. Replaces Twilio, per-platform bot APIs.
Apache-2.0. Independent wrapper around Beeper Desktop, no affiliation with Beeper / Automattic.
- Beeper Desktop — upstream app this containerizes
- Beeper Desktop API — official API reference
- bareagent — lightweight agent orchestration that consumes beeperbox via MCP
- multis — personal-assistant project that drove beeperbox's extraction