SkillAgentSearch skills...

mcp-whatsapp

Single-binary Go MCP server that wraps whatsmeow to expose a personal WhatsApp account as 42 MCP tools (messaging, groups, polls, media, privacy).

Install / Use

claude mcp add Sealjay -- npx -y github:Sealjay/mcp-whatsapp

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

76/100

Supported Platforms

Claude Code
Claude Desktop

Our assessment of mcp-whatsapp

mcp-whatsapp scores 76/100 on our quality scale, 406th of 431 Communication skills we index.

Its MCP Server is 23 KB long, well organised into 29 sections with 13 code examples: a thorough specification that gives an agent plenty to work with.

It has 10 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
4/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 10 days ago, so mcp-whatsapp is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 97/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

mcp-whatsapp compared with similar skills

All 4 of these similar skills score higher than mcp-whatsapp; compare them before choosing.

SkillScoreStarsUpdatedFormat
mcp-whatsapp (this skill)by Sealjay761010d agoMCP Server
claude-memby thedotmack10096.6ktodayCLAUDE.md
Agent-Reachby Panniantong10091.8k20d agoCLAUDE.md
headroomby headroomlabs-ai10074.5ktodayCLAUDE.md
CowAgentby zhayujie10047.2ktodayCLAUDE.md

Frequently asked questions

How do I install mcp-whatsapp?
Run claude mcp add Sealjay -- npx -y github:Sealjay/mcp-whatsapp. The install tabs above show the steps for each supported agent.
Which AI agents does mcp-whatsapp work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is mcp-whatsapp safe to use?
It is MIT-licensed and scores 97/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is mcp-whatsapp still maintained?
The repository was last updated 10 days ago, so mcp-whatsapp is actively maintained.

WhatsApp MCP Server

License: MIT CI Go Report Card Go 1.25+ MCP 42 tools whatsmeow Sealjay/mcp-whatsapp MCP server GitHub issues

A single-binary Go MCP server that wraps whatsmeow to expose a personal WhatsApp account to LLMs. whatsapp-mcp serve runs as a lightweight HTTP daemon on 127.0.0.1:8765; MCP clients (Claude Desktop, Cursor, Claude Code, etc.) connect to it via HTTP — no process spawning, no stdin/stdout juggling. Messages are cached in local SQLite and only travel to the model when the agent calls a tool.

Unaffiliated. This is an independent open-source project. It is not affiliated with, endorsed by, or otherwise associated with Meta Platforms, Inc., WhatsApp, or whatsmeow. "WhatsApp" is a trademark of Meta Platforms, Inc., used here nominatively to describe interoperability.

This started as a fork of lharries/whatsapp-mcp and has since been rewritten as a single Go binary. What it adds over the original:

  • LID resolution — normalises @lid JIDs to real phone numbers for accurate contact matching.
  • Sent-message storage — outgoing messages are persisted locally so conversation history stays complete.
  • Disappearing-message timers — outgoing messages inherit the group chat's ephemeral timer automatically.
  • Targeted history sync — on-demand per-chat backfill via the request_sync tool.
  • Extended tool surface — 42 tools (see below): reactions, replies, edits, revoke, mark-read, typing, is-on-whatsapp, full group admin, blocklist, polls (create + vote + tally), contact cards, view-once flag, presence, privacy settings, and the profile "About" text.
  • Single-instance enforcement — a flock(2) on store/.lock prevents two serve processes racing on the same SQLite files.

Setup

Prerequisites

  • Go 1.25+ (build-time only; runtime needs just the compiled binary).
  • An MCP client that speaks HTTP (Claude Desktop, Cursor, Claude Code, etc.).
  • FFmpeg (optional) — required only for send_audio_message when the input is not already .ogg Opus. Without it, use send_file to send raw audio.
  • Windows: CGO must be enabled — see docs/windows.md.

Install

git clone https://github.com/Sealjay/mcp-whatsapp.git
cd mcp-whatsapp
make build    # writes ./bin/whatsapp-mcp

Pair your phone (first run only)

Start the daemon, then open the pairing page in a browser:

./bin/whatsapp-mcp serve          # starts on 127.0.0.1:8765
open http://127.0.0.1:8765/pair   # macOS; or visit the URL manually

Scan the QR code with WhatsApp on your phone (Settings → Linked Devices → Link a Device). The pairing persists to ./store/whatsapp.db. When WhatsApp invalidates the session (roughly every 20 days), visit /pair again and re-scan.

Alternative (headless / CI): ./bin/whatsapp-mcp login renders the QR in the terminal. Use this when a browser isn't available.

Connect your MCP client

whatsapp-mcp serve is an HTTP daemon on 127.0.0.1:8765 (or $WHATSAPP_MCP_ADDR). MCP clients connect to it over HTTP:

Claude Desktop's claude_desktop_config.json doesn't support a bare url/type: http entry the way Claude Code and Cursor do — it only launches stdio servers via command/args. Bridge it with mcp-remote instead:

// Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "whatsapp": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://127.0.0.1:8765/mcp"]
    }
  }
}
// Claude Code — .claude/mcp.json (project) or ~/.claude/mcp.json (user)
{
  "mcpServers": {
    "whatsapp": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
  }
}
// Cursor — ~/.cursor/mcp.json
{
  "mcpServers": {
    "whatsapp": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
  }
}

Restart the client. WhatsApp appears as an available integration. Closing and reopening the client reconnects to the daemon — no process spawn, no per-session handshake, no stdin/stdout juggling.

Sending and receiving files

WHATSAPP_MCP_MEDIA_ROOT is an allowlist root and gates both directions of file movement:

  • Sending — send_file and send_audio_message accept a media_path argument pointing at the file to send. The path must live under the allowed root.
  • Receiving — download_media writes decrypted media to the daemon cache at <store>/<chat_jid>/<hex(message_id)>/<safe_filename>. The message-ID directory prevents distinct messages with the same filename from sharing cached bytes; cache hits are checked against the stored size and SHA-256 when available. Passing the optional output_path argument additionally places the file at a caller-chosen location, which must also live under the allowed root. If a file already exists at output_path the call is a no-op.

By default the allowed root is ./store/uploads/ (resolved relative to your -store directory). On first run, serve creates it automatically; drop files you intend to send into it and point output_path here if you want to read incoming media from the same place.

To allow a different directory, set WHATSAPP_MCP_MEDIA_ROOT (absolute path) when starting the daemon:

WHATSAPP_MCP_MEDIA_ROOT=/Users/me/whatsapp-shared ./bin/whatsapp-mcp serve

Or add it to your launchd plist / systemd unit / shell profile so it persists across restarts.

Paths outside the allowed root are rejected with a clear error so Claude can ask you to move the file or update the env var. Symlinks inside the root are resolved before the check, so a symlink that points out of the root is also rejected. Do not place secrets inside the allowed root — the allowlist bounds what the tool can read or write, but anything inside is fair game.

Sandboxed clients (Claude.ai with Cowork, etc.)

Sandboxed MCP clients cannot read the daemon's local cache. To make downloaded media visible to them, point WHATSAPP_MCP_MEDIA_ROOT at a directory the client's sandbox can also read (a Cowork workspace mount, a shared volume, etc.), and tell the client to pass output_path on every download_media call into that root. A copy-pasteable system instruction:

When calling the WhatsApp MCP's download_media, always pass output_path set to a path under your shared workspace. Without it the decrypted file lands only in the daemon's local cache, which is outside your sandbox and unreadable. output_path must live under WHATSAPP_MCP_MEDIA_ROOT on the daemon side; the basename is yours to pick.

Architecture

One binary, seven internal packages:

cmd/whatsapp-mcp/       login / serve / smoke subcommands
internal/client/        whatsmeow client wrapper (send, download, events, history, features)
internal/daemon/        HTTP server, pairing state machine, /pair endpoint
internal/mcp/           mark3labs/mcp-go server + tool registrations
internal/media/         ogg parsing, waveform synthesis, ffmpeg shell-out
internal/security/      path allowlisting, filename sanitisation, log redaction
internal/store/         SQLite cache, LID resolution, query layer

Process lifecycle

serve runs as a long-lived HTTP daemon. MCP clients connect and disconnect freely; the daemon stays up and continues receiving WhatsApp events. A flock(2) on store/.lock prevents two instances racing on the same store (WhatsApp would kick one of the two linked-device connections anyway).

The trade-off: events are persisted to SQLite only while serve is running. If the daemon stops, the WhatsApp connection closes. On the next start, whatsmeow emits events.HistorySync events that backfill conversations into SQLite, but the recovery window is governed by WhatsApp's server-side retention for multidevice clients — not by this codebase. Messages that arrive during a gap long enough to outlast WhatsApp's retention are not recoverable. For shorter, known gaps, the request_sync tool triggers a per-chat backfill on demand.

Data storage

Everything lives under ./store/ (override with -store DIR):

  • store/messages.db — local chat/message cache, indexed for search.
  • store/whatsapp.db — whatsmeow's own device/session state.
  • store/.lock — ephemeral advisory lock for single-instance serve.

Data flow

  1. The client sends a JSON-RPC tools/call to serve over HTTP.
  2. The MCP layer dispatches to an internal handler.
  3. The handler either queries the local SQLite store or calls whatsmeow directly (send, download, reactions, etc.).
  4. Incoming WhatsApp events are persisted to the store in a background goroutine inside the same process, so query tools always see current state.

Running the daemon

The daemon is designed to run independently of any MCP client. Three supported lifecycle models:

macOS — launchd. Template at docs/launchd/com.sealjay.whatsapp-mcp.plist. Copy to ~/Library/LaunchAgents/, replace {{PATH_TO_REPO}} / {{STORE_DIR}} placeholders, launchctl load. Daemon runs from login onwards.

Linux — systemd user unit. Template at docs/systemd/whatsapp-mcp.service. Copy to ~/.config/systemd/user/, replace placeholders, systemctl --user enable --now whatsapp-mcp.

Claude Code SessionStart hook. For project-scoped lifetimes, drop docs/hooks/setup.sh into your project's .claude/hooks/ and configure settings.json to invoke it. The hook is idempotent — safe to run alongside launchd/systemd.

Manual. ./bin/whatsapp-mcp serve -addr 127.0.0.1:8765 in any terminal. Ctrl-C to stop.

Docker. A multi-stage Dockerfile builds the binary and ships it on debian:bookworm-slim with ffmpeg and CA certs. ENTRYPOINT bakes in -store /home/app/store; CMD defaults to serve and is a normal Docker command override (docker run whatsapp-mcp smoke, ... login, ... serve -addr ...). Persist /home/app/store or you lose the paired session on every restart:

docker build -t whatsapp-mcp --build-arg VERSION=$(git describe --tags --always) .

Pair once, before starting the long-running daemon — login and serve both take an exclusive lock on the store, so running login via docker exec against an already-running serve container fails with another whatsapp-mcp instance is already running. A one-off container sharing the same volume avoids that: no serve is running yet, so there's nothing to contend with, and the QR renders straight to your terminal with no browser or auth header involved.

docker run --rm -it -v whatsapp-mcp-store:/home/app/store whatsapp-mcp login

Then start the daemon proper:

docker run -d --name whatsapp-mcp -v whatsapp-mcp-store:/home/app/store whatsapp-mcp

The image binds 127.0.0.1:8765 inside the container by default, same as the binary — a plain -p 8765:8765 publish won't reach it, since

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryCommunication
Updated10d ago
Forks13

Languages

Go

Trust signals

97/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

1 info