Skip to main content
Glama
wsti-studio

WhatsApp MCP

by wsti-studio
README.md
# WhatsApp MCP

An MCP server that gives Claude read and write access to WhatsApp, through a
self-hosted [Evolution API](https://github.com/EvolutionAPI/evolution-api)
gateway. Dependency-free: one file, Node's built-in `fetch`, stdio transport.

Your number stays linked on your own machine. No third party sees the messages.

## Tools

| Tool | What it does |
|---|---|
| `connection_status` | Is the number linked and online. |
| `list_chats` | Recent chats, newest first, with JIDs and unread counts. |
| `list_messages` | Messages in one chat. Each carries an `id`; attachments carry a `media_type`. |
| `get_media` | Download the attachment on a message. Images come back viewable inline. |
| `search_contacts` | Match contacts by name or number substring. |
| `check_number` | Is a phone number registered on WhatsApp. |
| `list_groups` | Groups this number belongs to, with JIDs. |
| `send_message` | Send a text message. The only tool with an outbound side effect. |
| `reconnect` | Returns a pairing QR when the link has dropped. |
| `restart_instance` | Bounce a stuck instance. Does not unlink the number. |

## Requirements

A running Evolution API instance with a linked WhatsApp number. This server is
only a client; it does not start or manage the gateway.

## Configure

All configuration is environment variables:

| Variable | Default | Meaning |
|---|---|---|
| `EVO_APIKEY` | (required) | Global API key, `AUTHENTICATION_API_KEY` in Evolution's `.env`. |
| `EVO_URL` | `http://localhost:8080` | Base URL of the Evolution API server. |
| `EVO_INSTANCE` | `primary` | Instance name for your number. |
| `EVO_MEDIA_DIR` | `media/` beside `server.js` | Where `get_media` saves attachments. |
| `EVO_QR_PATH` | `<instance>-qr.png` beside `server.js` | Where `reconnect` writes the pairing QR. |

Register it with Claude Code:

```bash
claude mcp add whatsapp -s user \
  -e EVO_APIKEY=your-key \
  -e EVO_URL=http://localhost:8080 \
  -e EVO_INSTANCE=primary \
  -- node /path/to/whatsapp-mcp/server.js

claude mcp list   # expect: whatsapp ... Connected
```

Restart Claude Code afterwards. Tool lists are read once at session start, so a
newly added server (or a newly added tool) will not appear in a session that was
already running.

## Test

```bash
EVO_APIKEY=your-key npm test
```

An integration check against the live gateway, no mocks: it spawns a real server
process, finds a recent image on its own, and asserts `get_media` returns decoded
image bytes and writes them to disk. Pin a specific message with
`WA_TEST_MESSAGE_ID` if you would rather not have it search.

## Notes

- `get_media` inlines images up to 3.5 MB; anything larger, and any non-image, is
  saved to disk and the path is returned instead.
- Downloads are pruned after 24 hours so a chat full of photos cannot quietly
  grow into a disk problem.
- Media only downloads while it is still on WhatsApp's servers. Very old
  attachments can come back empty.