MCP Hub
Back to servers

mcp-wacli

An MCP server that wraps the wacli tool to enable AI clients to read, search, and send WhatsApp messages through a personal account. It provides comprehensive tools for managing chats, groups, and contacts using an existing authenticated WhatsApp session.

glama
Updated
Mar 9, 2026

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

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 servers

All data stays local. Messages are only sent to the AI when it explicitly invokes a tool.

Prerequisites

DependencyVersionNotes
waclidev+Must be authenticated (wacli auth)
Python>= 3.11Managed by uv
uv>= 0.10Python 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.py

Transport modes

Mode 1: stdio (over SSH) — default

Best for Claude Code and Claude Desktop when accessing a remote server via SSH.

uv run server.py

Mode 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 --http

On 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_USER

Useful commands:

  • systemctl --user status mcp-wacli — check status
  • systemctl --user restart mcp-wacli — restart after updates
  • journalctl --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=ERROR to suppress SSH warnings on stderr (they break the MCP JSON-RPC handshake)
  • Use -o ClearAllForwardings=yes if your ~/.ssh/config has LocalForward entries 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)

ToolDescription
list_chatsList chats with optional name search
show_chatShow details of a single chat by JID

Messages (4)

ToolDescription
list_messagesList recent messages with date/chat filters
search_messagesFull-text search (FTS5 or LIKE fallback)
show_messageShow a single message by ID
message_contextShow surrounding messages for context

Contacts (5)

ToolDescription
search_contactsSearch contacts by name or phone
show_contactShow contact details by JID
set_contact_aliasSet a local nickname for a contact
remove_contact_aliasRemove a local nickname
refresh_contactsRe-import contacts from session store

Send (2)

ToolDescription
send_messageSend a text message
send_fileSend image, video, audio, or document

Groups (9)

ToolDescription
list_groupsList groups with optional search
group_infoFetch live group info
group_renameRename a group
group_leaveLeave a group
group_joinJoin a group by invite code
group_participants_addAdd members to a group
group_participants_removeRemove members from a group
group_participants_promotePromote members to admin
group_participants_demoteDemote admins

Media (1)

ToolDescription
download_mediaDownload media from a message

Sync & History (2)

ToolDescription
sync_onceSync new messages (connect, fetch, exit)
history_backfillRequest older messages from primary device

Diagnostics (2)

ToolDescription
doctorCheck store, auth, and search status
auth_statusShow 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

TypeFormatExample
Individual{country}{number}@s.whatsapp.net573001234567@s.whatsapp.net
Group{id}@g.us120363001234567890@g.us
Phone number{country}{number}573001234567

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_message and send_file tools require the AI client to request permission before execution
  • HTTP mode uses a 192-bit Bearer token (secrets.token_urlsafe(32)) stored with mode 0600
  • Recommended: 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 auth
  • Client 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 sync should be running or sync_once must be called

License

MIT

Reviews

No reviews yet

Sign in to write a review