Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

An MCP server that connects Claude and other LLM clients to WhatsApp via the Baileys library. Enables sending and receiving messages, listing chats, downloading media, and more.

README.md

WhatsApp MCP Server

An MCP (Model Context Protocol) server that connects Claude and other LLM clients to WhatsApp. Built on top of the Baileys library, which implements the WhatsApp Web protocol natively — no browser automation required.

Features

  • whatsapp_get_status — Check connection status (connected, waiting for QR, error)
  • whatsapp_list_chats — List available chats and groups with metadata
  • whatsapp_list_messages — List recent messages from the server's local store (observed while running; optional persistence)
  • whatsapp_send_message — Send text messages to contacts or groups
  • whatsapp_send_file — Send files/media (document/image/video/audio/voice note)
  • whatsapp_get_media — Get media directly as Base64 without local download (new!)
  • whatsapp_download_media — Download attachments (including voice notes) to local file
  • whatsapp_get_group_info — Get group details, participants, and admin info

Prerequisites

  • Node.js >= 18
  • A WhatsApp account linked to a phone
  • An MCP-compatible client (Claude Desktop, Claude Code, etc.)

Compatibility: Works with both regular WhatsApp and WhatsApp Business accounts. Baileys implements the WhatsApp Web Multi-Device protocol, which is identical for both account types. Business-specific features (catalogs, auto-replies, labels) are not supported by this server.

Important: This server requires @whiskeysockets/baileys@^7.0.0-rc.9 or later. Older versions may fail to generate valid QR codes for new device linking.

Quick Start

1. Clone and Build

git clone https://github.com/ydmw74/whatsapp-mcp-server.git
cd whatsapp-mcp-server
npm install
npm run build

2. First Run — QR Code Authentication

Run the server once manually to complete the QR code pairing:

node dist/index.js

A QR code will appear in your terminal. Scan it with your phone:

WhatsApp > Settings > Linked Devices > Link a Device

After successful pairing, the session is persisted in ~/.whatsapp-mcp/auth. You won't need to scan again unless you unlink the device.

Note: To use whatsapp_list_messages, keep the server running while messages arrive. The server can only list messages it has observed (and optionally persisted).

3. Configure Your MCP Client

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "whatsapp": {
      "command": "node",
      "args": ["/absolute/path/to/whatsapp-mcp-server/dist/index.js"]
    }
  }
}

Claude Code

claude mcp add whatsapp node /absolute/path/to/whatsapp-mcp-server/dist/index.js

4. Optional: Shared HTTP Mode (Single Server Process)

If you want one long-running MCP server process for multiple clients, run in HTTP mode:

WHATSAPP_MCP_TRANSPORT=http WHATSAPP_HTTP_HOST=127.0.0.1 WHATSAPP_HTTP_PORT=8787 WHATSAPP_HTTP_PATH=/mcp node dist/index.js

Or with npm script:

WHATSAPP_HTTP_HOST=127.0.0.1 WHATSAPP_HTTP_PORT=8787 WHATSAPP_HTTP_PATH=/mcp npm run start:http

Then configure your MCP client to use the URL endpoint (Streamable HTTP), for example with Codex:

codex mcp add whatsapp --url http://127.0.0.1:8787/mcp

Configuration

| Environment Variable | Default | Description | |---|---|---| | WHATSAPP_AUTH_DIR | ~/.whatsapp-mcp/auth | Directory for session persistence | | WHATSAPP_DEVICE_NAME | (unset) | Optional linked-device label shown in WhatsApp ("Linked devices"), e.g. WHATSAPP_DEVICE_NAME=MyAgent-1 (will show like MyAgent-1 (Mac OS) or ... (Ubuntu)). | | WHATSAPP_RELINK | (unset) | Force re-linking in non-interactive environments. Use backup (or 1/true) to move the existing auth dir aside, or delete to remove it. | | WHATSAPP_EXIT_AFTER_PAIR | auto | If a QR code was shown in this run, exit automatically after successful pairing. Defaults to enabled only for interactive terminal runs (TTY). | | WHATSAPP_PERSIST_MESSAGES | false | Persist the local message store to disk (message-store.json). | | WHATSAPP_MAX_MESSAGES_PER_CHAT | 200 | Retention limit per chat for the local message store. | | WHATSAPP_MAX_MESSAGES_TOTAL | 2000 | Global retention limit for the local message store. | | WHATSAPP_MCP_TRANSPORT | stdio | MCP transport mode: stdio or http (http = Streamable HTTP server). | | WHATSAPP_HTTP_HOST | 127.0.0.1 | Bind address for HTTP mode. Use 0.0.0.0 if clients connect from other hosts. | | WHATSAPP_HTTP_PORT | 8787 | TCP port for HTTP mode. | | WHATSAPP_HTTP_PATH | /mcp | HTTP endpoint path for MCP requests. | | WHATSAPP_UPLOAD_DIR | /tmp/whatsapp-uploads | Directory for uploaded files (HTTP mode). | | WHATSAPP_UPLOAD_MAX_SIZE | 52428800 | Max upload file size in bytes (default: 50 MB). |

Tools Reference

whatsapp_get_status

Check if WhatsApp is connected and ready.

Parameters: None

Returns: Connection status, phone number, or QR code if authentication is pending.

whatsapp_list_chats

List available WhatsApp chats.

Parameters:

  • limit (number, 1-100, default: 20) — Maximum chats to return

Returns: List of chats with ID, name, type (group/DM), and unread count.

whatsapp_list_messages

List recent messages from the server's local message store.

Parameters:

  • chat_id (string, optional) — Chat JID (DM or group). If omitted, returns recent messages across all chats.
  • limit (number, 1-100, default: 20) — Maximum number of messages to return

Returns: A formatted list of messages with timestamp, sender, and text.

Notes:

  • Only messages observed by the running server are available.
  • To keep messages across restarts, set WHATSAPP_PERSIST_MESSAGES=1 (stores message-store.json next to the auth dir).
  • If a message includes media, the list includes basic media metadata (kind, mimetype, etc.). Use whatsapp_download_media to download the attachment.

whatsapp_send_message

Send a text message.

Parameters:

  • chat_id (string) — Phone number with country code (e.g., 4915123456789) or full JID
  • text (string) — Message text (max 4096 chars)

Returns: Message ID and timestamp.

whatsapp_send_file

Send a file/media message (document/image/video/audio/voice note).

Parameters:

  • chat_id (string) — Phone number with country code or full JID
  • path (string) — Local file path (supports ~/ expansion)
  • kind (string, optional) — document|image|video|audio|voice (default: document)
  • caption (string, optional) — Caption (image/video/document)
  • mimetype (string, optional) — MIME type override
  • fileName (string, optional) — File name override (document only)

Returns: Message ID and timestamp.

whatsapp_download_media

Download an attachment (including voice notes) from a message that the server has observed.

Parameters:

  • chat_id (string) — Chat JID (from whatsapp_list_messages)
  • message_id (string) — Message ID (from whatsapp_list_messages)
  • output_dir (string, optional) — Directory to write the file to (supports ~/ expansion)

Returns: Absolute file path and media metadata.

whatsapp_get_media

Get media (attachments) directly from the server as Base64 without saving to disk.

Parameters:

  • chat_id (string) — Chat JID (from whatsapp_list_messages)
  • message_id (string) — Message ID (from whatsapp_list_messages)
  • format (string, optional) — Return format: "base64" for raw base64 (default) or "data_url" for image data URL

Returns: Base64 encoded media and media metadata.

Notes:

  • Only works for messages observed by the server since it started
  • No local file download required
  • Supports images, videos, documents, audio, and voice notes

whatsapp_get_group_info

Get detailed group information.

Parameters:

  • group_id (string) — Group JID (e.g., 120363012345678901@g.us)

Returns: Group subject, description, participant list with admin status.

HTTP File Transfer Endpoints (HTTP Mode)

When running in HTTP mode, the server provides two additional endpoints for remote file transfer. These are essential for remote MCP clients that cannot access the server filesystem directly.

POST /upload — Upload a file to the server

curl -s -F "file=@/local/path/photo.jpg" http://server:8787/upload

Response: ``json {"path": "/tmp/whatsapp-uploads/a1b2c3d4-photo.jpg", "size": 123456, "name": "photo.jpg"} ``

Use the returned path with whatsapp_send_file. Files are auto-cleaned after 1 hour.

GET /download?path=... — Download a file from the server

curl -s -o local-file.jpg "http://server:8787/download?path=/root/whatsapp-mcp-data/downloads/whatsapp-ABC123.jpeg"

Only serves files from allowed directories (/tmp, uploads dir, downloads dir) to prevent arbitrary file access.

