WhatsApp MCP Server
by cascodigital
README.md
# WhatsApp MCP Server
A local-first WhatsApp message collector built on [Baileys](https://github.com/WhiskeySockets/Baileys),
paired with a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that lets
LLM clients (Claude, Codex, etc.) **read and search your own WhatsApp history** stored in a local
SQLite database.
Nothing leaves your machine: messages are captured by your own linked device, persisted locally,
and exposed only over MCP stdio.
> **Heads up:** 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.
## Features
- **Live capture** of new messages from the moment the device is paired (no history backfill).
- **Deleted-message retention**: if a captured message is later revoked, the text is kept and the
record is flagged instead of being lost.
- **Group / direct awareness**, push names, attachments and links indexing.
- **SQLite storage** — easy to inspect, back up, or query directly.
- **MCP tools** for status, listing chats, recent messages, full-text search, date ranges,
attachments, links, deleted messages and chat summaries.
- **Optional import** of WhatsApp `.txt` chat exports.
- Runs natively (Node) or in **Docker**.
## Architecture
Two processes share one SQLite database:
| Process | File | Role |
|-------------|-------------------|-------------------------------------------------------------|
| `collector` | `src/collector.js`| Stays connected to WhatsApp, writes incoming messages to DB |
| `mcp` | `src/index.js` | Stdio MCP server, read-only queries against the same DB |
By default everything lives under `~/.local/share/whatsapp-mcp/`:
```
~/.local/share/whatsapp-mcp/
├── auth/ # Baileys credentials (pairing)
├── messages.sqlite # the message database
├── collector.log
└── collector.pid
```
Override the location with `WHATSAPP_MCP_HOME`.
## Requirements
- Node.js 22+ (or Docker)
- A WhatsApp account on your phone for pairing
## Quick start (native)
```bash
npm install
# 1. Run the collector in the foreground to display the pairing QR code
npm run collector
```
On your phone: **Settings → Linked devices → Link a device**, then scan the QR code.
Once paired, you can run the collector in the background via tmux:
```bash
bash bin/start-collector.sh # start
tmux attach -t whatsapp-mcp-collector # inspect (detach: Ctrl+B then D)
bash bin/stop-collector.sh # stop
```
The device will appear on your phone as `macOS` (the collector uses
`Browsers.macOS('Desktop')`).
## Quick start (Docker)
```bash
docker compose up -d --build collector
docker compose logs -f collector
```
When you see `Scan the QR code in WhatsApp > Linked devices.`, scan it on your phone.
Persistent data lives in `./data` next to `compose.yml`:
- auth: `./data/auth/`
- database: `./data/messages.sqlite`
- pidfile: `./data/collector.pid`
Common operations:
```bash
docker compose ps
docker compose logs --tail=50 collector
docker compose stop|start|restart collector
# reset pairing
docker compose stop collector && rm -rf data/auth && docker compose up -d collector
```
## Using the MCP server
The MCP server speaks **stdio**, not HTTP. Point your MCP client at one of:
**Native:**
```json
{
"command": "node",
"args": ["src/index.js"],
"cwd": "/path/to/whatsapp-mcp-server"
}
```
**Docker:**
```bash
docker compose run --rm -T mcp
```
**Remote Docker over SSH** — `bin/mcp-remote-stdio.sh` runs the stdio MCP on another host.
Configure it with environment variables (no values are hardcoded):
```bash
WHATSAPP_MCP_REMOTE_HOST=user@your-docker-host \
WHATSAPP_MCP_REMOTE_STACK_DIR=/opt/whatsapp-mcp \
bash bin/mcp-remote-stdio.sh
```
For quick manual testing without writing JSON-RPC by hand:
```bash
bash bin/mcp-run-list-tools.sh
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":"hello","limit":10}'
```
### Available MCP tools
| Tool | Description |
|-------------------------------|--------------------------------------|
| `whatsapp_status` | Collector / connection status |
| `whatsapp_list_chats` | List known chats |
| `whatsapp_find_chat` | Resolve a chat by name/JID |
| `whatsapp_recent_messages` | Most recent messages |
| `whatsapp_search_messages` | Full-text search |
| `whatsapp_messages_by_date` | Messages within a date range |
| `whatsapp_list_attachments` | Attachments index |
| `whatsapp_list_links` | Links index |
| `whatsapp_deleted_messages` | Messages revoked after capture |
| `whatsapp_summarize_chat` | Summarize a chat |
## Deleted messages
This server tries to keep the text of messages that are deleted **after** they were received:
- If the message was persisted first and the revoke event arrived later, the text stays in the DB.
- The record is marked `isRevoked=true`, with `revokedAt`, `revokedBy`, `revokedByMe` and
`revokeSourceMessageId`.
**Limitation:** if the delete event arrives *before* the original message is persisted, there is no
text to recover. The collector logs that it received a revoke for an unknown message.
## Importing WhatsApp exports
To import a `.txt` chat export:
```bash
npm run import-export -- "/path/to/exported/chat/folder"
```
The importer:
- ignores `.vcf` files
- handles multi-line messages
- marks records with `source=import`
- uses synthetic chat IDs so imports never mix with live capture
## Configuration
| Variable | Default | Purpose |
|---------------------------------|----------------------------------------|----------------------------------|
| `WHATSAPP_MCP_HOME` | `~/.local/share/whatsapp-mcp` | Base dir for auth/db/logs |
| `WHATSAPP_MCP_TMUX_SESSION` | `whatsapp-mcp-collector` | tmux session name |
| `WHATSAPP_MCP_SYSTEMD_SERVICE` | `whatsapp-mcp-collector.service` | systemd user unit name |
| `WHATSAPP_BAILEYS_LOG_LEVEL` | `warn` | Baileys log verbosity |
| `WHATSAPP_MCP_REMOTE_HOST` | — | SSH target for remote stdio MCP |
| `WHATSAPP_MCP_REMOTE_STACK_DIR` | — | Remote compose stack directory |
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues