Skip to main content
zapo ships two optional packages aimed purely at development and testing — neither is meant for production:
  • MCP server (@zapo-js/mcp-server) — expose a live WaClient to 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

Development & testing only. @zapo-js/mcp-server is a debugging aid, not a production protocol server. It exposes a live WaClient — and the whole zapo-js module — to an AI agent that can send messages, read state, and run arbitrary library calls on a real WhatsApp account. Run it only against accounts you control.
It exposes a live WaClient 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

Register with Claude Code at user scope (build first), so it works from any directory:
For tight iteration on the library itself, register the source through tsx — no build step, and zapo-js resolves straight from src/:
An HTTP transport with node --watch gives the smoothest dev loop: edit a .ts → the process restarts → the next tool call reconnects automatically, with no manual /mcp reconnect. See the package README for the dev script and HTTP setup.

Pairing gotcha

client.connect() blocks until pairing finishes, so always start it without awaiting, then poll the event buffer:
Surface the 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:
Add --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.
Last modified on July 24, 2026