Typical workflow:

  1. whatsapp_download_media → returns a server-local path
  2. GET /download?path=<server-path> → download the file to your local machine

How It Works

By default (WHATSAPP_MCP_TRANSPORT=stdio), your MCP client (Claude Desktop, Claude Code, etc.) launches and manages the server process automatically in the background.

When you open a chat in Claude Desktop, it spawns node dist/index.js as a child process and communicates with it over stdio (stdin/stdout). When you close the chat, the process is stopped. You don't need to manage it yourself.

The only manual step is the one-time QR code authentication (see Quick Start, Step 2). After that, the session is persisted to disk and the server reconnects automatically on every subsequent start.

In HTTP mode (WHATSAPP_MCP_TRANSPORT=http), you run one persistent server process and clients connect to it via URL (for example http://server:8787/mcp).

Architecture

stdio mode (local child process):

┌──────────────────┐     stdio      ┌──────────────────┐
│  Claude / LLM    │ ◄──────────── │  MCP Server      │
│  Client          │ ──────────── │  (this project)  │
└──────────────────┘               └────────┬─────────┘
                                            │
                                   Baileys Protocol
                                            │
                                   ┌────────▼─────────┐
                                   │  WhatsApp Web    │
                                   │  Servers         │
                                   └──────────────────┘

http mode (shared daemon):

┌──────────────────┐      HTTP      ┌──────────────────┐
│  MCP Client A    │ ────────────► │                  │
├──────────────────┤                │  MCP Server      │
│  MCP Client B    │ ────────────► │  (single process)│
└──────────────────┘                └────────┬─────────┘
                                             │
                                    Baileys Protocol
                                             │
                                    ┌────────▼─────────┐
                                    │  WhatsApp Web    │
                                    │  Servers         │
                                    └──────────────────┘

Session state is persisted to disk so re-authentication is only needed once.

PM2 Deployment (Linux, Shared in Network)

This is the recommended setup if you want a single MCP server running on a dedicated Linux host in your LAN.

Important: Baileys 7.x (this project requires ^7.0.0-rc.9) is required for QR code authentication to work properly. If you encounter QR code issues, ensure you have the correct Baileys version installed.

0. Fresh server preflight (if Node.js/npm are missing)

On a fresh Debian host, install required base packages first:

apt-get update -y
apt-get install -y nodejs npm git rsync

1. Install PM2

npm install -g pm2

2. Build the server

cd /home/<linux-user>/whatsapp-mcp-server
npm install
npm run build

3. Start MCP server with PM2 (HTTP mode)

Bind to all interfaces (0.0.0.0) if clients connect from other machines:

WHATSAPP_MCP_TRANSPORT=http \
WHATSAPP_HTTP_HOST=0.0.0.0 \
WHATSAPP_HTTP_PORT=8787 \
WHATSAPP_HTTP_PATH=/mcp \
WHATSAPP_AUTH_DIR=/home/<linux-user>/whatsapp-mcp-data/auth \
pm2 start node --name whatsapp-mcp -- dist/index.js

You can also use:

WHATSAPP_HTTP_HOST=0.0.0.0 WHATSAPP_HTTP_PORT=8787 WHATSAPP_HTTP_PATH=/mcp pm2 start npm --name whatsapp-mcp -- run start:http

Recommended (path-independent): use the included PM2 config file:

cd /home/<linux-user>/whatsapp-mcp-server
pm2 start ecosystem.config.cjs

The provided ecosystem.config.cjs uses:

  • cwd: __dirname (works regardless of clone directory)
  • WHATSAPP_AUTH_DIR dynamically from the current Linux user's home directory, e.g. /home/<linux-user>/whatsapp-mcp-data/auth

4. Persist PM2 across reboot

pm2 startup
pm2 save

5. Useful PM2 commands

pm2 status
pm2 logs whatsapp-mcp
pm2 restart whatsapp-mcp
pm2 stop whatsapp-mcp

Check the MCP HTTP listener:

ss -lntp | grep 8787

5.1 QR code in PM2 logs (scan-friendly output)

PM2 prefixes each line with timestamp/process metadata, which can make the terminal QR hard to scan. Use the helper script (from repository root) to print the latest complete QR block:

./scripts/show-whatsapp-qr.sh

Optional: pass a different PM2 app name:

./scripts/show-whatsapp-qr.sh whatsapp-mcp

6. Connect MCP clients to your Linux host

Codex

codex mcp add whatsapp --url http://<linux-server-ip>:8787/mcp

Claude Desktop (claude_desktop_config.json)

Use mcp-remote to connect Claude Desktop to your remote HTTP server.

Important: mcp-remote only allows HTTPS URLs by default. Since the server runs over plain HTTP (no TLS), you must add the --allow-http flag — otherwise the connection will fail with: `` Error: Non-HTTPS URLs are only allowed for localhost or when --allow-http flag is provided ``

{
  "mcpServers": {
    "whatsapp": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://<linux-server-ip>:8787/mcp",
        "--allow-http"
      ]
    }
  }
}

