WhatsApp MCP Server
Captures WhatsApp messages via a linked device, stores them locally in SQLite, and provides MCP tools to read, search, and analyze your WhatsApp history, including deleted messages, attachments, and links.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
whatsapp-mcp-server
A local WhatsApp message collector plus a Model Context Protocol (MCP) server that lets LLM clients read and send messages on your own WhatsApp account.
Overview
WhatsApp has no official API for reading a personal account's message history, and its built-in search is unavailable to AI assistants. This project links a companion device with Baileys, stores every incoming message in a local SQLite database, and exposes that database to MCP clients (Claude, Codex, and others) over stdio. Clients can also queue outgoing text or image messages, sent immediately or at a scheduled time. Messages stay on your machine: there is no cloud component and no HTTP listener.
This links a real WhatsApp account as a companion device. Use it only with an account you own and respect the privacy of everyone in your chats. It is not affiliated with or endorsed by WhatsApp/Meta.
Sending safety:
whatsapp_send_messagesends real messages from your personal WhatsApp account, to real people, and they cannot be unsent by this server. Configure your MCP client to require explicit user confirmation (recipient and content) before every call to this tool, and do not auto-approve it.
Related MCP server: whatsapp-profiles
Features
Captures new messages live from the moment the device is paired (full history sync is disabled).
Keeps the text of messages that are deleted after capture and flags them as revoked.
Tracks direct and group chats, push names, contacts, group subjects, attachments and links.
Stores everything in a single SQLite file that is easy to inspect, back up or query directly.
Exposes 12 MCP tools: 10 read-only tools (status, chat listing and lookup, recent messages, text search, date ranges, attachments, links, deleted messages, per-chat summaries) plus sending and outbox status.
Sends text, or a JPEG/PNG/WebP image (up to 10 MiB) with an optional caption, immediately or scheduled for a later time, through an outbox queue dispatched by the collector.
Self-healing collector: exits on disconnect (except logout) or when no connection is established within 120 s, so the supervisor (Docker
restart: unless-stopped, systemd) restarts it cleanly; a heartbeat file drives the Docker healthcheck.Imports WhatsApp
.txtchat exports into the same database.Runs natively (Node.js, optionally under tmux or systemd) or in Docker.
How it works
Two processes share one SQLite database:
WhatsApp servers
^ |
sends | | receives
| v
src/collector.js (Baileys linked device, long-running)
| writes messages, reads/updates outbox
v
messages.sqlite <-- src/import_whatsapp_export.js (one-shot .txt import)
^ reads messages, inserts into outbox
|
src/index.js (MCP server over stdio, started on demand by the MCP client)Process | File | Role |
collector |
| Stays connected to WhatsApp, writes messages to the DB and dispatches the outbox |
mcp |
| Stdio MCP server; queries the DB and enqueues outgoing messages |
importer |
| Parses exported |
Design notes:
The database uses Node's built-in
node:sqlitemodule, so there is no native addon to compile.Deleted messages are detected both from
protocolMessageREVOKE events and from revoke stub updates. The stored row is markedisRevoked=truewithrevokedAt,revokedBy,revokedByMeandrevokeSourceMessageId; the original text is kept.Imported messages get synthetic chat IDs (
import:<hash>) andsource=import, so they never mix with live-captured chats.The MCP server never talks to WhatsApp directly.
whatsapp_send_messageinserts a row into theoutboxtable; the collector polls it every second and sends due messages (see Sending messages).The collector identifies itself as
Browsers.macOS('Desktop'), so the linked device appears on the phone as macOS.
By default all runtime data lives under ~/.local/share/whatsapp-mcp/:
~/.local/share/whatsapp-mcp/
├── auth/ # Baileys pairing credentials
├── messages.sqlite # message database
├── collector.log
├── collector.pid
└── collector.connected # heartbeat, touched every 30 s while connectedRequirements
Node.js 22.5 or later (for
node:sqlite), or Docker with ComposeA WhatsApp account on a phone, for pairing
tmux(optional, forbin/start-collector.sh)python3(only for thebin/mcp-*.shtest helpers)
Quick start
Native:
Install dependencies:
npm installStart the collector in the foreground to display the pairing QR code:
npm run collectorOn the phone, open Settings > Linked devices > Link a device and scan the QR code.
Check the result:
npm run statusOutput includes
auth=readyand the database path once pairing succeeded.
Docker:
Build and start the collector:
docker compose up -d --build collector docker compose logs -f collectorWhen the log shows
Scan the QR code in WhatsApp > Linked devices., scan it on the phone.List the MCP tools through the container:
bash bin/mcp-run-list-tools.sh
With Docker, data is persisted in ./data next to compose.yml (./data/auth/,
./data/messages.sqlite, ./data/collector.pid).
Configuration
All configuration is through environment variables.
Variable / key | Required | Default | Description |
| No |
| Base directory for auth, database, log and pid file ( |
| No |
| Baileys (pino) log level |
| No |
| tmux session used by the start/stop/status scripts |
| No |
| systemd user unit inspected by |
| No | repository root | Directory |
| No | empty | Sender name in |
| No |
| Prefix added to bare 10/11-digit local numbers when sending; empty disables it |
| For remote |
| SSH target used by |
| For remote |
| Compose stack directory on the remote host |
Usage
MCP client configuration
The server speaks stdio, not HTTP.
Native:
{
"command": "node",
"args": ["src/index.js"],
"cwd": "/path/to/whatsapp-mcp-server"
}Docker (uses the mcp service in the manual profile):
docker compose run --rm -T mcpRemote Docker host over SSH:
WHATSAPP_MCP_REMOTE_HOST=user@your-docker-host \
WHATSAPP_MCP_REMOTE_STACK_DIR=/opt/whatsapp-mcp \
bash bin/mcp-remote-stdio.shMCP tools
Tool | Description |
| Collector status, auth state, database stats and local paths |
| Known chats, newest first |
| Find chat IDs by contact name, group name or partial JID |
| Recent stored messages, optionally for one chat |
| Case-insensitive substring search over message text |
| Messages in a date/time range, globally or for one chat |
| Media/document messages, filterable by chat or type |
| Messages that contain URLs |
| Messages captured and later revoked |
| Statistical summary of a chat (participants, counts, links, media) |
| Sends (or schedules) text or an image with caption from your account; require confirmation |
| Status of one outbox entry, or the most recent entries |
Sending messages
whatsapp_send_message arguments:
Argument | Description |
| Full JID ( |
| Text, or the caption when an image is sent |
| Optional JPEG, PNG or WebP as base64 or a |
| Optional ISO 8601 datetime (e.g. |
| Default |
| 1 to 30, default 10 |
Flow:
The MCP server validates the input (non-empty text or a valid image), normalizes the recipient and inserts a
pendingrow into theoutboxtable.The collector, while connected, polls the outbox every second and takes up to 5 due messages (
scheduled_atempty or in the past), marks eachsending, and sends it.On success the row becomes
sentwithsent_atand the WhatsAppmessage_id, and the stored image bytes are discarded. On error it becomesfailedwith the error text. Failed messages are not retried automatically.
Statuses: pending (queued, or waiting for its schedule), sending, sent, failed. The tool
returns scheduled for future messages, pending when not waiting or when the timeout elapsed
before confirmation (the message is still queued and will go out once the collector is connected).
Use whatsapp_outbox_status with outbox_id to follow up.
Helper scripts
Script | What it does | Changes state? |
| Starts the collector in a detached tmux session | Yes |
| Kills the tmux session and the pid in | Yes |
| Prints systemd/tmux/pid state and DB/auth presence | No |
| Emits the JSON-RPC lines for | No |
| Emits the JSON-RPC lines for one | No |
| Pipes | No |
| Pipes | No |
| Runs the MCP container on a remote host over SSH | No |
Examples:
bash bin/mcp-run-tool.sh whatsapp_recent_messages '{"limit":5,"include_from_me":true}'
bash bin/mcp-run-tool.sh whatsapp_search_messages '{"query":"invoice","limit":10}'
bash bin/mcp-run-tool.sh whatsapp_outbox_status '{"limit":5}'
# Native piping without Docker
bash bin/mcp-list-tools.sh | node src/index.jsImporting WhatsApp exports
WHATSAPP_EXPORT_OWNER_NAME="Your Name" npm run import-export -- "/path/to/exported/chats"The importer walks the folder recursively, parses every .txt file (US date format
M/D/YY, H:MM - Sender: text), handles multi-line messages, ignores other files such as .vcf,
and prints a JSON summary.
Resetting the pairing (Docker)
docker compose stop collector && rm -rf data/auth && docker compose up -d collectorLimitations
No history backfill: only messages received after pairing are captured (plus
.txtimports).If a delete event arrives before the original message is stored, the text cannot be recovered; the collector logs the revoke for an unknown message.
Search is a SQL
LIKEsubstring match, not ranked full-text search.The
.txtimporter only understands the US-style export format (M/D/YY, H:MM -). Exports from other locales are skipped or have day and month swapped.Baileys is an unofficial client; WhatsApp protocol changes can break the collector until the dependency is updated.
Sending is fire-and-forget: there is no read receipt tracking, no automatic retry of
failedmessages and no way to cancel a scheduled message through MCP (delete or update theoutboxrow in SQLite instead). Scheduled messages only go out while the collector is connected.The collector exits on disconnect instead of reconnecting in-process, so it needs a supervisor (Docker restart policy or systemd
Restart=always).bin/start-collector.sh(tmux) does not restart it.bin/mcp-remote-stdio.shdisables SSH host key checking (StrictHostKeyChecking=no).
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read, search and reply to your WhatsApp chats from your AI, using your own number.
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
Connect your own WhatsApp number to Cursor, Claude and ChatGPT: catch up, search, send replies.
Read-only WhatsApp MCP for your AI agent: it reads the chats you choose. Try the public demo.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with your personal WhatsApp account to search messages, list chats, and send messages. It stores all authentication and message data locally using SQLite for privacy and direct multi-device API connection.15 npm1ISC
- AlicenseNot gradedqualityCmaintenanceEnables local querying of WhatsApp message history via SQLite, with profile separation, media transcription, and operational summaries.1MIT
- AlicenseNot gradedqualityAmaintenanceLets AI agents search and read your personal Telegram and WhatsApp conversations through a self-hosted, read-only MCP server backed by a single SQLite file.2AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to read WhatsApp chat history from a SQLite archive, optionally scrape live chats, and send messages through a chain of safety guards.44 npmMIT