Skip to main content
Glama
README.md
# whatsapp-mcp-server

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.5-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org)
[![MCP Compatible](https://img.shields.io/badge/MCP-compatible-6B46C1?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyem0tMSAxNEg5VjhIMTF2OHptNCAwaC0yVjhoMnY4eiIvPjwvc3ZnPg==)](https://modelcontextprotocol.io)
[![Official Meta API](https://img.shields.io/badge/Meta-Official%20Cloud%20API-0866FF?logo=meta&logoColor=white)](https://developers.facebook.com/docs/whatsapp/cloud-api)
[![WhatsApp Business](https://img.shields.io/badge/WhatsApp-Business%20API%20v21.0-25D366?logo=whatsapp&logoColor=white)](https://developers.facebook.com/docs/whatsapp/cloud-api)
[![No Ban Risk](https://img.shields.io/badge/Ban%20Risk-None%20(Official%20API)-25D366)](https://developers.facebook.com/docs/whatsapp/cloud-api)

A production-ready **Model Context Protocol (MCP) server** that connects AI assistants like Claude to the **WhatsApp Cloud API** (Meta). Send messages, manage conversations, handle media, send template messages, and receive real-time webhooks — all through natural language.

---

## Why this MCP server?

> **This is the only WhatsApp MCP server built on the official Meta WhatsApp Cloud API.**

Most WhatsApp tools for developers rely on unofficial browser automation libraries (`whatsapp-web.js`) or reverse-engineered protocols (`whatsmeow`, `Baileys`). These approaches violate WhatsApp's Terms of Service and carry a real risk of account bans. This project is different.

| | **whatsapp-mcp-server** (this project) | Unofficial libraries (`whatsapp-web.js`, `whatsmeow`, `Baileys`) |
|---|---|---|
| **API type** | ✅ Official Meta WhatsApp Cloud API | ❌ Unofficial / reverse-engineered |
| **Account ban risk** | ✅ None — Meta-approved | ⚠️ High — violates WhatsApp ToS |
| **Account type** | ✅ WhatsApp Business account | Personal account only |
| **Uptime reliability** | ✅ Meta SLA-backed infrastructure | ❌ Breaks when WhatsApp updates |
| **Scalability** | ✅ Business-grade, multi-agent ready | ❌ Limited to one session |
| **Template messages** | ✅ Full support | ❌ Not available |
| **Media handling** | ✅ Native Cloud API media endpoints | ⚠️ Workarounds required |
| **Webhook support** | ✅ Official Meta webhook events | ❌ Polling / fragile listeners |
| **Production use** | ✅ Built for production | ❌ Recommended for personal/hobby use only |
| **Long-term viability** | ✅ Stable, versioned API | ❌ Depends on reverse engineering staying current |

**Bottom line:** if you are building anything beyond a personal experiment — customer support, automated notifications, business workflows — use the official API. This server gives you that, packaged as a drop-in MCP server.

---

## Features

- **Send all message types** — text, images, videos, audio, documents, reactions
- **Template messages** — send and list approved WhatsApp Business templates with full component support
- **Media management** — upload, retrieve, and delete media files
- **Conversation history** — in-memory store of recent conversations via webhook
- **Real-time webhooks** — receive incoming messages and delivery status updates
- **Business profile** — read and update your WhatsApp Business profile
- **Contact lookup** — validate phone numbers against WhatsApp
- **Rate limit handling** — automatic exponential backoff retry logic
- **Type-safe** — fully typed TypeScript with Zod input validation
- **Docker ready** — multi-stage Dockerfile and docker-compose included
- **Works without webhook** — send-only mode with no webhook server required

---

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    AI Assistant (Claude)                      │
└──────────────────────────┬──────────────────────────────────┘
                           │ MCP Protocol (stdio)
                           │
┌──────────────────────────▼──────────────────────────────────┐
│                  whatsapp-mcp-server                         │
│                                                              │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────────────┐  │
│  │  MCP Server │  │   Tools      │  │  WhatsApp Client  │  │
│  │  (stdio)    │◄─┤  messages    ├─►│  (Axios + retry)  │  │
│  │             │  │  contacts    │  └────────┬──────────┘  │
│  └─────────────┘  │  media       │           │              │
│                   │  templates   │           │ HTTPS        │
│  ┌─────────────┐  └──────────────┘           │              │
│  │  Webhook    │                             ▼              │
│  │  Server     │  ◄──── Incoming   ┌─────────────────────┐ │
│  │  (Express)  │       messages    │ WhatsApp Cloud API  │ │
│  └──────┬──────┘       & statuses  │  graph.facebook.com  │ │
└─────────│───────────────────────────┼─────────────────────┘ │
          │                           │                        │
          │ HTTP POST (Meta webhooks) │ HTTPS (send messages)  │
          │                           │                        │
     ┌────▼──────────────────────────▼──────────────┐
     │            WhatsApp Users                     │
     └────────────────────────────────────────────────┘

Webhook flow for incoming messages:
WhatsApp User → Meta Servers → POST /webhook → WhatsAppWebhook
→ in-memory conversation store → EventEmitter → MCP tools
```

---

## Prerequisites

1. **Node.js 20+** — [download](https://nodejs.org)
2. **Meta Developer Account** — [create one](https://developers.facebook.com/)
3. **WhatsApp Business App** configured in Meta App Dashboard
4. **Phone Number ID** and **Access Token** from your WhatsApp app settings
5. *(Optional)* A public HTTPS URL for receiving webhooks (use ngrok for local dev)

---

## Quick Start

### Option A — Run with npx (no clone required)

The package ships a `whatsapp-mcp-server` binary, so the fastest way to use it is
to let your MCP client launch it via `npx` and pass credentials through `env`
(see the [client config blocks below](#usage-with-claude-desktop)):

```bash
npx -y @fredshred7/whatsapp-mcp-server
```

`npx` downloads and runs the published package on demand — point your MCP client
at it and you are done. Jump to [Usage with Claude Desktop](#usage-with-claude-desktop)
or [Usage with Claude Code](#usage-with-claude-code).

### Option B — Clone and build from source

**Step 1 — Clone and install:**
```bash
git clone https://github.com/FredShred7/whatsapp-mcp-server.git
cd whatsapp-mcp-server
npm install
```

**Step 2 — Configure credentials:**
```bash
cp .env.example .env
# Edit .env with your WhatsApp credentials
```

**Step 3 — Build:**
```bash
npm run build
```

**Step 4 — Add to Claude Desktop or Claude Code** (see sections below)

**Step 5 — Test it:**
Ask Claude: *"Send a WhatsApp message to +15551234567 saying Hello from Claude!"*

---

## Configuration

All configuration is via environment variables. Copy `.env.example` to `.env` and fill in the values.

| Variable | Required | Description |
|---|---|---|
| `WHATSAPP_PHONE_NUMBER_ID` | Yes | Your WhatsApp phone number ID (from Meta App Dashboard > WhatsApp > API Setup) |
| `WHATSAPP_ACCESS_TOKEN` | Yes | Permanent access token for your app (generate in Meta App Dashboard) |
| `WHATSAPP_WEBHOOK_VERIFY_TOKEN` | Webhook | Random secret string — must match what you enter in Meta App Dashboard |
| `WHATSAPP_APP_SECRET` | Recommended | Meta **App Secret** (App Dashboard > Settings > Basic). Used to verify the `X-Hub-Signature-256` signature on incoming webhooks. Strongly recommended in production. If unset, signature verification is skipped (with a startup warning) so local dev still works. |
| `WHATSAPP_BUSINESS_ACCOUNT_ID` | Optional | WhatsApp Business Account ID — required for listing phone numbers and templates |
| `WHATSAPP_API_VERSION` | Optional | WhatsApp Cloud API version (default: `v21.0`) |
| `WEBHOOK_PORT` | Optional | Port for incoming webhook server (default: off). Set to `3000` to enable |
| `WEBHOOK_PATH` | Optional | HTTP path for webhooks (default: `/webhook`) |
| `LOG_LEVEL` | Optional | Logging verbosity: `info` or `debug` (default: `info`) |

---

## Available Tools

| Tool | Description | Key Parameters |
|---|---|---|
| `whatsapp_send_text` | Send a text message | `to`, `text`, `preview_url?`, `reply_to_message_id?` |
| `whatsapp_send_image` | Send an image with optional caption | `to`, `image_url`, `caption?` |
| `whatsapp_send_video` | Send a video with optional caption | `to`, `video_url`, `caption?` |
| `whatsapp_send_audio` | Send an audio message | `to`, `audio_url` |
| `whatsapp_send_document` | Send a document/file | `to`, `document_url`, `caption?`, `filename?` |
| `whatsapp_send_reaction` | React to a message with emoji | `to`, `message_id`, `emoji` |
| `whatsapp_mark_read` | Mark a message as read | `message_id` |
| `whatsapp_list_conversations` | List recent conversations (webhook required) | `limit?` |
| `whatsapp_get_conversation` | Get messages with a contact (webhook required) | `phone_number`, `limit?` |
| `whatsapp_get_message_status` | Get delivery/read status (webhook required) | `message_id` |
| `whatsapp_get_contact` | ⚠️ **Legacy/unsupported** — validate a phone number on WhatsApp (see note below) | `phone_number` |
| `whatsapp_get_business_profile` | Get your WhatsApp Business profile | — |
| `whatsapp_update_business_profile` | Update business profile info | `about?`, `address?`, `description?`, `email?`, `websites?`, `vertical?` |
| `whatsapp_upload_media` | Upload media from URL, get media ID | `media_url`, `mime_type`, `filename?` |
| `whatsapp_get_media_url` | Get temporary download URL for media | `media_id` |
| `whatsapp_delete_media` | Delete uploaded media | `media_id` |
| `whatsapp_send_template` | Send an approved template message | `to`, `template_name`, `language_code`, `components?` |
| `whatsapp_list_templates` | List available message templates | `limit?` |

> ⚠️ **`whatsapp_get_contact` is legacy and not expected to work on the Cloud API.**
> It relies on the `POST /{phone-number-id}/contacts` "contact check", which was a
> feature of the legacy **WhatsApp On-Premises API** — not a Cloud API endpoint that
> was later removed. Per [Meta's On-Premises API Sunset](https://developers.facebook.com/docs/whatsapp/on-premises/sunset),
> the final On-Premises client version **expired on 2025-10-23**. The contact-check
> never existed in the WhatsApp Cloud API (the API this server uses), and the Cloud
> API has **no contact-validation equivalent**. (Even on On-Premises, Meta had
> degraded it to always return `valid`, so the result could not be trusted.) To
> determine whether a number can receive messages, **send the message and inspect
> the message-status webhooks / error codes** (e.g. `131026` "message
> undeliverable") instead. The tool is retained only for backwards compatibility.

---

## Usage with Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows).

**Recommended — run the published package via `npx`** (no local build needed):

```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "npx",
      "args": ["-y", "@fredshred7/whatsapp-mcp-server"],
      "env": {
        "WHATSAPP_PHONE_NUMBER_ID": "your_phone_number_id",
        "WHATSAPP_ACCESS_TOKEN": "your_access_token",
        "WHATSAPP_WEBHOOK_VERIFY_TOKEN": "your_verify_token",
        "WHATSAPP_APP_SECRET": "your_app_secret",
        "WHATSAPP_BUSINESS_ACCOUNT_ID": "your_business_account_id",
        "WEBHOOK_PORT": "3000"
      }
    }
  }
}
```

**Alternatively — run a local build** (after cloning and `npm run build`):

```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "node",
      "args": ["/absolute/path/to/whatsapp-mcp-server/dist/index.js"],
      "env": {
        "WHATSAPP_PHONE_NUMBER_ID": "your_phone_number_id",
        "WHATSAPP_ACCESS_TOKEN": "your_access_token",
        "WHATSAPP_WEBHOOK_VERIFY_TOKEN": "your_verify_token",
        "WHATSAPP_APP_SECRET": "your_app_secret",
        "WHATSAPP_BUSINESS_ACCOUNT_ID": "your_business_account_id",
        "WEBHOOK_PORT": "3000"
      }
    }
  }
}
```

Restart Claude Desktop after saving. You should see the WhatsApp tools available in the tools panel.

---

## Usage with Claude Code

Add to your Claude Code MCP settings (`~/.claude/settings.json` or project-level `.claude/settings.json`). Using the published package via `npx`:

```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "npx",
      "args": ["-y", "@fredshred7/whatsapp-mcp-server"],
      "env": {
        "WHATSAPP_PHONE_NUMBER_ID": "your_phone_number_id",
        "WHATSAPP_ACCESS_TOKEN": "your_access_token",
        "WHATSAPP_WEBHOOK_VERIFY_TOKEN": "your_verify_token",
        "WHATSAPP_APP_SECRET": "your_app_secret",
        "WHATSAPP_BUSINESS_ACCOUNT_ID": "your_business_account_id",
        "WEBHOOK_PORT": "3000"
      }
    }
  }
}
```

Or use the CLI to add it:
```bash
claude mcp add whatsapp npx -y @fredshred7/whatsapp-mcp-server
```

---

## Webhook Setup

Webhooks allow you to **receive** incoming messages and delivery status updates. They are optional — the MCP server works without them for sending messages only.

### Local development with ngrok

```bash
# 1. Install ngrok: https://ngrok.com/download
# 2. Start your webhook server
WEBHOOK_PORT=3000 npm run dev

# 3. In another terminal, expose it publicly
ngrok http 3000

# 4. Copy the HTTPS URL (e.g. https://abc123.ngrok.io)
```

### Configure in Meta App Dashboard

1. Go to [Meta App Dashboard](https://developers.facebook.com/apps/) > Your App > WhatsApp > Configuration
2. Set **Callback URL** to: `https://your-ngrok-url.ngrok.io/webhook`
3. Set **Verify Token** to match your `WHATSAPP_WEBHOOK_VERIFY_TOKEN`
4. Click **Verify and Save**
5. Subscribe to the **messages** webhook field

### Production

For production, deploy this server behind a reverse proxy (nginx, Caddy, etc.) with a valid TLS certificate. Set `WEBHOOK_PORT` to your internal port and expose it via HTTPS on port 443.

---

## Docker Deployment

### Build and run with docker-compose

```bash
# Copy and fill in your credentials
cp .env.example .env

# Build and start
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down
```

### Build manually

```bash
# Build image
docker build -t whatsapp-mcp-server .

# Run (send-only, no webhook)
docker run --rm -i \
  -e WHATSAPP_PHONE_NUMBER_ID=xxx \
  -e WHATSAPP_ACCESS_TOKEN=xxx \
  whatsapp-mcp-server

# Run with webhook server
docker run --rm -i \
  -p 3000:3000 \
  --env-file .env \
  whatsapp-mcp-server
```

