whatsapp-mcp
Provides tools for interacting with WhatsApp, allowing agents to send and receive messages, send media, search chats, manage groups, and access contact/chat information through a linked WhatsApp device.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@whatsapp-mcpsend a message to Alice: I'm running 10 minutes late"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
whatsapp-mcp 📱
WhatsApp as an MCP server — link your phone once by scanning a QR code, then let any agent read and write your chats. Works with pi, Hermes, Claude Code, Cursor, or literally any Model Context Protocol client. Also usable headless for plain automation (cron, CI, scripts) with no agent at all.
┌──────────────────────────────────────────────────────────────────┐
│ core/whatsapp.mjs — Baileys session + all read/write actions │
│ • QR pairing (scan once, session persists) │
│ • auto-reconnect, auto-restart, QR re-pair on unlink │
│ • on-demand history (no bulk download), date-ranged reads │
│ • one connection shared across pi + hermes + scripts │
└───────────────┬──────────────────────────────────┬───────────────┘
│ │
┌─────────▼─────────────┐ ┌─────────▼───────────────┐
│ server.mjs │ │ pi-extension/index.ts │
│ MCP stdio server │ │ native pi extension │
│ → Hermes, Claude │ │ (pi ships no MCP by │
│ Code, Cursor, any │ │ design — so pi gets │
│ MCP client │ │ the same tools natively)│
└───────────────────────┘ └─────────────────────────┘Quickstart
git clone https://github.com/vimal-v-2006/whatsapp-mcp.git
cd whatsapp-mcp
npm install
### First-time pairing (do this first, once)
```bash
node pair.mjs # prints the QR and waits for you to scanOn your phone: WhatsApp → Settings → Linked devices → Link a device → scan the terminal QR (a PNG copy is saved to ~/.whatsapp-mcp/qr.png if the terminal QR is unreadable).
That's it — you scanned once. The session lives in ~/.whatsapp-mcp/; every future start reconnects silently, even headless.
No QR-friendly terminal? Use a pairing code instead: WhatsApp → Linked devices → Link with phone number. The tool
whatsapp_pairing_codereturns an 8-character code.
Starting the MCP server (any harness, any time after pairing)
node server.mjsWith a saved session it just reconnects silently — no QR.
Pairing got interrupted / stuck? Run
rm -rf ~/.whatsapp-mcpandnode pair.mjsagain. Also make sure no oldnode server.mjsprocess is still running (pkill -f server.mjs) — a zombie server holds the session and blocks fresh QRs.
Related MCP server: WhatsApp MCP Stream
Tools
Tool | Description |
| Link state ( |
| Get the pairing QR (ASCII + PNG path). Scan once; session persists |
| Unlink device, wipe local session, generate a fresh QR |
| 8-char code pairing instead of QR (phone number input) |
| Recent DMs/groups: name, unread count, last message preview |
| Latest N messages — or a window via |
| Send a text message |
| Send image / video / audio / document / sticker from a local file path |
| Revoke a message (by id from |
| Known contacts (JID + name) from synced history |
| Resolve contact by JID/phone/name → existence, LID, profile picture |
| Full-text search. Defaults to the last 2 days; tune with |
| Group subject, description, size, participants |
Identifiers are flexible everywhere: 15551234567@s.whatsapp.net (JID), +15551234567 (phone), or a contact/group name are all accepted by to / chat / group parameters.
Examples
whatsapp_send_message { to: "+15551234567", text: "Deploy done ✅" }
whatsapp_read_messages { chat: "Alice", limit: 10 }
whatsapp_read_messages { chat: "Alice", since: "2026-09-20", limit: 50 } # one specific day
whatsapp_send_media { to: "Team", path: "/tmp/report.pdf", caption: "Q2 numbers" }
whatsapp_search_messages { query: "invoice", days: 7 }With pi
pi intentionally ships no MCP — so this repo includes a native extension that registers the exact same 13 tools. It lives in pi-extension/ and reuses the same core.
Permanent (recommended): add the directory to your pi settings (~/.pi/agent/settings.json):
{
"extensions": ["/path/to/whatsapp-mcp/pi-extension"]
}One-off:
pi -e /path/to/whatsapp-mcp/pi-extension/index.tsThe WhatsApp session starts in the background when pi boots. First run prints the QR to the terminal — scan it, and whatsapp_* tools are live in every pi session. (Project-local .pi/extensions/ also works if you copy the folder in.)
With Hermes
Hermes is a first-class MCP client. One command:
hermes mcp add whatsapp --command node --args /path/to/whatsapp-mcp/server.mjsHermes connects, discovers the 13 tools, and registers them. Verify any time:
hermes mcp list # shows configured servers
hermes mcp test whatsapp # connection + tool discovery checkEquivalent raw config (in Hermes's mcp_servers section of config.yaml):
mcp_servers:
whatsapp:
command: node
args: ["/path/to/whatsapp-mcp/server.mjs"]
# env: # optional, e.g. custom session dir
# WHATSAPP_MCP_DATA_DIR: /home/me/.whatsapp-mcpPer-server extras Hermes supports for this server: tools.include / tools.exclude filters (e.g. expose only send/read tools to a sub-agent) and sampling settings.
Tip: the WhatsApp session keeps running inside the
hermes mcp-spawned server process, so pairing state persists across Hermes restarts — scan once, ever.
With Claude Code
claude mcp add whatsapp -- node /path/to/whatsapp-mcp/server.mjsWith Cursor
Add to ~/.cursor/mcp.json (or the workspace .cursor/mcp.json):
{
"mcpServers": {
"whatsapp": {
"command": "node",
"args": ["/path/to/whatsapp-mcp/server.mjs"]
}
}
}Any other MCP client (generic stdio JSON)
{
"mcpServers": {
"whatsapp": {
"command": "node",
"args": ["/path/to/whatsapp-mcp/server.mjs"]
}
}
}Cline, Continue, Zed, Gemini CLI, OpenCode, Goose… anything that speaks MCP stdio works with this block.
Headless automation (no agent)
The core is a plain ES module — after the first QR pairing you can drive WhatsApp from cron, CI, systemd timers, whatever:
// my-automation.mjs
import * as wa from "/path/to/whatsapp-mcp/core/whatsapp.mjs";
await wa.getSocket({ wait: true }); // reconnects silently (paired already)
await wa.sendMessage("+15551234567", "Backup finished ✅");
const chats = await wa.listChats({ limit: 10 });
const msgs = await wa.readMessages(chats.chats[0].id, { limit: 25 });
const hits = await wa.searchMessages("invoice");Cron example — daily 9am digest of yesterday's unread chats:
0 9 * * * cd /path/to/whatsapp-mcp && node -e '
import("./core/whatsapp.mjs").then(async wa => {
await wa.getSocket({ wait: true });
const { chats } = await wa.listChats({ limit: 20 });
const lines = chats.filter(c => c.unread > 0)
.map(c => `• ${c.name}: ${c.unread} unread`);
await wa.sendMessage("me@s.whatsapp.net", "Morning digest:\n" + (lines.join("\n") || "no unread"));
});' >> /tmp/wa-digest.log 2>&1Run node examples/send-once.mjs for a working sample script.
How it works
Baileys (WhatsApp Web multi-device protocol, pinned to
6.5.0— the last line with the full chat-store API) opens a linked-device session on first run.Pairing: the QR from
connection.updateis rendered to the terminal (stderr) and to~/.whatsapp-mcp/qr.png. Credentials are stored on disk byuseMultiFileAuthState, so restarts are silent.On-demand history (no bulk download): nothing is fetched at process start. The first tool that actually needs history (list/read/search/contacts) triggers a one-time sync of the recent history WhatsApp retains for this account (the same window WhatsApp Web loads), which is cached in memory; later reads/searches filter that cache by
since/until/dayswith zero extra network. (Baileys 6.5 exposes no per-date fetch API — the sync window is the protocol's finest granularity — so "fetch only the last 2 days" is enforced by fetching-once + date-filtering + caching.)One connection, many processes: WhatsApp allows a single active connection per linked device. This project elects one owner process (first to run — pi, hermes, or a script) that holds the Baileys socket; every other process joins it as a client over a loopback-only, token-authenticated local bridge (lock file:
~/.whatsapp-mcp/daemon.json). If the owner exits, the next tool call picks the session back up from the saved credentials. Run pi + hermes + cron scripts at the same time without conflicts.Resilience: connection drops auto-restart (2s;
conflictcloses back off 20–30s with jitter so stray processes can't ping-pong), logout events wipe creds and re-emit a QR (3s), QR is re-rendered whenever the server rotates it.Protocol hygiene: only the MCP JSON-RPC goes to stdout; all logs and the QR go to stderr, so MCP clients stay clean.
Configuration
Env var | Default | Meaning |
|
| Session credentials + |
Troubleshooting
Symptom | Fix |
No QR appears | Check stderr (MCP clients often hide it — run |
| Scan the QR first ( |
Keeps reconnecting | Unstable network, or the phone itself unlinked the device (battery-saver modes can do this) |
Logged out / QR after restart | Someone unlinked the device from the phone; just re-scan |
Empty reads right after a restart | The in-memory cache starts empty; the first read triggers the on-demand sync (a few seconds for the initial snapshot). Retry once, or ask for a specific window ( |
| A process from before an upgrade still holds the same session. Normal operation handles ownership automatically — restart your pi/hermes sessions once so they run the new code |
Update broke things | Baileys is pinned for a reason — don't |
Security & fair use
~/.whatsapp-mcp/contains your full WhatsApp session key — treat it like a password. Don't commit it, don't share it, keep file perms tight (chmod 700).This uses the unofficial WhatsApp Web protocol. It's fine for personal use and moderate automation; aggressive bulk messaging can get your number banned. Be a good citizen: keep volumes human.
Agents can send messages as you. If you expose tools to a sub-agent, consider Hermes-style
tools.excludefilters to hidewhatsapp_send_*from agents that shouldn't write.
Project layout
whatsapp-mcp/
├── core/whatsapp.mjs # Baileys session + actions (the core)
├── core/daemon.mjs # single-owner election + loopback client bridge
├── core/api.mjs # facade: routes each call local or to the owner
├── server.mjs # MCP stdio server
├── pi-extension/index.ts # native pi extension (same 13 tools)
├── examples/send-once.mjs # headless automation sample
├── pair.mjs # node pair.mjs — one-shot QR pairing helper
├── test-client.mjs # npm test — MCP smoke test
└── README.mdLicense
MIT — do whatever, no warranty. Not affiliated with WhatsApp/Meta.
This server cannot be deployed
Maintenance
Related MCP Connectors
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
WhatsApp (Web + Business API), SMS, contacts, and call records via 2Chat's MCP server.
WhatsMCP connects Claude and other MCP-compatible AI agents directly to WhatsApp. Send and receive text, images, documents, and voice notes; manage groups (create, add/remove members, promote admins); look up contacts and profiles; follow channels; and read call and message history — all through a standard MCP interface. For voice use cases, WhatsMCP offers SIP-based calling plans (inbound-only, or full inbound/outbound) so AI voice agents can answer and place WhatsApp calls, plus low-latency WebSocket integrations with voice agent providers like ElevenLabs. Multiple WhatsApp accounts can be paired and managed per workspace, with webhook support for real-time inbound message delivery to your own infrastructure.
Let Claude or ChatGPT search, read and send your WhatsApp messages over MCP. OAuth sign-in.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables sending messages, managing templates, uploading media, and configuring webhooks for WhatsApp Business via the MCP protocol.10 npm5MIT
- AlicenseNot gradedqualityCmaintenanceEnables programmatic WhatsApp automation through MCP, including sending messages, managing chats and contacts, searching conversation history, and exchanging media files.MIT
- AlicenseAqualityCmaintenanceSend WhatsApp messages from any MCP client — text, images and files, plus session management and contact checks. Authenticate by scanning a QR code: no Meta Business approval and no WhatsApp Business account required.946 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to send and receive WhatsApp messages, search chats, share media, manage approvals, and get activity summaries through MCP.Apache 2.0