Skip to main content
Glama
whatsapp-mcp

whatsapp-mcp

by petrkyncl
README.md
# whatsapp-mcp

**Your WhatsApp in Claude, ChatGPT, Cursor and any other MCP client.** Read and search your chats, pull a chat's full history from your phone, let the agent read the PDFs, spreadsheets, Word files, photos and videos people sent you, and send messages, all through the [Model Context Protocol](https://modelcontextprotocol.io).

One Node.js process. Runs locally over stdio, or as a remote server with OAuth that ChatGPT and claude.ai connect to by URL.

<!-- DEMO GIF goes here: ask Claude "what did Tom send me last week? open the spreadsheet" and record the answer -->

> **Unofficial.** This connects to WhatsApp as a linked device (like WhatsApp Web) using the open-source [Baileys](https://github.com/WhiskeySockets/Baileys) library. It is not affiliated with or endorsed by WhatsApp or Meta. Read [the risks](#risks) before you link an account you can't afford to lose.

## What it does

- **Chats and messages**: list chats with unread counts, read a conversation page by page, full-text search across everything.
- **Full history on demand**: when you link a device, WhatsApp only gives it recent messages. `load_full_history` asks your phone for the older ones, the same way WhatsApp Web does when you scroll up (500 messages per request; phones serve roughly the last year).
- **Reads attachments**: `download_media` gives the agent the content, not just a file: photos as images, four frames of a video, the text of PDFs and Word documents, Excel sheets as CSV, CSV/TSV/TXT/JSON as text. Older files are recovered from your phone if WhatsApp no longer has them.
- **Read receipts on your terms**: reading never marks anything as read. `mark_read` does it (blue ticks and the unread badge cleared on all your devices) only when you ask.
- **Sends messages** as you, to a contact, group or phone number.
- **Readable system events, nothing lost**: disappearing messages turned on/off, deletions and edits show up as text. A message deleted for everyone keeps its original text (marked `[deleted by sender]`), an edit replaces it (marked `[edited]`), and messages stay even after they disappear on the phone. A first message that arrived undecrypted is fetched again from the phone when the agent reads the chat.
- **Phone numbers**: chats, contacts, messages and group senders come with the person's phone number when WhatsApp shares it.
- **Handles WhatsApp's two ids per person** (phone number and the newer `@lid` privacy id): messages split between them show up as one chat.
- **Works with today's WhatsApp**: pairing with Baileys 7.0.0-rc14 fails since WhatsApp added a new pairing step (`companion_reg_refresh`). The fix is applied automatically ([details](patches/README.md)).

## Quick start (local)

Requires Node.js 22 or newer.

**1. Link your WhatsApp** (once):

```bash
npx -y @petrkyncl/whatsapp-mcp pair
```

Scan the QR code with WhatsApp → **Settings → Linked devices → Link a device**. Prefer a code? Run `WA_PAIR_PHONE=15551234567 npx -y @petrkyncl/whatsapp-mcp pair` (your number with country code) and choose **Link with phone number instead** on the phone. Keep it running until it says it's synced: the first connection receives your recent messages.

**2. Add it to your MCP client:**

Claude Code:

```bash
claude mcp add whatsapp -- npx -y @petrkyncl/whatsapp-mcp
```

Claude Desktop (`claude_desktop_config.json`), Cursor (`~/.cursor/mcp.json`), Windsurf and others:

```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "npx",
      "args": ["-y", "@petrkyncl/whatsapp-mcp"]
    }
  }
}
```

Then ask: *"Which WhatsApp chats have unread messages?"*, *"Summarize my chat with Anna from last week"*, *"Open the invoice PDF Tom sent me"*.

Your session, messages and downloaded files stay in `~/.whatsapp-mcp` on your machine.

## Remote (ChatGPT, claude.ai, phones)

Clients that connect by URL need a server with a public HTTPS address. `serve` mode adds OAuth 2.1 (dynamic client registration + PKCE): when a client connects, you approve it on a page that asks for your password, and that browser is remembered for a year.

```bash
cp .env.example .env    # set WA_MCP_PASSWORD and WA_PUBLIC_URL
docker compose up -d
docker compose logs -f  # scan the QR code shown here, once
```

Put a TLS reverse proxy in front of port 3000 (Caddy, nginx, Cloudflare Tunnel), for example with Caddy:

```
wa.example.com {
    reverse_proxy 127.0.0.1:3000
}
```

Without Docker: `WA_MCP_PASSWORD=… WA_PUBLIC_URL=https://wa.example.com npx -y @petrkyncl/whatsapp-mcp serve`.

Connect:

- **claude.ai** (web, desktop, mobile): Settings → Connectors → Add custom connector → `https://wa.example.com/mcp`
- **ChatGPT**: turn on developer mode in Settings, then add a custom connector with the URL `https://wa.example.com/mcp` and OAuth authentication
- **Claude Code**: `claude mcp add --transport http whatsapp https://wa.example.com/mcp`

## Tools

| Tool | What it does |
|---|---|
| `list_chats` | Chats (people and groups), most recent first, with phone numbers and unread counts. `unread_only` to see just those. |
| `search_contacts` | Find a contact or chat by name or phone number; returns phone numbers. |
| `list_messages` | Messages of one chat, newest page first; `before` pages back. Says whether the stored history is complete. |
| `search_messages` | Full-text search across all chats or inside one. |
| `load_full_history` | Asks your phone for the older messages of a chat (phone must be online). |
| `download_media` | Downloads a message's file and shows its content: images, video frames, text of PDF/Word/Excel/CSV/TXT. |
| `mark_read` | Marks a chat as read on all your devices (blue ticks). Only when you ask. |
| `send_message` | Sends a text message as you. |

## Configuration

| Variable | Default | |
|---|---|---|
| `WA_MCP_DATA_DIR` | `~/.whatsapp-mcp` | Session, message store and downloaded files. Use a second directory for a second account. |
| `WA_MCP_PASSWORD` | | `serve`: the password on the OAuth consent page. Required. |
| `WA_PUBLIC_URL` | | `serve`: the public HTTPS URL, e.g. `https://wa.example.com`. |
| `WA_MCP_PORT` / `WA_MCP_HOST` | `3000` / `127.0.0.1` | `serve`: where to listen. |
| `WA_PAIR_PHONE` | | Pair with an 8-character code instead of a QR code. |
| `WA_MCP_NAME` | `WhatsApp` | Name shown to clients and on the consent page. |
| `WA_LOG_LEVEL` | `silent` | Baileys' own logging (`info`, `debug`) for troubleshooting. |

Commands: `whatsapp-mcp` (stdio), `whatsapp-mcp pair`, `whatsapp-mcp serve`, `whatsapp-mcp status`.

Only one process can use a WhatsApp session at a time (two connections with the same keys kick each other out). If several clients need the same account, run `serve` once and point them all at it.

## Compared with lharries/whatsapp-mcp

[lharries/whatsapp-mcp](https://github.com/lharries/whatsapp-mcp) made WhatsApp + MCP popular. As of November 2026 its last commit is from July 2025 and it has 274 open issues and pull requests.

| | whatsapp-mcp (this) | lharries/whatsapp-mcp |
|---|---|---|
| Runtime | One Node.js process, `npx` | Go bridge + Python MCP server, two processes |
| WhatsApp library | Baileys 7.0.0-rc14 + current pairing fix | whatsmeow pinned to March 2025 |
| Remote use (ChatGPT, claude.ai, mobile) | Yes, OAuth 2.1 with password | No, local stdio only |
| Older history | `load_full_history` asks the phone | Only what the first sync delivered |
| Attachments | Agent sees the content (images, video frames, PDF/Word/Excel text) | Downloads the file and returns its path |
| Unread counts, mark as read | Yes | No tool for it |
| Send files and voice messages | Not yet | Yes |
| Docker | Yes | No |

## Risks

Read this before linking an account.

- **This is an unofficial client.** It talks to WhatsApp's servers the way WhatsApp Web does, through a reverse-engineered protocol. WhatsApp's [Terms of Service](https://www.whatsapp.com/legal/terms-of-service) don't allow accessing the service through unauthorized or automated means, and WhatsApp's help center says unofficial apps violate its Terms. **WhatsApp can restrict or ban accounts that use them**, temporarily or permanently.
- Ordinary personal use (reading, searching, replying like you would yourself) is what this is built for. Bulk messaging, messaging people who don't know you or automation that looks like spam is what gets accounts banned. Don't.
- Consider a secondary number if losing the account would hurt.
- An agent with `send_message` can send messages as you. Most MCP clients ask before each tool call; keep it that way for sending.
- The message store is a plain SQLite file in your data directory. Anyone with access to that directory can read your messages. In `serve` mode, use a long password and HTTPS.

## How it works

`src/whatsapp.js` runs a Baileys linked device and writes everything it receives into SQLite (`src/store.js`), including the full message of every media message so its file can be downloaded later. History on demand uses WhatsApp's `HISTORY_SYNC_ON_DEMAND` peer-data request; single lost files use the placeholder resend request. The phone files a chat under one of two ids, so both are tried before a chat is called complete. `src/tools.js` defines the MCP tools, `src/http.js` the OAuth server, `src/patches.js` the Baileys fixes.

## Development

```bash
npm install
npm run lint && npm run typecheck && npm test
node src/cli.js pair && node src/cli.js
```

## License

[MIT](LICENSE) © Petr Kynčl

---

Want an AI agent to use a real app on a real phone, not just WhatsApp? See [MationX Android MCP](https://mationx.com/android-mcp).

TDQS

A3.8/5.0

Scored across 8 tools

Disambiguation4/5

Each tool has a distinct primary action and resource: listing chats, searching contacts/messages, loading history, downloading media, marking read, and sending. Minor overlap exists between list_chats and search_contacts, since search_contacts also returns chats, but the descriptions make the intended use clear enough.

Naming Consistency5/5

All tools follow a consistent snake_case verb_noun pattern (list_chats, search_messages, load_full_history, download_media, mark_read, send_message). There are no mixed conventions or vague standalone verbs.

Tool Count5/5

Eight tools is well-scoped for a WhatsApp assistant covering discovery, reading, history loading, media handling, and sending. Each tool earns its place without redundant operations.

Completeness4/5

The surface covers core WhatsApp workflows: listing/searching chats and messages, loading older history, downloading media, marking read, and sending text. Minor gaps remain around sending media, replying/quoted messages, reactions, or group management, but core read/send workflows are covered.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues