WhatsApp MCP for Claude: Give Your Agent a WhatsApp Number
Add the Chatmaid WhatsApp MCP server to Claude Code, Cursor or Claude Desktop so your agent can send WhatsApp messages from your number and read replies.

The Chatmaid MCP server gives Claude Code, Claude Desktop, Cursor and other MCP clients a set of WhatsApp tools that run on your own WhatsApp number. Your agent can send messages to people and groups, read the messages you receive, and check whether a message was delivered. In Claude Code, setup is one command:
claude mcp add chatmaid --env CHATMAID_API_KEY=sk_test_xxx -- npx -y @chatmaid/mcpStart with a free sandbox key (sk_test_). Nothing reaches WhatsApp until you swap in a live key.
What is the Chatmaid MCP server?
Model Context Protocol (MCP) is an open standard that lets AI agents call external tools. An MCP server describes its tools to the agent, and the agent decides when to call them and with which arguments.
@chatmaid/mcp is an open-source MCP server for the Chatmaid Developers API. The source is on GitHub at github.com/chatmaid/mcp under the MIT license, so you can read exactly what each tool sends. It runs on your machine through npx, talks to your client over stdio, and turns each tool call into a request to the REST API at https://developers-api.chatmaid.net/v1. Arguments are checked before the request goes out, and API errors come back as readable text the agent can act on. You need Node.js 18 or later.
As of October 2026 (version 0.3.1), the server has eleven tools:
| Tool | What it does |
|---|---|
| send_message | Sends text, media, or media with a caption to a phone number or a group |
| list_phone_numbers | Lists the sender numbers on your account and the IDs send_message needs |
| get_phone_number | Shows details for one number, by ID or E.164 number |
| get_phone_status | Checks whether a number is connected to WhatsApp right now |
| list_groups | Lists the groups a connected number can post to, with their group IDs |
| list_messages | Lists sent messages, filtered by status or sender number, with paging |
| get_message | Fetches one sent message with its status and timestamps |
| list_inbound_messages | Lists messages your numbers received (live keys only) |
| get_inbound_message | Fetches one received message by its inmsg_ ID |
| get_account | Shows your account name, email and subscription status |
| get_usage | Shows message and API request counts for a day, week or month |
Get an API key first
- Create a free account from the Chatmaid Developers page.
- Open API Keys, click Create API Key and choose Test (sk_test_*).
- New accounts start in Test Mode. Open Phone Numbers, click Add Number, then Connect. Test numbers connect instantly, with no QR code.
Sandbox keys are free and need no subscription. Live keys (sk_live_) come with the Developers plan, $7.99 a month flat, and need a real number connected by scanning a QR code with WhatsApp on your phone. There is no Meta Business verification and no template approval. For background on that, read WhatsApp API without Meta Business verification.
How to install it in Claude Code
Run this in a terminal from your project folder, with your own key in place of sk_test_xxx:
claude mcp add chatmaid --env CHATMAID_API_KEY=sk_test_xxx -- npx -y @chatmaid/mcpEverything after -- is the command Claude Code runs to start the server. Keep the server name (chatmaid) before --env: the flag takes several KEY=value pairs, so a name placed right after it gets read as one more pair.
By default the server gets local scope: it loads only in this project and is stored in ~/.claude.json, outside your repository. To use it in every project, add --scope user:
claude mcp add chatmaid --scope user --env CHATMAID_API_KEY=sk_test_xxx -- npx -y @chatmaid/mcpAvoid --scope project when the key is in the command. That scope writes the server to a .mcp.json file at your project root, which is meant to be committed and shared with your team. The scopes are explained in the Claude Code MCP docs.
To check the connection, run claude mcp list in your terminal, or type /mcp inside Claude Code. The chatmaid server should show as connected. Connected only means the server started, because it starts even without a valid key. To test the key, ask Claude to list your Chatmaid phone numbers. A 401 error means the key is wrong. An empty list means no number has been added in that key's environment (test or live).
How to install it in Claude Desktop
In Claude Desktop, open Settings > Developer > Edit Config, or open the config file directly: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or %APPDATA%\Claude\claude_desktop_config.json on Windows. Add this entry, save, then fully quit and reopen Claude Desktop:
{
"mcpServers": {
"chatmaid": {
"command": "npx",
"args": ["-y", "@chatmaid/mcp"],
"env": {
"CHATMAID_API_KEY": "sk_test_xxx"
}
}
}
}If the file already has an mcpServers block, add the chatmaid entry inside it rather than pasting a second block.
How to install it in Cursor
Add the same JSON to ~/.cursor/mcp.json, and create the file if it does not exist. Save the file and restart Cursor so it picks up the server. To limit the server to one project, put the JSON in .cursor/mcp.json inside that project instead, as described in Cursor's MCP docs.
How to install it in Windsurf (Devin Desktop)
Windsurf was renamed Devin Desktop in June 2026, according to the Devin Desktop FAQ. It reads the same mcpServers format: add the chatmaid entry from the block above to ~/.config/devin/mcp_config.json on macOS and Linux, or %APPDATA%\devin\mcp_config.json on Windows, and save. Builds released before the rename read ~/.codeium/windsurf/mcp_config.json. The current paths are in Devin's MCP docs.
For VS Code, the README on GitHub has a setup that prompts for the key and stores it securely instead of writing it into the config file. Any other MCP client can run the same npx -y @chatmaid/mcp command with CHATMAID_API_KEY set in its environment. The optional CHATMAID_BASE_URL variable points the server at a different API host; it defaults to https://developers-api.chatmaid.net.
What can your agent do with it?
Once the server is connected, ask in plain language and the agent picks the tools. Some examples, with the tools it calls:
Send yourself a summary when a task finishes
"Run the test suite. When it finishes, send a WhatsApp to +15555550123 with the pass and fail counts."
The agent calls list_phone_numbers to find your sender ID, runs the tests, then calls send_message. Phone numbers go in E.164 format: a plus sign, the country code and the number, with no spaces or dashes.
Post a deploy notice in a team group
"Deploy to staging, then post the commit hash in our Engineering WhatsApp group."
The agent calls list_groups to find the group's ID, which ends in @g.us, and passes it to send_message as the recipient. The sending number has to be a member of the group and allowed to post in it. Groups it cannot post in, such as announcement-only groups where it is not an admin, are left out of the list. For more team-alert patterns, see WhatsApp as an internal ops channel.
Send a document to a client
"Send the proposal at https://example.com/files/proposal.pdf to +15555550123 with a short note saying it's attached."
Attachments go in mediaUrls as public HTTPS links. Plain http:// links are rejected, so a file on your laptop has to be uploaded somewhere reachable first. Text can be up to 4,096 characters. Text with a single attachment goes out as one captioned message. With several attachments, the text is sent first as its own message and each file follows separately.
Check whether a message was delivered
"Did the message you just sent get delivered?"
The agent calls get_message with the ID that send_message returned. A message moves from pending to sent, delivered and read. read may never arrive if the recipient has read receipts turned off.
If a send fails, send_message returns an error with the HTTP status and a plain explanation. When WhatsApp itself refuses the send, the message is also stored as failed with a code such as NOT_GROUP_MEMBER or RECIPIENT_NOT_REACHABLE, so asking the agent to list failed messages shows what went wrong. If the sending number is already marked disconnected, the call is rejected before anything is stored, so it's worth asking the agent to run get_phone_status first.
Summarize what customers sent
"Read the last 20 messages received on our support number and group them by topic."
The agent calls list_phone_numbers, then list_inbound_messages filtered to that number. This one needs a live key.
How does the sandbox behave?
With an sk_test_ key, every tool answers, but nothing is sent to WhatsApp:
send_messagestores the message, marks itsentright away, and fires amessage.sentwebhook if you have configured a webhook and subscribed to that event. Sandbox messages stay atsent, becausedeliveredandreadcome from WhatsApp receipts.list_groupsreturns two fixed sample groups, so you can test a group send from start to finish.list_inbound_messagesalways returns an empty list. Received messages only exist on live numbers.- Keys and numbers belong to one environment. A test key can only send from sandbox numbers, and a live key only from live numbers.
To go live:
- Subscribe under Billing in the dashboard.
- Click Switch to Live in the dashboard banner.
- In Phone Numbers, click Add Number, then Connect, and scan the QR code from WhatsApp > Linked devices on your phone.
- In API Keys, click Create API Key and choose Live (sk_live_*).
- Swap the key. In Claude Code, run
claude mcp remove chatmaid, then the sameclaude mcp addcommand with the live key (keep--scope userif you used it). In Claude Desktop, Cursor and other JSON configs, editCHATMAID_API_KEYand restart the client.
The tools and your prompts stay the same. Switch back to a sandbox key whenever you change what the agent is allowed to do.
How does the agent read incoming messages?
list_inbound_messages and get_inbound_message show the agent what people sent to your connected numbers: the sender, the text, the message type and when it arrived. Messages from a group include a groupId, which the agent can pass straight to send_message to answer in that group. The list includes every chat on the connected number, groups included, so consider connecting a number used only for this work rather than your personal one.
Two patterns work well:
- Triage. Ask the agent to read the last 50 messages received on a number (the list is newest first), sort them by urgency, and forward the urgent ones to your personal number. There is no unread flag, so give it a cut-off, such as "received since 9:00 today".
- Drafted replies. Let the agent draft answers from your docs or product notes, and review them before it sends. An agent replying on its own from your number is speaking for you.
MCP tools only run when the agent calls them. To react the moment a message arrives, subscribe to the message.received webhook instead. How to receive WhatsApp messages with webhooks walks through it.
Why give your agent tools instead of code?
Without MCP, adding WhatsApp to a task means reading the API reference, writing the auth header, handling errors and wiring the result back into your workflow. With the server installed, the agent already has described, typed tools, so you state the outcome and it fills in the arguments.
Idempotency keys make retries safe. send_message accepts an optional idempotencyKey of up to 64 characters. If the agent retries with the same key after a timeout, Chatmaid returns the original message instead of sending a second one. A send that failed returns the same error again under that key, so a fresh attempt needs a new key. Agents don't always add a key on their own, so ask for one, for example: "Send the deploy notice with idempotency key deploy-4f2a91c."
The llms.txt alternative
If you want the agent to write integration code rather than call tools, give it the docs. Chatmaid publishes its full developer documentation as Markdown (the MDX source of each page) in the llms.txt format:
curl https://www.chatmaid.net/llms-full.txtllms-full.txt is the whole documentation in one file. https://www.chatmaid.net/llms.txt is a short index that links to each page, and adding .mdx to a docs URL returns that page's source, for example https://www.chatmaid.net/docs/mcp.mdx.
Both approaches use the same API key and the same endpoints. The MCP server suits interactive work where the agent acts for you. The docs suit work where you want code you will deploy, like the REST examples in How to connect your AI agent to WhatsApp. The full MCP reference is in the MCP setup docs.
Frequently asked questions
Is the Chatmaid MCP server free?
The server itself is free and open source, and sandbox keys are free with no subscription, so you can try every tool at no cost. Sending real WhatsApp messages needs a live key, which comes with the Chatmaid Developers plan at $7.99 a month flat.
Does it use the official WhatsApp Business API?
No. It sends from your own WhatsApp number, which you connect by scanning a QR code, so there is no Meta Business verification. Message people who expect to hear from you: accounts get restricted when they behave like spam, such as unsolicited bulk messages to people who do not have you saved.
Does it work in claude.ai or the Claude mobile app?
No. claude.ai in the browser and the Claude mobile apps connect to MCP servers by URL, through Anthropic's cloud, and @chatmaid/mcp runs as a local process on your computer. Use Claude Desktop on macOS or Windows, or Claude Code.
Can my agent read replies?
Yes, with a live key. list_inbound_messages returns messages received by your connected numbers, and get_inbound_message fetches one by ID. With a sandbox key the inbound list is always empty.
Why does my agent say the phone number was not found?
Keys only see numbers from their own environment. A sandbox key cannot use a live number, and a live key cannot use a sandbox number. Check that the key in your MCP config matches the environment where you added the number.
Does it work with VS Code?
Yes. The README on GitHub has a VS Code setup that asks for the key instead of storing it in plain text. Any MCP client that can start a local command works the same way.


