WA MCP
by delltrak
README.md
<p align="center">
<img src="https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white" alt="WhatsApp" />
<img src="https://img.shields.io/badge/MCP-000000?style=for-the-badge&logo=anthropic&logoColor=white" alt="MCP" />
<img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
<img src="https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white" alt="Docker" />
</p>
<h1 align="center">π’ WA MCP</h1>
<p align="center">
<strong>The first WhatsApp integration built natively for AI Agents.</strong>
<br />
<em>Full MCP server exposing WhatsApp as discoverable tools, resources, and real-time notifications.</em>
</p>
<p align="center">
<a href="#-quick-start">Quick Start</a> β’
<a href="#-features">Features</a> β’
<a href="#-tools">Tools</a> β’
<a href="#-architecture">Architecture</a> β’
<a href="#%EF%B8%8F-configuration">Configuration</a> β’
<a href="#-docker">Docker</a> β’
<a href="#-contributing">Contributing</a>
</p>
<p align="center">
<a href="https://github.com/delltrak/wamcp/actions/workflows/ci.yml"><img src="https://github.com/delltrak/wamcp/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
<img src="https://img.shields.io/github/license/delltrak/wamcp?style=flat-square" alt="License" />
<img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square" alt="Node" />
<img src="https://img.shields.io/badge/MCP-Streamable%20HTTP-blue?style=flat-square" alt="Transport" />
</p>
---
## π€ What is WA MCP?
**WA MCP** is a WhatsApp MCP server built with TypeScript that gives AI agents full access to WhatsApp through the [Model Context Protocol](https://modelcontextprotocol.io). It supports both **Baileys** (WhatsApp Web) and **Meta Cloud API** as dual-channel backends, deployable with **Docker** in a single command.
Your agent connects once and auto-discovers **63 tools**, **10 resources**, and **12 real-time events** β zero configuration, zero REST wrappers, zero glue code.
```
Your AI Agent ββ MCP Protocol ββ WA MCP ββ WhatsApp
```
Instead of writing HTTP clients, parsing webhook payloads, and mapping endpoints to tools manually β your agent just **connects and goes**. Works out of the box with **Claude**, **Google ADK**, **LangChain**, and any MCP-compatible AI agent framework.
> π‘ **MCP** (Model Context Protocol) is the open standard for connecting AI agents to tools and data. WA MCP speaks MCP natively via Streamable HTTP and stdio transports.
---
## π Quick Start
### One command with Docker
```bash
docker compose up
```
That's it. WA MCP + Redis, ready on `http://localhost:3000/mcp`.
### Or run locally
```bash
# Prerequisites: Node.js >= 22, Redis running
npm install
cp .env.example .env
# Development (stdio transport)
npm run dev
# Production (HTTP transport)
npm run build && npm start
```
### Connect your agent
<details>
<summary>π Google ADK (Python)</summary>
```python
from google.adk.tools.mcp_tool import McpToolset
tools = McpToolset(url="http://localhost:3000/mcp")
# Agent auto-discovers 63 WhatsApp tools
# wa_create_instance, wa_send_text, wa_send_image, ...
```
</details>
<details>
<summary>π¦ LangChain</summary>
```python
from langchain_mcp import McpToolkit
toolkit = McpToolkit(server_url="http://localhost:3000/mcp")
tools = toolkit.get_tools()
```
</details>
<details>
<summary>π» Claude Desktop</summary>
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"whatsapp": {
"command": "node",
"args": ["path/to/wa-mcp/dist/index.js"],
"env": {
"WA_TRANSPORT": "stdio",
"WA_REDIS_URL": "redis://localhost:6379"
}
}
}
}
```
</details>
---
## β¨ Features
| | Feature | Description |
| --- | ---------------------- | --------------------------------------------------------------------------------------------------------- |
| π | **MCP-native** | Streamable HTTP + stdio transports. No REST, no webhooks. |
| π± | **Dual-channel** | Baileys (WhatsApp Web) + Meta Cloud API β same interface. |
| π | **Multi-instance** | Run 1β50 WhatsApp numbers from a single server. |
| π¨ | **Full messaging** | Text, images, video, audio, documents, polls, reactions, replies, forwards, edits, deletes, view-once. |
| π₯ | **Groups** | Create, manage members, promote/demote admins, settings, invite links, join requests, ephemeral messages. |
| π€ | **Contacts & Profile** | Number check, block/unblock, business profiles, privacy, status updates. |
| π‘ | **Real-time events** | 12 notification types via SSE: messages, typing, groups, calls, connection status. |
| β‘ | **Rate limiting** | BullMQ queues prevent WhatsApp bans (20 msg/min Baileys, 80 msg/min Cloud). |
| π | **Auto-reconnect** | Automatic reconnection with exponential backoff. |
| ποΈ | **Persistent** | SQLite storage for sessions, messages, contacts, groups. |
| π³ | **Single container** | `docker compose up` β only Redis as external dependency. |
---
## π οΈ Tools
WA MCP exposes **63 tools** across 9 domains. All tools use the `wa_` prefix.
<details>
<summary>π <strong>Instance Management</strong> (8 tools)</summary>
| Tool | Description |
| -------------------------- | -------------------------------- |
| `wa_create_instance` | Create a new WhatsApp connection |
| `wa_connect_instance` | Connect (generates QR code) |
| `wa_disconnect_instance` | Gracefully disconnect |
| `wa_delete_instance` | Permanently remove instance |
| `wa_restart_instance` | Disconnect + reconnect |
| `wa_get_qr_code` | Get QR as base64 (Baileys) |
| `wa_get_pairing_code` | Get pairing code (Baileys) |
| `wa_set_cloud_credentials` | Set Cloud API token |
</details>
<details>
<summary>π¬ <strong>Messaging</strong> (17 tools)</summary>
| Tool | Description |
| ---------------------- | ----------------------- |
| `wa_send_text` | Send text message |
| `wa_send_image` | Send image with caption |
| `wa_send_video` | Send video with caption |
| `wa_send_audio` | Send audio / voice note |
| `wa_send_document` | Send file / document |
| `wa_send_location` | Send GPS location |
| `wa_send_contact` | Send vCard contact |
| `wa_send_poll` | Create a poll |
| `wa_send_reaction` | React with emoji |
| `wa_send_link_preview` | Send URL with preview |
| `wa_forward_message` | Forward a message |
| `wa_edit_message` | Edit sent message |
| `wa_delete_message` | Delete message |
| `wa_pin_message` | Pin a message |
| `wa_send_view_once` | Send view-once media |
| `wa_send_presence` | Show typing / recording |
| `wa_mark_read` | Mark messages as read |
</details>
<details>
<summary>π <strong>Chat Management</strong> (6 tools)</summary>
| Tool | Description |
| ----------------- | ------------------------ |
| `wa_get_messages` | Get chat message history |
| `wa_archive_chat` | Archive / unarchive |
| `wa_pin_chat` | Pin / unpin chat |
| `wa_mute_chat` | Mute / unmute |
| `wa_delete_chat` | Delete chat |
| `wa_clear_chat` | Clear chat history |
</details>
<details>
<summary>π₯ <strong>Groups</strong> (14 tools)</summary>
| Tool | Description |
| ------------------------------ | ----------------------------- |
| `wa_create_group` | Create group |
| `wa_group_add_participants` | Add members |
| `wa_group_remove_participants` | Remove members |
| `wa_group_promote` | Promote to admin |
| `wa_group_demote` | Demote from admin |
| `wa_group_update_subject` | Change group name |
| `wa_group_update_description` | Change description |
| `wa_group_update_settings` | Change settings |
| `wa_group_leave` | Leave group |
| `wa_group_get_invite_code` | Get invite link |
| `wa_group_revoke_invite` | Revoke invite link |
| `wa_group_join` | Join via invite code |
| `wa_group_toggle_ephemeral` | Toggle disappearing messages |
| `wa_group_handle_request` | Approve / reject join request |
</details>
<details>
<summary>π <strong>Contacts</strong> (5 tools)</summary>
| Tool | Description |
| ------------------------- | -------------------------------- |
| `wa_search_contact` | Search contacts by name or phone |
| `wa_check_number_exists` | Check if number is on WhatsApp |
| `wa_block_contact` | Block contact |
| `wa_unblock_contact` | Unblock contact |
| `wa_get_business_profile` | Get business profile |
</details>
<details>
<summary>π€ <strong>Profile</strong> (5 tools)</summary>
| Tool | Description |
| --------------------------- | ----------------------- |
| `wa_update_profile_picture` | Set profile picture |
| `wa_remove_profile_picture` | Remove profile picture |
| `wa_update_profile_name` | Change display name |
| `wa_update_profile_status` | Change status text |
| `wa_update_privacy` | Update privacy settings |
</details>
<details>
<summary>π’ <strong>Status / Stories</strong> (3 tools)</summary>
| Tool | Description |
| ---------------------- | ----------------- |
| `wa_send_text_status` | Post text status |
| `wa_send_image_status` | Post image status |
| `wa_send_video_status` | Post video status |
</details>
<details>
<summary>π° <strong>Newsletter</strong> (3 tools)</summary>
| Tool | Description |
| ------------------------ | --------------------- |
| `wa_newsletter_follow` | Follow a newsletter |
| `wa_newsletter_unfollow` | Unfollow a newsletter |
| `wa_newsletter_send` | Send to newsletter |
</details>
<details>
<summary>π <strong>Calls</strong> (1 tool)</summary>
| Tool | Description |
| ---------------- | -------------------- |
| `wa_reject_call` | Reject incoming call |
</details>
---
## π Resources
Resources expose read-only WhatsApp state via `whatsapp://` URIs:
| URI | Description |
| --------------------------------------------- | ------------------------------ |
| `whatsapp://instances` | List all instances |
| `whatsapp://instances/{id}` | Instance details + queue stats |
| `whatsapp://instances/{id}/contacts` | All contacts |
| `whatsapp://instances/{id}/chats` | Active conversations |
| `whatsapp://instances/{id}/groups` | All groups |
| `whatsapp://instances/{id}/groups/{gid}` | Group metadata |
| `whatsapp://instances/{id}/messages/{chatId}` | Message history |
| `whatsapp://instances/{id}/profile` | Own profile |
| `whatsapp://instances/{id}/privacy` | Privacy settings |
| `whatsapp://instances/{id}/blocklist` | Blocked contacts |
---
## π‘ Real-time Notifications
Events are pushed to agents via SSE (Server-Sent Events):
| Event | Trigger |
| ------------------------------------- | ---------------------------------------------- |
| `whatsapp/message.received` | New incoming message |
| `whatsapp/message.updated` | Status change (sent β delivered β read) |
| `whatsapp/message.deleted` | Message deleted |
| `whatsapp/message.reaction` | Emoji reaction added/removed |
| `whatsapp/message.edited` | Message edited |
| `whatsapp/presence.updated` | Typing / recording / online |
| `whatsapp/chat.updated` | Chat metadata changed |
| `whatsapp/group.updated` | Group info changed |
| `whatsapp/group.participants_changed` | Member add/remove/promote/demote |
| `whatsapp/contact.updated` | Contact info changed |
| `whatsapp/connection.changed` | Instance status change (includes QR as base64) |
| `whatsapp/call.received` | Incoming call |
---
## ποΈ Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββ
β AI Agent Runtime β
β (Google ADK, Claude, LangChain, ...) β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββ
β MCP Streamable HTTP
ββββββββββββββββββββΌβββββββββββββββββββββββββββ
β WA MCP Server β
β β
β ββββββββββββββββββββββββββββββββββββββββββ β
β β Layer 1 β MCP Transport (HTTP/stdio) β β
β ββββββββββββββββββββββββββββββββββββββββββ€ β
β β Layer 2 β MCP Core β β
β β 63 Tools β 10 Resources β 12 Events β β
β ββββββββββββββββββββββββββββββββββββββββββ€ β
β β Layer 3 β Services β β
β β Instance Manager β Queue β Dedup β β
β ββββββββββββββββββββββββββββββββββββββββββ€ β
β β Layer 4 β Channel Abstraction β β
β β ββββββββββββββββ ββββββββββββββββββ β β
β β β Baileys β β Cloud API β β β
β β β (WebSocket) β β (HTTPS) β β β
β β ββββββββββββββββ ββββββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββ β
β SQLite (Drizzle) BullMQ (Redis) β
βββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ WebSocket / HTTPS
WhatsApp Servers
```
### Dual-Channel Design
| | Baileys | Cloud API |
| ---------- | ------------------------ | ------------------------ |
| Protocol | WhatsApp Web (WebSocket) | Meta Official (HTTPS) |
| Auth | QR Code / Pairing Code | Access Token |
| Cost | Free | Per-conversation pricing |
| Compliance | Unofficial | Meta-approved |
| Best for | Dev, testing, low volume | Production, enterprise |
Both backends implement the same `ChannelAdapter` interface. Your agent doesn't know or care which one is active β the tools work identically.
---
## βοΈ Configuration
Copy `.env.example` to `.env` and configure:
| Variable | Default | Description |
| --------------------------- | ------------------------ | ---------------------------------------- |
| `WA_TRANSPORT` | `http` | `http` (Streamable HTTP) or `stdio` |
| `WA_MCP_API_KEY` | β | Bearer token auth. Unset = no auth (dev) |
| `WA_MCP_PORT` | `3000` | HTTP server port |
| `WA_REDIS_URL` | `redis://localhost:6379` | Redis for BullMQ queues |
| `WA_LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error` |
| `WA_BAILEYS_RATE_LIMIT` | `20` | Messages/min per Baileys instance |
| `WA_CLOUD_RATE_LIMIT` | `80` | Messages/min per Cloud API instance |
| `WA_MESSAGE_RETENTION_DAYS` | `30` | Auto-delete old messages |
| `WA_AUTO_RECONNECT` | `true` | Auto-reconnect on disconnect |
| `WA_MEDIA_CACHE_MAX_MB` | `500` | Media cache size limit |
| `WA_CLOUD_WEBHOOK_SECRET` | β | Meta webhook verification |
| `WA_CLOUD_WEBHOOK_PORT` | `3001` | Webhook receiver port |
| `WA_VERSION_CHECK` | `true` | Daily WhatsApp Web version check |
---
## π³ Docker
### Production
```bash
docker compose up -d
```
Services:
- **wa-mcp** β The MCP server on port `3000`
- **redis** β BullMQ backend with AOF persistence
### Health Check
```bash
curl http://localhost:3000/health
```
```json
{
"status": "ok",
"uptime": 3600,
"instances": { "total": 3, "connected": 2, "disconnected": 1 },
"version": "1.0.0"
}
```
### Resource Requirements
| Instances | RAM | CPU | Disk |
| --------- | ------ | -------- | ----- |
| 1β5 | 256 MB | 0.5 vCPU | 1 GB |
| 5β20 | 512 MB | 1 vCPU | 5 GB |
| 20β50 | 1 GB | 2 vCPU | 10 GB |
---
## π Project Structure
```
src/
βββ index.ts # Entry point (HTTP/stdio)
βββ constants.ts # Defaults and limits
βββ server/mcp.ts # MCP server setup
βββ tools/ # π§ 63 MCP tools (9 files)
βββ resources/ # π 10 MCP resources (8 files)
βββ notifications/events.ts # π‘ 12 event types
βββ channels/
β βββ channel.interface.ts # ChannelAdapter contract
β βββ baileys/ # Baileys implementation
β βββ cloud-api/ # Cloud API implementation
βββ services/
β βββ instance-manager.ts # Instance lifecycle
β βββ message-queue.ts # BullMQ rate limiting
β βββ dedup.ts # Message deduplication
β βββ media.ts # Media handling
βββ db/
β βββ schema.ts # Drizzle table definitions
β βββ client.ts # SQLite connection
βββ schemas/ # Zod validation (9 files)
βββ types/ # TypeScript definitions
```
---
## πΊοΈ Roadmap
- [x] **Phase 1** β Foundation: Baileys adapter, text messaging, QR auth, instance management
- [x] **Phase 2** β Full messaging: all media types, dedup, reactions, edits, forwards
- [x] **Phase 3** β Groups, contacts, profile, status/stories, newsletters
- [x] **Phase 4** β Cloud API adapter: dual-channel unified interface
- [x] **Phase 5** β Hardening: error recovery, CI/CD, tests, docs, v1.0 release
- [x] **Phase 6** β Baileys v7 upgrade, LID support, contact sync, message persistence
---
## π€ Contributing
Contributions are welcome! Here's how the codebase is organized:
1. **One file per domain** β tools, resources, schemas, and channels each have domain-specific files
2. **Zod schemas for everything** β all tool inputs are validated with strict Zod schemas in `src/schemas/`
3. **Both adapters** β new features should be implemented in Baileys and stubbed in Cloud API
4. **Layered architecture** β tools β services β channels. No cross-layer imports.
5. **Structured logging** β use Pino, never `console.log`
```bash
# Development
npm run dev # Start with stdio transport
npm run build # Type-check + compile
npx tsc --noEmit # Type-check only
```
---
## π License
MIT β do whatever you want.
---
<p align="center">
<strong>Built for the agentic era.</strong>
<br />
<em>Stop writing REST wrappers. Let your agent discover WhatsApp.</em>
</p>
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues