WAHA WhatsApp MCP Server
The WAHA WhatsApp MCP Server integrates WhatsApp messaging with AI assistants via the Model Context Protocol (MCP), providing 28 tools across messaging, contacts, media, search, and automation.
Session & Account
Check WhatsApp session connection status and authenticated account info (connected number, display name)
Chats & Messages
List recent chats with previews
Read message history with filtering by sender, type, and date range
Send text messages to individuals or groups (rate-limited)
React to messages with emojis, edit previously sent messages, delete (unsend) for everyone, and forward messages
Contacts
Check if a phone number is registered on WhatsApp
List all contacts (people and groups) with activity stats
Get detailed info on a specific person or group (members, metadata, message stats)
View a contact's social graph — shared groups and mutual connections
Media
Download images, audio, video, and documents from messages (images/audio returned inline)
Transcribe voice messages to text using server-side Whisper-based transcription
Generate text-to-speech (TTS) audio inline without sending to WhatsApp
Message Store & Search
Full-text search across all message history with date, sender, and type filters
Get readable chat summaries (up to 200 recent messages)
View activity stats: message totals, top chats, top contacts, group/DM breakdown
Import WhatsApp chat export files (ZIP or TXT) to backfill historical messages
Auto-Reply
Enable/disable automatic voice-note transcription replies for specific contacts
List all contacts with auto-reply currently enabled
Media Automation
Read and update per-conversation media automation policies (capture, analysis, archiving, Nextcloud integration)
Disable all media automation flags for a conversation
Check system health diagnostics for backend, listener, media, and worker components
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@WAHA WhatsApp MCP Server send 'Running late' to my contact John"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
WAHA WhatsApp MCP Server
A TypeScript Model Context Protocol stdio server for WhatsApp through a unified WAHA backend. It exposes 28 tools for messages, contacts, media, transcription, speech generation, automatic voice-note replies, message-store search, and per-conversation media automation.
Architecture
MCP client → this package → unified backend /api (:8200)
├─ PostgreSQL message store
├─ WAHA live proxy
├─ transcription and TTS providers
└─ media analysis/archive workerThe MCP server only talks to the authenticated /api facade. It does not connect
directly to WAHA, databases, Nextcloud, or model providers. LAN-only management
routes for archive review and LLM provider administration are intentionally excluded.
This release targets waha-backend commit 46acc32 or a compatible newer build.
Related MCP server: WhatsApp MCP Server
Install
Claude Code
claude mcp add waha-whatsapp -- \
env WAHA_API_URL=http://your-server:8200/api \
WAHA_API_KEY=your-backend-api-key \
npx -y @marcos-heidemann/waha-mcp-serverMCP JSON configuration
{
"mcpServers": {
"waha-whatsapp": {
"command": "npx",
"args": ["-y", "@marcos-heidemann/waha-mcp-server"],
"env": {
"WAHA_API_URL": "http://your-server:8200/api",
"WAHA_API_KEY": "your-backend-api-key"
}
}
}
}Configuration
Variable | Required | Default | Description |
| no |
| Unified backend API URL |
| yes | — | Value sent as |
| no |
| WAHA session name |
| no |
| Minimum delay between outbound sends; non-negative integer |
Older WAHA_STORE_* and WAHA_TRANSCRIPTION_* variables are no longer used.
Those services are configured behind the unified backend.
Contact identifiers
Chat-targeting tools use a stable contactId:
Person: phone digits with country code, such as
5521999999999.Group: the stable group JID ending in
@g.us.Legacy
@c.usand@lidaliases remain accepted on routes where the backend supports them.Imported chat IDs ending in
@importwork with message read/search, but not with the backend chat-summary route.
Use whatsapp_list_contacts to discover identifiers.
Tools (28)
Area | Tool | Purpose |
Session |
| Connection and account presence |
Session |
| Authenticated WhatsApp identity |
Chats |
| Live chat overview with previews |
Chats |
| Persistent history with live fallback and optional mark-read |
Messaging |
| Rate-limited text send |
Messaging |
| Add or remove a reaction |
Messaging |
| Edit an outgoing text message |
Messaging |
| Unsend a message |
Messaging |
| Copy stored text into another chat |
Media |
| Return images/audio up to 10 MiB inline; save larger/other files in |
Media |
| Transcribe with language and prompt hints |
Media |
| Generate inline TTS audio; does not send it to WhatsApp |
Contacts |
| Check whether a phone is registered |
Contacts |
| Unified people and groups address book |
Contacts |
| Person or group detail |
Store |
| Search text plus indexed captions, OCR, summaries, tags, and documents |
Store |
| Shared groups and mutual contacts |
Store |
| Recent readable history, up to 100 messages |
Store |
| Activity totals and top chats/contacts |
Store |
| Import a local |
Auto-reply |
| Enable person/group voice-note replies; optional contextual mode |
Auto-reply |
| Disable automatic voice-note replies |
Auto-reply |
| Check enabled/found state |
Auto-reply |
| List enabled people and groups |
Automation |
| Read per-conversation media policy |
Automation |
| Partially update capture/analysis/reply/archive policy |
Automation |
| Turn every media automation flag off for a conversation |
Automation |
| Combined backend/listener/media/worker diagnostics |
Media automation settings
whatsapp_media_settings_update supports:
captureEnabledanalyzeImagesanalyzeDocumentswhatsappReplyEnabledincludeMediaInRecaparchiveMode:off,review, orautofixedNextcloudFolderId: integer ornullarchiveConfirmationEnabledallowSensitiveProcessingaskOnReview
Conversation settings are combined with backend-wide kill switches. Always inspect
returned warnings or call whatsapp_automation_health before assuming a feature is
active. The current public health/warning contract does not expose the global gates
for recap inclusion or review questions.
Current backend limitations
Manual quote replies are not implemented by the public backend send route. Supplying
replyToreturns an MCP error and sends nothing.whatsapp_forward_messagere-sends stored text. It does not preserve media, sender attribution, or WhatsApp's Forwarded label.Some current GOWS media is still exposed as stored type
chat; type filters may miss it until the backend public API switches tonormalized_type.Public chat summaries are not fully
@lidalias-aware. Read/search are the safer choices for migrated histories.Imported sender identities are history-only and are omitted from
whatsapp_list_contacts; imported*@importchats support read/search but not live read receipts or chat summaries.Durable staged-media preview, Nextcloud folder discovery, archive review/actions, and Motor/LLM configuration remain operator-only management functions.
Development and verification
npm ci
npm test # hermetic unit + backend-contract tests
npm run build
npm pack --dry-runReleases are deployed by pushing a tag that exactly matches the package version,
for example v2.4.0. The publish workflow repeats unit tests and the build before
publishing to npm with the repository secret.
Live tests require WAHA_API_URL and WAHA_API_KEY:
npm run test:live # read-only suites
WAHA_TEST_LEVEL=2 npm run test:live # includes self-chat writes
WAHA_TEST_LEVEL=3 npm run test:live # includes configured contact writesThe default test and CI paths never contact WhatsApp.
Security
Treat the backend API key as a password; never commit it.
Sending through an unofficial WhatsApp API can trigger anti-abuse controls. Keep automation narrow and rate-limited.
Media and chat exports can contain sensitive data. Review automation policy before enabling analysis, replies, or archival.
Rotate any credential that has previously appeared in Git history.
License
Available Tools
22 toolswhatsapp_account_infoWhatsApp Account InfoARead-onlyIdempotent
Get information about the authenticated WhatsApp account.
Returns the phone number, display name, and WhatsApp ID of the connected account. Use this to verify which account is connected.
No parameters required.
Inputs: no named parameters.
whatsapp_auto_reply_disableDisable Auto-Reply TranscriptionAIdempotent
Disable auto-reply with audio transcription for a contact.
Args:
phone: Phone number digits only, no @, no spaces (e.g., "5521986910666").
Returns:
status: "ok"
phone: the canonical phone
enabled: false
Inputs: phone (required).
whatsapp_auto_reply_enableEnable Auto-Reply TranscriptionAIdempotent
Enable auto-reply with audio transcription for a contact.
When the contact sends a voice note, the transcription is sent back as a quoted reply automatically. DM only — voice notes in groups are never auto-replied even if a member is flagged.
The flag is contact/phone-scoped, so it follows the contact across WhatsApp's @c.us → @lid JID transitions automatically — no need to re-flag when WhatsApp migrates the JID.
Args:
phone: Phone number digits only, no @, no spaces (e.g., "5521986910666"). Look up via whatsapp_list_contacts first if you only know the name.
Returns:
status: "ok" on success
phone: the canonical phone
enabled: true
Inputs: phone (required).
whatsapp_auto_reply_listList Contacts with Auto-Reply EnabledARead-onlyIdempotent
List every contact that currently has auto-reply transcription enabled, with display names from Google Contacts (when matched) or WhatsApp push name fallback.
Returns:
contacts: array of { phone, display_name, person_name, push_name }
Inputs: no named parameters.
whatsapp_chat_summaryChat SummaryARead-onlyIdempotent
Get a readable summary of recent messages in a WhatsApp chat, including sender names and timestamps.
This is optimized for readability — use whatsapp_read_messages for structured data with filtering, or whatsapp_search_messages for full-text search.
Args:
contactId: Phone digits for a person, or "*@g.us" for a group
limit: Number of recent messages to include (1-200, default 50)
Returns:
chat: Name, type, message count, date range
messages: Recent messages with sender name, body, timestamp, type
Inputs: contactId (required), limit.
whatsapp_check_numberCheck WhatsApp NumberARead-onlyIdempotent
Check if a phone number is registered on WhatsApp.
Use this before sending a message to a number not yet in your address book.
Args:
phone: Phone number with country code, no spaces or dashes (e.g., "5511999999999")
Returns:
numberExists: true if registered on WhatsApp
contactId: The id to use as contactId in other tools (the same phone digits)
Inputs: phone (required).
whatsapp_contact_graphContact Social GraphARead-onlyIdempotent
Get social graph for a WhatsApp contact — shared groups, mutual connections.
Args:
phone: Phone number with country code (e.g., "5524999160115")
Returns:
groups: Groups this contact is in, with message counts
mutualContacts: Other contacts who share groups with this person
Inputs: phone (required).
whatsapp_delete_messageDelete WhatsApp MessageADestructive
Delete (unsend) a message from a contact's chat.
Removes the message for everyone. WhatsApp shows "This message was deleted" in its place.
Args:
contactId: Contact id: phone digits for a person (e.g. "5521986910666"; survives @c.us↔@lid flips), or a group JID "*@g.us". Look up via whatsapp_list_contacts.
messageId: Message ID to delete
Returns confirmation of deletion.
Inputs: contactId (required), messageId (required).
whatsapp_download_mediaDownload WhatsApp MediaARead-onlyIdempotent
Download media (image, audio, video, document) from a WhatsApp message.
Fetches the media attached to a specific message and returns it directly:
Images: returned inline so Claude can see them
Audio: returned inline so Claude can process them
Video/documents: saved to /tmp/whatsapp-media/ and path returned
Use whatsapp_read_messages first to find messages with hasMedia=true, then pass the contactId and messageId here.
Note: Old media (weeks+) may no longer be available on WhatsApp's servers.
Args:
contactId: Phone digits or "*@g.us" — the contact whose chat contains the message
messageId: Message ID with media to download (from whatsapp_read_messages)
Returns:
For images: the image content directly (Claude can see it)
For audio: the audio content directly
For other files: file path where it was saved + metadata
Inputs: contactId (required), messageId (required).
whatsapp_edit_messageEdit WhatsApp MessageAIdempotent
Edit a previously sent text message.
Only works on messages you sent (fromMe=true). WhatsApp shows an "edited" label on the message after editing.
Args:
contactId: Contact id: phone digits for a person (e.g. "5521986910666"; survives @c.us↔@lid flips), or a group JID "*@g.us". Look up via whatsapp_list_contacts.
messageId: Message ID to edit (must be your own message)
text: New text content
Returns confirmation with the edited message ID.
Inputs: contactId (required), messageId (required), text (required).
whatsapp_forward_messageForward WhatsApp MessageA
Forward a message from one chat to another contact.
The forwarded message shows a "Forwarded" label in WhatsApp and preserves the original sender attribution.
Args:
contactId: Contact id: phone digits for a person (e.g. "5521986910666"; survives @c.us↔@lid flips), or a group JID "*@g.us". Look up via whatsapp_list_contacts. — destination
messageId: Message ID to forward (get from whatsapp_read_messages)
Returns confirmation with forwarded message ID.
Inputs: contactId (required), messageId (required).
whatsapp_get_contactGet Contact Detail (person or group)ARead-onlyIdempotent
Detail for a single contact — person OR group, by stable id.
Returns shape depends on kind:
Person: contact (phone, names, email, org), all chats they appear in, all JID variants, message stats.
Group: chat (group metadata), members with display names, member_count.
Args:
contactId: phone digits (person; "5521986910666"), or "*@g.us" (group). Look up via whatsapp_list_contacts.
Inputs: contactId (required).
whatsapp_import_chatImport WhatsApp Chat ExportAIdempotent
Import a WhatsApp chat export file (ZIP or TXT) into the message store.
Use this to backfill historical messages from WhatsApp's "Export Chat" feature. Only inserts new messages — won't overwrite or duplicate existing data.
The file should be a WhatsApp chat export:
ZIP file containing a .txt (standard WhatsApp export format)
Or a plain .txt file
The chat name is extracted from the filename (e.g., "Conversa do WhatsApp com NAME.zip"). You can override it with the chatName parameter.
Messages are matched to existing contacts by name. If a contact doesn't exist, it's created. If the chat already exists in the store (by name), messages are added to it.
Args:
filePath: Absolute path to the ZIP or TXT file on the server
chatName: Optional override for the chat name (extracted from filename if omitted)
Returns:
chat_name: Resolved chat name
total_parsed: Number of messages found in file
inserted: New messages added
skipped_duplicates: Messages already in store
senders: List of sender names found
Inputs: filePath (required), chatName.
whatsapp_list_chatsList WhatsApp ChatsARead-onlyIdempotent
List recent WhatsApp chats with last message preview and profile pictures.
Returns chat IDs, names, profile picture URLs, and a preview of the last message. Use the chat ID from results to read messages with whatsapp_read_messages.
Args:
limit: Number of chats to return (1-100, default 20)
offset: Pagination offset (default 0)
Returns array of chats with:
id: Chat ID (use this in other tools)
name: Contact or group name
picture: Profile picture URL (may expire)
lastMessage: Preview with body, from, fromMe, hasMedia, timestamp
lastMessageAt: ISO timestamp of last message
Inputs: limit, offset.
whatsapp_list_contactsList WhatsApp Contacts (people + groups)ARead-onlyIdempotent
Unified address book — lists people you DM and groups you're in.
Use the returned 'id' as contactId in any chat-targeting tool (send_text, read_messages, etc.):
Person: id = phone digits (universal — survives @c.us↔@lid flips)
Group: id = group JID (e.g. "120363...@g.us")
Args:
kind: "person" | "group" | "all" (default "all")
search: Filter by name or id (optional)
limit: Maximum rows to return (1-100, default 20)
offset: Pagination offset for the persons section (default 0)
Returns array of contacts with:
kind: "person" | "group"
id: phone digits or group JID — pass to other tools
name: display name (Google Contact name → push name → phone/jid fallback)
messageCount, lastMessageAt: activity stats
For persons: pushName, googleName, email, organization
For groups: memberCount
Inputs: kind, search, limit, offset.
whatsapp_reactReact to WhatsApp MessageAIdempotent
React to a WhatsApp message with an emoji.
Use an empty string for the reaction to remove an existing reaction.
Args:
contactId: Contact id: phone digits for a person (e.g. "5521986910666"; survives @c.us↔@lid flips), or a group JID "*@g.us". Look up via whatsapp_list_contacts.
messageId: Message ID to react to (get from whatsapp_read_messages)
reaction: Emoji to react with (e.g., "👍", "❤️", "😂"). Empty string removes reaction.
Returns confirmation of the reaction.
Inputs: contactId (required), messageId (required), reaction (required).
whatsapp_read_messagesRead WhatsApp MessagesA
Read messages from a specific WhatsApp chat.
Returns messages with sender, text content, timestamp, and message ID. Use the message ID from results for whatsapp_react or reply_to in whatsapp_send_text.
Powered by Message Store — persistent full history with full-text search and sender filtering.
Args:
contactId: Phone digits for a person ("5521986910666"; survives @c.us↔@lid flips), or group JID "*@g.us". Look up via whatsapp_list_contacts.
limit: Number of messages to return (1-100, default 20)
offset: Skip N messages for pagination (default 0)
search: Full-text search within this chat's messages (optional)
sender: Filter by sender name or JID (optional)
type: Filter by message type: chat, image, album (optional)
since: ISO date — messages after this date (optional)
until: ISO date — messages before this date (optional)
fromMe: Filter sent (true) or received (false) messages (optional)
downloadMedia: Include media download URLs when falling back to live (default false)
markAsRead: Mark messages as read after fetching (default false)
Returns:
messages: Array with id, sender, body, timestamp, type, fromMe, hasMedia
total: Total matching messages
hasMore: Whether more results exist
Inputs: contactId (required), limit, offset, search, +7 more.
whatsapp_search_messagesSearch WhatsApp MessagesARead-onlyIdempotent
Search across all WhatsApp message history. Supports full-text search, date ranges, sender filtering, and message type filtering.
Args:
search: Text to search for (case insensitive, supports Portuguese/unicode)
contactId: Scope search to one contact (phone digits or "*@g.us") (optional)
sender: Filter by sender name or JID (optional)
since: ISO date string — messages after this date (optional)
until: ISO date string — messages before this date (optional)
type: Message type filter: chat, image, album, e2e_notification (optional)
fromMe: Filter sent (true) or received (false) messages (optional)
limit: Results per page (1-100, default 20)
offset: Pagination offset (default 0)
Returns:
messages: Array with id, chatJid, senderName, body, timestamp, messageType, fromMe
total: Total matching messages
has_more: Whether more results exist
Note: sender_name may be null for some messages.
Inputs: search (required), contactId, sender, since, +5 more.
whatsapp_send_textSend WhatsApp Text MessageA
Send a text message to a contact (person or group).
CORE tier supports text messages only (no images, video, audio, or documents). A rate limit delay is enforced between sends to avoid WhatsApp detection.
Args:
contactId: Contact id: phone digits for a person (e.g. "5521986910666"; survives @c.us↔@lid flips), or a group JID "*@g.us". Look up via whatsapp_list_contacts.
text: Message text to send
replyTo: Optional message ID to quote-reply to (get from whatsapp_read_messages)
Returns:
status: "sent"
messageId: The sent message's ID
contactId: Where it was sent
Inputs: contactId (required), text (required), replyTo.
whatsapp_session_statusWhatsApp Session StatusARead-onlyIdempotent
Check if the WhatsApp session is connected and working.
Returns the session status (WORKING, STOPPED, etc.), the connected phone number, and display name. Use this to verify connectivity before sending messages.
No parameters required.
Returns:
name: Session name
status: "WORKING" if connected, "STOPPED" if disconnected
phone: Connected phone number (if authenticated)
pushName: Display name on WhatsApp
Inputs: no named parameters.
whatsapp_statsWhatsApp StatsARead-onlyIdempotent
Overview dashboard of WhatsApp activity — message totals, top chats, top contacts, and group/DM breakdown.
No arguments needed. Returns:
Totals: messages, contacts, chats, groups, DMs
Activity: messages today, this week
Top 5 chats by message count (name may be null for groups — use whatsapp_get_contact to look up)
Top 5 contacts by message count
Inputs: no named parameters.
whatsapp_transcribe_audioTranscribe WhatsApp AudioA
Transcribe a WhatsApp voice message or audio to text.
Server-side transcription via Speaches (Whisper). Optionally replies to the original message with the transcription text.
Args:
contactId: Phone digits or "*@g.us" — the contact whose chat contains the audio
messageId: Message ID of the audio to transcribe
replyWithTranscription: If true, sends the transcription as a WhatsApp reply to the audio message (default false)
Returns:
transcription: The transcribed text
language: Detected language (if available)
replyMessageId: ID of the reply message (if replyWithTranscription=true)
Inputs: contactId (required), messageId (required), replyWithTranscription.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Each tool has a clearly distinct purpose, from account info to message operations to auto-reply management. No two tools appear to do the same thing, and descriptions clarify boundaries (e.g., chat_summary vs read_messages vs search_messages).
All tools share the 'whatsapp_' prefix and mostly follow a verb_noun pattern (e.g., delete_message, send_text). A few deviate slightly (e.g., account_info, stats, session_status are noun_noun or noun only), but the overall pattern is clear and consistent.
With 22 tools, the count is slightly above the ideal range but still well-scoped for a comprehensive WhatsApp server. Each tool covers a distinct operation, and none feel redundant or excessive.
The tool set covers most core WhatsApp operations: account management, contacts, chats, messages (send, read, edit, delete, forward, react, download media, transcribe), and auto-reply. Notable gaps include sending media (images, files) and group management, but the core workflow is well-supported.
Related MCP Connectors
WhatsApp for Claude, ChatGPT or any AI agent: search, reply and send. Personal or Business API.
Your own WhatsApp in Claude and ChatGPT: read chats, draft replies, send messages you approve.
WhatsMCP connects Claude and other MCP-compatible AI agents directly to WhatsApp. Send and receive text, images, documents, and voice notes; manage groups (create, add/remove members, promote admins); look up contacts and profiles; follow channels; and read call and message history — all through a standard MCP interface. For voice use cases, WhatsMCP offers SIP-based calling plans (inbound-only, or full inbound/outbound) so AI voice agents can answer and place WhatsApp calls, plus low-latency WebSocket integrations with voice agent providers like ElevenLabs. Multiple WhatsApp accounts can be paired and managed per workspace, with webhook support for real-time inbound message delivery to your own infrastructure.
Business WhatsApp from Claude: read chats, reply to customers, pause the AI agent, edit its prompt.
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables Claude to manage WhatsApp templates, flows, and send messages through the WhatsApp Cloud API.3119 npmMIT
- AlicenseNot gradedqualityDmaintenanceConnect your personal WhatsApp to Claude — send messages, read chats, and manage contacts.GPL 3.0
- AlicenseNot gradedqualityDmaintenanceEnables Claude to read and send WhatsApp messages through a self-hosted REST API, supporting multi-user sessions, media, groups, contacts, and webhooks.4 npmMIT
- FlicenseNot gradedqualityAmaintenanceEnables a Claude Code session to send and receive WhatsApp messages from a linked personal account or the official Cloud API, including photos, voice notes and documents, with local voice transcription and allowlist-based access control. It also lets users approve or deny Claude's tool requests remotely by emoji reaction and keeps per-chat personalities, cron jobs and conversation context across restarts.-