**Note:** When using Docker with Claude Desktop/Code, the MCP transport uses stdio. Make sure to pass `-i` (interactive) so stdin/stdout remain connected. The webhook port is separate from the MCP transport.

---

## Development

```bash
# Install dependencies
npm install

# Run with auto-reload
npm run dev

# Type-check only (no build)
npm run typecheck

# Build
npm run build

# Lint
npm run lint

# Run the test suite
npm test

# Re-run tests on change
npm run test:watch
```

### Project structure

```
src/
├── index.ts              # Entry point — loads env, wires up components
├── server.ts             # MCP server — registers tools, handles requests
├── whatsapp/
│   ├── client.ts         # WhatsApp Cloud API client with retry logic
│   ├── types.ts          # TypeScript types and interfaces
│   └── webhook.ts        # Express webhook server + in-memory store
└── tools/
    ├── shared.ts         # Shared helpers: formatError + Zod->JSON Schema
    ├── messages.ts       # Send/receive message tools
    ├── contacts.ts       # Contact and business profile tools
    ├── media.ts          # Media upload/download/delete tools
    └── templates.ts      # Template message tools

test/                     # Vitest unit tests (schema, errors, webhook)
```

---

## Contributing

Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on reporting bugs, suggesting features, and submitting pull requests.

---

## License

[MIT](LICENSE) — Copyright (c) 2025 FredShred7

TDQS

A3.7/5.0

Scored across 18 tools

Disambiguation5/5

Each tool targets a distinct operation: sending different media types, managing profiles, listing conversations/templates, etc. There is no ambiguity between tools even for similar actions like sending different media types because the tool names clearly specify the media type.

Naming Consistency5/5

All tools follow a consistent 'whatsapp_verb_noun' pattern using snake_case. For example, 'whatsapp_send_text', 'whatsapp_get_conversation', 'whatsapp_list_templates'. This makes the tool set predictable and easy to navigate.

Tool Count5/5

With 18 tools, the set is well-scoped for a WhatsApp Business API server. It covers sending, receiving, media management, profile updates, and template listing without being overwhelming or too sparse.

Completeness4/5

The tool set covers core CRUD operations for sending messages, managing media, and updating profiles. However, template management is limited to listing only (no create/update/delete), and there is no support for group chats or webhook configuration, which are notable gaps for a complete WhatsApp integration.

Maintenance

ActivityInactive
ResponsivenessNo issues