wazap-mcp
Provides tools for interacting with a linked WhatsApp account, enabling management of chats, messages, media, contacts, and groups, including sending messages, searching history, downloading media, and administering group settings.
Click on "Install 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., "@wazap-mcpwhat did I miss on WhatsApp today?"
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.
██╗ ██╗ █████╗ ███████╗ █████╗ ██████╗
██║ ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
██║ █╗ ██║███████║ ███╔╝ ███████║██████╔╝
██║███╗██║██╔══██║ ███╔╝ ██╔══██║██╔═══╝
╚███╔███╔╝██║ ██║███████╗██║ ██║██║
╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝WhatsApp for your AI agent. An MCP server that puts your WhatsApp account — chats, messages, media, contacts, groups — behind 22 tools any MCP client can call. Pairing-code login, no browser, no phone-number reseller, ~20 MB of RAM.
Built on Baileys, which speaks the WhatsApp multi-device protocol over a WebSocket.
Get started
The npm package is wazap-mcp; the command it installs is wazap.
npx wazap-mcp setupThat is the whole install. It links your account, finds the MCP clients installed on this machine, writes their config and tells you what to restart.
Or have your agent do it. Paste this:
Set up WhatsApp for me: run npx wazap-mcp setup --agent and follow what it prints.
Then ask your agent: "what did I miss on WhatsApp today?"
Below are the steps setup runs for you. Each is still its own command when you
want to run it by hand.
npx wazap-mcp login shows a QR code; scan it from Settings → Linked devices
→ Link a device. No camera handy, or linking over SSH? npx wazap-mcp login --phone +15550100
prints an 8-character code you type under Link with phone number instead.
It ends by asking whether the agent may send messages; the answer is no unless
you say yes, and npx wazap-mcp config writes on changes it later.
npx wazap-mcp connect claude-code writes the MCP entry for one client. The
table under Connect a client has the rest.
npx wazap-mcp on its own is safe to run: it prints where you stand and what to do
next, and starts no server. When something is off, npx wazap-mcp status is the
first thing to run — it checks Node, the data directory, the lock, the
credentials and whether a newer version is out, and prints the fix next to
anything broken.
Connect a client
wazap connect <client> writes the entry for you, keeping whatever else is in
the file and backing it up once before the first change. --dry-run shows what
it would write.
Client | What |
| runs |
|
|
|
|
|
|
|
|
|
|
anything remote | client's MCP URL field: |
Any MCP client works the same way: the command is npx -y wazap-mcp, the transport
is stdio. Tell the agent to call learn first — it returns the id formats, the
workflows and every error code with what to do about it.
{
"mcpServers": {
"whatsapp": {
"command": "npx",
"args": ["-y", "wazap-mcp"]
}
}
}Claude Desktop, Cursor and Gemini CLI take exactly that. VS Code nests it under
servers and wants a "type": "stdio" alongside command. Codex CLI is TOML:
[mcp_servers.whatsapp]
command = "npx"
args = ["-y", "wazap-mcp"]The skills/ folder follows the Agent Skills format, so Codex, Cursor and other skill-aware agents can load the same five skills.
Related MCP server: wa-bridge
Tools
Tool | Kind | What it does |
| read | The guide to every tool, id format and error code. Call it first. |
| read | Connection status, sync state, linked account, versions, data dir. |
| read | Conversations newest-first; filter |
| read | Messages in a chat; |
| read | Everything from the last N hours, grouped by chat. The catch-up tool. |
| read | Text search across the locally held messages. |
| read | One message in full, with its quoted message and reactions. |
| read | Find contacts by name or number. |
| read | Name, number, about text, profile picture. |
| read | Participants, admins, announcement mode, invite link (when you are admin). |
| read | Save an attachment to disk; small images also come back inline. |
| write | Send text, optionally as a reply, with @-mentions. |
| write | Send an image, video, audio, voice note or document from a path or URL. |
| write | Send a poll with 2–12 options. |
| write | Send a map pin. |
| write | Edit your own message, within WhatsApp's 15-minute window. |
| write | Add or remove an emoji reaction. |
| write | Forward a message to another chat. |
| write | Retract your own message, within WhatsApp's 2-day window. |
| write | Archive, pin, mute (8h by default), mark read/unread. |
| write | Create a group and add participants. |
| write | Add, remove, promote, demote, leave, rename, invite links. |
Every message comes back with a non-empty text: media and system messages
carry a placeholder such as [image] caption, [voice message], [deleted] or
[poll] Pizza or pasta?. Timestamps are ISO 8601 with the machine's UTC offset,
alongside a human age like 2h ago.
Skills
wazap ships five Agent Skills that teach an agent the workflows behind the tools, not just the tools:
Skill | What the agent does |
| Diagnose with |
| "What did I miss?" Triage into needs you / FYI / noise, ranked, plus forgotten replies. Read-only |
| "Find the invoice Dan sent." Search with query variants, page back in time, download and read the file. Read-only |
| Catch up on a 300-message group: decisions, dates, what is asked of you. Read-only |
| Draft in the chat's own register, show recipient and text, send only after the user says yes |
Install everything (server and skills) as a Claude Code plugin:
/plugin marketplace add razvangirgiz/wazap
/plugin install wazap@wazapOr copy skills/<name>/ into any skills directory your agent reads.
Errors
Every failure is a structured { error, message, fix } rather than a stack
trace, so an agent can decide whether to retry, ask the user, or stop.
Code | Meaning |
| No account linked. Run |
| Unlinked from the phone. Run |
| Credentials unreadable. Run |
| Still connecting or reconnecting. |
| History sync has not finished; results may be partial. |
| Number is not in international format. |
| Not a WhatsApp chat, contact or group id. |
| That number has no WhatsApp account. |
| Unknown id. |
| Group permissions. |
| WhatsApp expired the file, or it was never synced here. |
| Outbound media problems. |
| Over WhatsApp's message limit. |
| WhatsApp's own limits on editing and deleting. |
| wazap is running read-only. |
| Too many writes; |
| WhatsApp did not answer, or rejected the operation. |
Data directory
Everything lives in ~/.wazap (override with --data-dir or WAZAP_DATA_DIR),
created 0700 with credentials written 0600:
~/.wazap/
auth/ WhatsApp credentials — treat this like a password
media/ downloads from download_media
history/ per-chat message history, so a restart is not amnesia
store.json chat-list snapshot
server.lock pid of the running server
daemon.json loopback endpoint a second wazap bridges to
.env optional settings, see .env.exampleCredential writes go to a temp file and are renamed into place, so killing the process mid-write cannot leave you re-linking your phone.
Several clients at once
Claude Desktop, Claude Code and Cursor each launch their own wazap. WhatsApp
allows one socket per linked device, so they share one session instead of
fighting over it. The first wazap on a data directory owns the session and
opens an MCP endpoint on 127.0.0.1; every later one bridges to it over that
endpoint. There is nothing to configure, and no client can tell the difference.
The owner publishes <data-dir>/daemon.json (0600) with its pid, its port
and the token a bridge authenticates with.
A bridge serves whatever the owner exposes, so an owner started --read-only
makes every client read-only, whatever flags that client was launched with.
When the owner exits, the bridges exit with it, and the next wazap a client
starts becomes the new owner.
WAZAP_NO_SHARE=1 opts out: a second wazap on the same directory exits with
code 2 naming the pid of the one already running. An explicit --http is a
server of its own rather than a bridge, and is refused the same way.
Read-only mode
Writes are opt-in. login asks once and stores the answer in
<data-dir>/.env; wazap config writes on|off changes it, and wazap config
alone prints every effective setting with where it came from.
WAZAP_READ_ONLY=1 or wazap serve --read-only does not register the write
tools at all. The agent never sees them, so it cannot message anyone from your
number even by mistake — useful when the linked account is your personal one.
Writes are also rate limited to WAZAP_RATE_LIMIT per minute (default 20, 0
disables). Sending faster than a human is how accounts get banned.
HTTP mode
WAZAP_READ_TOKEN=$(openssl rand -hex 32) \
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32) \
npx wazap-mcp serve --http --host 0.0.0.0 --port 8766Streamable HTTP at /mcp, with a health check at /healthz. Two bearer tokens:
the read token gets the read tools, the write token also unlocks the write
tools, so a leaked read token can never message anyone. wazap refuses to bind a
non-loopback address without a read token.
Self-host
Run wazap on a server of your own when the agent is not on your laptop: another machine, a VPS, a client's infrastructure. The session stays on that server; nothing goes through a third party.
With systemd
npm install -g wazap-mcp
sudo useradd --system --home /var/lib/wazap --create-home wazap
sudo -u wazap WAZAP_DATA_DIR=/var/lib/wazap wazap login --phone +15550100 # pairing code works over SSH
sudo -u wazap tee /var/lib/wazap/.env >/dev/null <<END
WAZAP_READ_TOKEN=$(openssl rand -hex 32)
WAZAP_WRITE_TOKEN=$(openssl rand -hex 32)
END
sudo curl -fsSL https://raw.githubusercontent.com/razvangirgiz/wazap/main/deploy/wazap.service -o /etc/systemd/system/wazap.service
sudo systemctl enable --now wazap
curl -s http://127.0.0.1:8766/healthzThe unit binds loopback only. Put TLS in front with the two-line deploy/Caddyfile (caddy run --config deploy/Caddyfile after editing the hostname) or any reverse proxy, then point the client at https://your-host/mcp with Authorization: Bearer <read or write token>.
With Docker
git clone https://github.com/razvangirgiz/wazap && cd wazap
printf 'WAZAP_READ_TOKEN=%s\nWAZAP_WRITE_TOKEN=%s\n' $(openssl rand -hex 32) $(openssl rand -hex 32) > .env
docker compose run --rm wazap login --phone +15550100 # once; the session lands in the wazap-data volume
docker compose up -d
curl -s http://127.0.0.1:8766/healthzThe container publishes 8766 on loopback only; add the same TLS proxy in front. Upgrading is git pull && docker compose up -d --build; the volume keeps the session.
Which clients can reach it
Claude Code, Claude Desktop, Cursor, Codex, VS Code and any client with an "MCP URL + header" field connect with the bearer token. claude.ai Connectors require OAuth rather than a static token, so they cannot use a self-hosted wazap yet. Keep the read token in clients that only need to read; hand out the write token deliberately.
Settings
Variable | Default | Meaning |
|
| Where everything is stored. |
|
| Do not register the write tools. |
|
| Ask WhatsApp for a fuller history sync. |
|
| Keep chats and messages across restarts. |
|
| Write tool calls per minute; |
|
|
|
|
| HTTP bind address. |
| unset | HTTP bearer tokens. |
|
|
|
Flags beat environment variables, which beat <data-dir>/.env.
Known limitations
Unofficial. Baileys reverse-engineers the WhatsApp multi-device protocol. This is not the WhatsApp Business API and Meta does not support it.
Ban risk is real. Automated sending, bulk messaging or anything a human would not plausibly type can get the number banned, and that is not recoverable from here. The rate limit helps; it is not a guarantee.
Media keys expire. WhatsApp drops old attachments from its servers, so
download_mediaon an old message returnsMEDIA_UNAVAILABLE.History is what the phone syncs. wazap sees the history WhatsApp hands the linked device, not your full phone archive.
read_messageswithbeforeasks for more, within whatever WhatsApp still keeps.@lidids. Newer accounts are addressed by a privacy id rather than a phone number. wazap translates them back to phone numbers when it has learned the mapping, and passes the@lidthrough when it has not.Your phone must stay reachable. A linked device stops receiving once the phone has been offline long enough;
get_statussays so inhint.
Development
npm install
npm run typecheck
npm test # builds, then runs node --test
node test/smoke-stdio.mjs # drives the built binary over MCP stdio
npm run dev -- status # run from source with tsxnpm test needs no WhatsApp session. The stdio smoke test spawns the built
binary against a throwaway data directory and checks that an unlinked install
still answers initialize, tools/list and get_status.
MIT licensed.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceWhatsApp MCP server that exposes messaging, groups, contacts, and profile management as tools and resources for AI agents, supporting Baileys and Meta Cloud API.19
- AlicenseNot gradedqualityAmaintenanceA self-hosted WhatsApp bridge that exposes a stdio MCP server with ~20 tools for reading conversations, sending messages, managing groups, contacts, and aliases, enabling AI agents to operate WhatsApp directly.2MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that connects AI agents to WhatsApp using the multi-device API, enabling messaging, group management, and more as a regular user.15MIT
- AlicenseNot gradedqualityAmaintenanceA native MCP server for SocialMate that gives your AI a WhatsApp, enabling it to send and read messages, manage contacts and groups, and more through 44 tools.831MIT
Related MCP Connectors
Free public MCP for AI agents — 193 tools, 44 workflows. No API key.
Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.
Managed LinkedIn MCP server for AI agents: search, connect, message and enrich on accounts you own.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/razvangirgiz/wazap'
If you have feedback or need assistance with the MCP directory API, please join our Discord server