zapo ships two optional packages aimed purely at development and testing — neither is meant for production:
- MCP server (
@zapo-js/mcp-server) — expose a liveWaClientto an AI agent (Claude Code, Cursor) so it can connect, pair, send, and inspect state interactively. - Fake server (
@zapo-js/fake-server) — an in-process fake WhatsApp server used for library-internal benchmarks and cross-check tests. For your own app’s E2E tests, see the End-to-end testing guide.
MCP server
It exposes a liveWaClient instance and the zapo-js module namespace as MCP tools. An LLM agent can then drive end-to-end WhatsApp flows — connect, pair, send, query groups/newsletters, inspect events, walk SQL state — without you writing throwaway scripts.
Tool surface
Each tool inlines its own schema and examples — the agent reads them at runtime rather than memorizing flags.
Install & register
tsx — no build step, and zapo-js resolves straight from src/:
Pairing gotcha
client.connect() blocks until pairing finishes, so always start it without awaiting, then poll the event buffer:
auth_qr string to the user, wait for auth_paired, then continue.
Key environment variables
One
WaClient per process (multi-session needs multiple servers with distinct MCP_AUTH_PATH + MCP_SESSION_ID); no auto-reconnect (call connect again on connection: close); restart soft does not pick up code changes while process_exit + a supervisor does. Full reference: packages/mcp-server/README.md.
Fake server
@zapo-js/fake-server is the in-process fake WhatsApp Web server the library uses for cross-check tests and benchmarks. It’s also the recommended way to run end-to-end tests for your own app without touching WhatsApp — see the dedicated End-to-end testing guide, which covers install, programmatic API, FakePeer fixtures, multi-session isolation, and CI recipes.
The rest of this section is scoped to the library-internal use — benchmarking.
Benchmarking
The package ships a messaging profiler (send/recv × 1:1/group) used to track the library’s performance, plus focused scenario suites for connect lifecycle, history sync, bulk usync, group provisioning, media upload, receipts flood, reconnect/resume, app-state, media-on-the-wire, and the Signal retry round-trip:bench:media:messaging sweeps every media type (image / video / audio / ptt / document / sticker) across 1:1 send, group fan-out (SKDM + SKMSG), and receive + download. It defaults to streaming input (Readable.from(...)) so the lib walks its streaming-upload path; switch to in-memory mode with ZAPO_BENCH_MEDIA_INPUT=buffer to A/B.
bench:retry validates the full retry round-trip against wa-web’s reference parser: incoming retry, recovery, and outbound retry replay after the peer rotates its prekey bundle.
Tune the workload with ZAPO_BENCH_* env vars (ZAPO_BENCH_CONTACTS, ZAPO_BENCH_GROUP_MEMBERS, ZAPO_BENCH_MESSAGES, ZAPO_BENCH_SCENARIOS, …) and add --cpu / --heap / --separate-process for profiles. With --separate-process, the bench drives the fake server in a child process over an RPC bridge and emits a matching server-side CPU profile and heap snapshot alongside the lib-side ones.
Pick a store backend with ZAPO_BENCH_STORE (memory, sqlite, postgres, mysql, redis, or mongo) — the same ZAPO_TEST_* connection env vars as the cross-store test harness apply. To sweep every bench across multiple stores in one shot:
--start-docker to bring up the bundled Postgres/MySQL/Redis/Mongo services on ephemeral ports and tear them down at the end. See packages/fake-server/README.md for the full flag reference.
bench:all-stores only sweeps the eight scenario suites (connect-lifecycle, history-sync, bulk-usync, group-provision, media-upload, receipts-flood, reconnect-resume, appstate) plus messaging. The newer bench:media:messaging and bench:retry aren’t in its --benches= set yet; run them directly when you need them.The fake server is an in-process testing harness, not a runtime you deploy. Pair it with the memory store for fast, isolated tests that reset on every run.