After editing claude_desktop_config.json, restart the Claude Desktop app to apply the changes.

Tip: If your server is accessible via HTTPS (e.g. behind a reverse proxy with TLS), omit the --allow-http flag.

Claude Code (CLI)

claude mcp add --transport http whatsapp http://<linux-server-ip>:8787/mcp

Note: Claude Code's built-in HTTP transport accepts plain HTTP URLs directly — no --allow-http flag required.

7. Linking Troubleshooting

  • If WhatsApp currently refuses new linked devices, this is usually a temporary WhatsApp-side issue.
  • Keep the PM2 process running and retry QR linking later.
  • To force a fresh QR attempt:
pm2 restart whatsapp-mcp

Session invalidated by WhatsApp (device_removed, code 401)

If you see this in the error log:

"stream errored out" ... "code":"401" ... "type":"device_removed"

WhatsApp has remotely revoked the session (e.g. because you unlinked the device from your phone, or WhatsApp forced a re-link). The server cannot reconnect with the existing auth files — you must delete them and re-pair:

pm2 stop whatsapp-mcp
rm -rf ~/whatsapp-mcp-data/auth/*   # adjust path to your WHATSAPP_AUTH_DIR
pm2 start ecosystem.config.cjs
./scripts/show-whatsapp-qr.sh       # or: whatsapp-qr

Then scan the QR code with WhatsApp > Settings > Linked Devices > Link a Device.

8. Quick Recovery (copy/paste runbook)

Use these commands in order when the remote deployment is not behaving as expected:

# 1) Process state
pm2 status whatsapp-mcp

# 2) Recent logs
pm2 logs whatsapp-mcp --lines 100 --nostream

# 3) Ensure HTTP endpoint is listening
ss -lntp | grep 8787

# 4) Restart app and refresh environment
pm2 restart whatsapp-mcp --update-env

# 5) Re-check logs after restart
pm2 logs whatsapp-mcp --lines 100 --nostream

If QR output is not scanable in PM2 logs:

./scripts/show-whatsapp-qr.sh

Full re-link (session invalidated or corrupted):

pm2 stop whatsapp-mcp
rm -rf ~/whatsapp-mcp-data/auth/*   # adjust to your WHATSAPP_AUTH_DIR
pm2 start ecosystem.config.cjs
./scripts/show-whatsapp-qr.sh       # or: whatsapp-qr

If PM2 is running but not restored after reboot:

pm2 startup systemd -u root --hp /root
pm2 save
systemctl status pm2-root

Hint: If this server runs in your network, protect access with firewall rules and/or a reverse proxy with authentication/TLS. Do not expose an unauthenticated MCP endpoint directly to the public internet.

Security Considerations

  • Session data is stored locally in ~/.whatsapp-mcp/auth. Protect this directory — anyone with access can impersonate your WhatsApp account.
  • Messages can be stored locally in memory for whatsapp_list_messages (and optionally persisted to message-store.json). Treat stored message data as sensitive.
  • The LLM client should always confirm with the user before sending messages via whatsapp_send_message.
  • This project uses the unofficial WhatsApp Web protocol. WhatsApp may block accounts that violate their Terms of Service. Use responsibly.

Limitations

  • Limited message history: The server lists recent messages that it observed while running (and optionally persisted). It does not fetch arbitrary chat history from WhatsApp.
  • Media downloads are limited to observed messages: whatsapp_download_media can only download media for messages the server has observed since it started (it keeps the raw message in memory for a bounded recent window).
  • Single session: Only one WhatsApp account can be linked at a time.

Development

# Install dependencies
npm install

# Run in development mode (auto-reload)
npm run dev

# Build
npm run build

# Clean build artifacts
npm run clean

Acknowledgements

License

MIT

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Communication servers.