mcp-wacli
mcp-wacli is an MCP server that lets AI clients interact with WhatsApp through your personal account, enabling reading, searching, and sending messages via 27 tools. All data stays local with no duplication, using the same authenticated session as wacli.
Chats:
List all chats (with optional name filtering) and view detailed info for a specific chat
Messages:
List recent messages with filters (chat, date range)
Full-text search across messages, filterable by chat, sender, date range, and media type
View details of a single message or surrounding context around a specific message
Contacts:
Search contacts by name or phone, view contact details
Set/remove local aliases (nicknames) and refresh contacts from the session store
Sending:
Send text messages or files (images, videos, audio, documents) to individuals or groups
Groups:
List groups, fetch live group info, rename or leave groups, join via invite code
Manage participants: add, remove, promote, or demote
Media:
Download media attachments from messages to a local file or directory
Sync & History:
Sync new messages on demand; request older message history backfill from your primary device
Diagnostics:
Check authentication status and run system diagnostics (store, auth, search capabilities)
Supports stdio (over SSH) and HTTP/SSE transports with Bearer token authentication, compatible with Claude, Cursor, Cline, GPT, Gemini, and other MCP clients.
Allows for reading, searching, and sending WhatsApp messages, managing contacts and group participants, and downloading media files through a personal WhatsApp account. It provides comprehensive group management tools, including adding/removing members, promoting admins, and handling group invites.
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., "@mcp-wacli Search my messages for 'invoice' from last week"
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.
mcp-wacli
MCP (Model Context Protocol) server that wraps wacli — a WhatsApp CLI built on whatsmeow. Lets any MCP-compatible AI client (Claude Code, Claude Desktop, Cursor, Cline, etc.) read, search, and send WhatsApp messages through your personal account.
Why a wrapper?
Instead of reimplementing the WhatsApp Web protocol, mcp-wacli delegates everything to wacli's --json mode. This means:
Zero duplicate sessions — uses the same authenticated session as your existing wacli install
Zero data duplication — one SQLite DB, shared with wacli
Full feature parity — any wacli command becomes an MCP tool
Tiny codebase — ~540 lines of Python glue
Related MCP server: WAHA MCP
Architecture
Two transport modes are supported:
┌─────────────────────────────────┐
│ AI Client │
│ Claude / Cursor / GPT / Gemini │
└──────┬────────────┬──────────────┘
│ │
SSH+stdio │ │ HTTP/SSE
▼ ▼
┌──────────────────────────┐
│ server.py (FastMCP) │
│ 27 tools │
│ Bearer token auth (HTTP) │
└──────────┬───────────────┘
│ subprocess
▼
┌──────────────────────┐
│ wacli --json │
│ (Go / whatsmeow) │
└──────────┬───────────┘
│
▼
WhatsApp serversAll data stays local. Messages are only sent to the AI when it explicitly invokes a tool.
Prerequisites
Dependency | Version | Notes |
wacli | dev+ | Must be authenticated ( |
Python | >= 3.11 | Managed by uv |
uv | >= 0.10 | Python package manager |
Quick start
# 1. Clone
git clone https://github.com/grrek/mcp-wacli.git
cd mcp-wacli
# 2. Install dependencies
uv sync
# 3. Verify wacli is authenticated
wacli doctor --json
# 4. Test the MCP server (stdio mode)
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | uv run server.pyTransport modes
Mode 1: stdio (over SSH) — default
Best for Claude Code and Claude Desktop when accessing a remote server via SSH.
uv run server.pyMode 2: HTTP/SSE with Bearer token auth
Best for network access from any MCP client, including non-Anthropic LLMs. Can run as a persistent systemd service.
uv run server.py --httpOn first run, a random 32-character token is generated and saved to ~/.mcp-wacli-token (mode 0600). The server prints the token to stderr on startup. All HTTP requests must include Authorization: Bearer <token>.
Customize with environment variables:
MCP_HOST— bind address (default:0.0.0.0)MCP_PORT— port (default:9800)
Note: The MCP library's built-in DNS rebinding protection (TrustedHostMiddleware) is disabled in mcp-wacli because it rejects connections from non-localhost IPs. Authentication is handled instead by the ASGI Bearer token middleware, which validates every request at the transport level before it reaches the MCP handler.
Running as a systemd user service (recommended for HTTP mode)
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/mcp-wacli.service << 'EOF'
[Unit]
Description=mcp-wacli HTTP/SSE server
After=network-online.target
[Service]
Type=simple
WorkingDirectory=/home/YOUR_USER/mcp-wacli
ExecStart=/home/YOUR_USER/.local/bin/uv run server.py --http
Environment=MCP_HOST=0.0.0.0
Environment=MCP_PORT=9800
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable mcp-wacli
systemctl --user start mcp-wacli
# Allow service to run without an active SSH session
loginctl enable-linger YOUR_USERUseful commands:
systemctl --user status mcp-wacli— check statussystemctl --user restart mcp-wacli— restart after updatesjournalctl --user -u mcp-wacli -f— follow logs
Configure your AI client
Claude Code — HTTP/SSE (recommended)
Use the Claude CLI to add the MCP server:
claude mcp add --transport sse -s user whatsapp http://YOUR_SERVER:9800/sse \
--header "Authorization: Bearer YOUR_TOKEN_HERE"This writes the config to ~/.claude.json. Alternatively, add it manually:
{
"mcpServers": {
"whatsapp": {
"type": "sse",
"url": "http://YOUR_SERVER:9800/sse",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
}
}
}Claude Code — SSH (stdio)
claude mcp add -s user whatsapp -- ssh \
-o LogLevel=ERROR \
-o ClearAllForwardings=yes \
your-server \
"export PATH=\$HOME/.local/bin:\$PATH && cd ~/mcp-wacli && uv run server.py"Important SSH caveats:
Use
-o LogLevel=ERRORto suppress SSH warnings on stderr (they break the MCP JSON-RPC handshake)Use
-o ClearAllForwardings=yesif your~/.ssh/confighasLocalForwardentries for this host (port-forward bind warnings also break the handshake)
Claude Desktop — HTTP/SSE
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"whatsapp": {
"type": "sse",
"url": "http://YOUR_SERVER:9800/sse",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
}
}
}Claude Desktop — SSH
{
"mcpServers": {
"whatsapp": {
"command": "ssh",
"args": [
"-o", "LogLevel=ERROR",
"-o", "ClearAllForwardings=yes",
"your-server",
"export PATH=$HOME/.local/bin:$PATH && cd ~/mcp-wacli && uv run server.py"
]
}
}
}Local (no SSH, no HTTP)
If wacli and mcp-wacli are on the same machine:
{
"mcpServers": {
"whatsapp": {
"command": "uv",
"args": ["run", "server.py"],
"cwd": "/path/to/mcp-wacli"
}
}
}Any MCP-compatible client (GPT, Gemini, etc.)
Start the HTTP server and point the client to http://YOUR_SERVER:9800/sse with the Bearer token from ~/.mcp-wacli-token.
Available tools (27)
Chats (2)
Tool | Description |
| List chats with optional name search |
| Show details of a single chat by JID |
Messages (4)
Tool | Description |
| List recent messages with date/chat filters |
| Full-text search (FTS5 or LIKE fallback) |
| Show a single message by ID |
| Show surrounding messages for context |
Contacts (5)
Tool | Description |
| Search contacts by name or phone |
| Show contact details by JID |
| Set a local nickname for a contact |
| Remove a local nickname |
| Re-import contacts from session store |
Send (2)
Tool | Description |
| Send a text message |
| Send image, video, audio, or document |
Groups (9)
Tool | Description |
| List groups with optional search |
| Fetch live group info |
| Rename a group |
| Leave a group |
| Join a group by invite code |
| Add members to a group |
| Remove members from a group |
| Promote members to admin |
| Demote admins |
Media (1)
Tool | Description |
| Download media from a message |
Sync & History (2)
Tool | Description |
| Sync new messages (connect, fetch, exit) |
| Request older messages from primary device |
Diagnostics (2)
Tool | Description |
| Check store, auth, and search status |
| Show authentication status |
Usage examples
Once configured, you can ask your AI client things like:
"Show me my recent WhatsApp chats"
"Search my messages for 'invoice' from last week"
"Send Aurora a message saying I'll be 10 minutes late"
"List all my WhatsApp groups"
"Who are the participants in the family group?"
"Download the image from that last message"
JID format reference
Type | Format | Example |
Individual |
|
|
Group |
|
|
Phone number |
|
|
Security considerations
All messages are stored locally in
~/.wacli/Data is only sent to the AI model when a tool is explicitly invoked
No data leaves the machine except through WhatsApp's own protocol and MCP tool calls
The
send_messageandsend_filetools require the AI client to request permission before executionHTTP mode uses a 192-bit Bearer token (
secrets.token_urlsafe(32)) stored with mode 0600Recommended: restrict HTTP access to a VPN (e.g. Tailscale) rather than exposing to the public internet
wacli uses the unofficial WhatsApp Web API — use at your own risk
Known limitations
Re-authentication: WhatsApp sessions expire every ~20 days. Re-scan QR with
wacli authClient outdated errors: WhatsApp updates protocol versions. Keep wacli updated
FTS5: Full-text search requires SQLite compiled with FTS5 support. Falls back to LIKE
No real-time events: This is a pull-based model (query when asked), not push-based
wacli sync must run: For fresh messages,
wacli syncshould be running orsync_oncemust be called
License
MIT
Available Tools
27 toolsauth_statusA
Show authentication status of the current wacli session.
Inputs: no named parameters.
doctorB
Run wacli diagnostics — check store, authentication, and search capabilities.
Inputs: no named parameters.
download_mediaB
Download media from a WhatsApp message.
Args:
message_id: The message ID containing media
chat: Chat JID where the message is
output: Optional output file or directory (defaults to wacli media dir)
Inputs: message_id (required), chat (required), output.
group_infoB
Fetch live group info from WhatsApp and update local DB.
Args:
jid: Group JID (e.g. '120363001234567890@g.us')
Inputs: jid (required).
group_joinA
Join a WhatsApp group by invite code.
Args:
code: Invite code from a group link (the part after https://chat.whatsapp.com/)
Inputs: code (required).
group_leaveC
Leave a WhatsApp group.
Args:
jid: Group JID
Inputs: jid (required).
group_participants_addC
Add participants to a WhatsApp group.
Args:
jid: Group JID
users: List of phone numbers or JIDs to add
Inputs: jid (required), users (required).
group_participants_demoteA
Demote admin participants in a WhatsApp group.
Args:
jid: Group JID
users: List of phone numbers or JIDs to demote
Inputs: jid (required), users (required).
group_participants_promoteB
Promote participants to admin in a WhatsApp group.
Args:
jid: Group JID
users: List of phone numbers or JIDs to promote
Inputs: jid (required), users (required).
group_participants_removeB
Remove participants from a WhatsApp group.
Args:
jid: Group JID
users: List of phone numbers or JIDs to remove
Inputs: jid (required), users (required).
group_renameC
Rename a WhatsApp group.
Args:
jid: Group JID
name: New group name
Inputs: jid (required), name (required).
history_backfillC
Request older messages for a chat from your primary device (best-effort).
Args:
chat: Chat JID to backfill history for
Inputs: chat (required).
list_chatsB
List WhatsApp chats from local DB.
Args:
query: Optional search string to filter chats by name
limit: Max number of chats to return (default 50)
Inputs: query, limit.
list_groupsB
List WhatsApp groups from local DB.
Args:
query: Optional search string to filter groups
limit: Max results (default 50)
Inputs: query, limit.
list_messagesB
List recent WhatsApp messages with optional filters.
Args:
chat: Optional chat JID to filter by
after: Only messages after this date (YYYY-MM-DD or RFC3339)
before: Only messages before this date (YYYY-MM-DD or RFC3339)
limit: Max results (default 50)
Inputs: chat, after, before, limit.
message_contextA
Show surrounding messages around a specific message ID for context.
Args:
message_id: The message ID to center on
chat: Chat JID where the message is
before: Number of messages before (default 5)
after: Number of messages after (default 5)
Inputs: message_id (required), chat (required), before, after.
refresh_contactsB
Import/refresh contacts from the WhatsApp session store into local DB.
Inputs: no named parameters.
remove_contact_aliasC
Remove a local alias from a contact.
Args:
jid: Contact JID
Inputs: jid (required).
search_contactsB
Search WhatsApp contacts by name or phone number.
Args:
query: Search term
limit: Max results (default 50)
Inputs: query (required), limit.
search_messagesA
Full-text search across WhatsApp messages (FTS5 if available, LIKE fallback).
Args:
query: Search text
chat: Optional chat JID filter
sender: Optional sender JID filter
after: Only after this date (YYYY-MM-DD or RFC3339)
before: Only before this date (YYYY-MM-DD or RFC3339)
media_type: Filter by media type (image|video|audio|document)
limit: Max results (default 50)
Inputs: query (required), chat, sender, after, +3 more.
send_fileA
Send a file (image, video, audio, document) via WhatsApp.
Args:
to: Recipient phone number or JID
file_path: Path to the file on the server
caption: Optional caption for the file
filename: Optional display name (defaults to file basename)
mime: Optional MIME type override
Inputs: to (required), file_path (required), caption, filename, +1 more.
send_messageB
Send a text message via WhatsApp.
Args:
to: Recipient phone number (e.g. '573001234567') or JID
message: Text message to send
Inputs: to (required), message (required).
set_contact_aliasA
Set a local alias (nickname) for a contact.
Args:
jid: Contact JID
alias: Alias to set
Inputs: jid (required), alias (required).
show_chatB
Show details of a single chat.
Args:
jid: Chat JID (e.g. '573001234567@s.whatsapp.net' or '...@g.us' for groups)
Inputs: jid (required).
show_contactC
Show details of a single contact.
Args:
jid: Contact JID (e.g. '573001234567@s.whatsapp.net')
Inputs: jid (required).
show_messageC
Show details of a single message.
Args:
message_id: The message ID
chat: Chat JID where the message is
Inputs: message_id (required), chat (required).
sync_onceA
Sync messages once (connect, fetch new messages, then exit).
Args:
refresh_contacts: Also refresh contacts from session store
refresh_groups: Also refresh joined groups (live)
download_media: Download media in the background during sync
Inputs: refresh_contacts, refresh_groups, download_media.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 27 tools
Most tools have distinct purposes, but there is some overlap between list_chats and list_groups (both list entities), and between search_messages and list_messages (both retrieve messages). The descriptions clarify the differences, but an agent might occasionally confuse them.
Tool names follow a consistent snake_case pattern with clear verb_noun structures (e.g., download_media, group_leave, search_contacts). There are no deviations in naming conventions across all 27 tools.
With 27 tools, the count feels heavy for a WhatsApp CLI toolset. While it covers many features, it borders on being overwhelming and could be streamlined without losing core functionality.
The toolset provides comprehensive coverage for WhatsApp operations, including authentication, messaging, group management, contact handling, media, and syncing. There are no obvious gaps; it supports full CRUD-like workflows for the domain.
Maintenance
Related MCP Connectors
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
Free WhatsApp MCP server for ChatGPT and Claude: read and search chats, every send you approve.
WhatsApp MCP on your own number: read chats, search contacts, send messages.
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
Related MCP Servers
- AlicenseCqualityDmaintenanceA Model Context Protocol server that connects your personal WhatsApp account to AI agents like Claude, enabling them to search messages, view contacts, retrieve chat history, and send messages via WhatsApp.711 npm76ISC
- FlicenseNot gradedqualityNot gradedmaintenanceA self-hosted MCP server that connects AI clients to WhatsApp via the WAHA HTTP API. It enables users to manage sessions, search contacts, and send or receive messages and media directly through natural language interfaces.8 npm-
- AlicenseNot gradedqualityBmaintenanceWhatsApp MCP server that exposes messaging, groups, contacts, and profile management as tools and resources for AI agents, supporting Baileys and Meta Cloud API.273 npm29MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that connects AI agents to WhatsApp using the multi-device API, enabling messaging, group management, and more as a regular user.6 npm1MIT