uni-msg-mcp-server
v0.3.1
Published
Model Context Protocol server for uni-msg — drive WhatsApp from Claude, Cursor or any MCP client.
Maintainers
Readme
uni-msg-mcp-server
Drive WhatsApp from Claude, Cursor, or any MCP client — using the same API key as the REST API. No separate credential, no OAuth.
Setup
Create a key in Dashboard → API Keys, then point your client at the hosted endpoint. Nothing to install, and it stays current without anyone upgrading a package.
https://uni-msg.com/mcp Authorization: Bearer <key>
https://uni-msg.com/mcp/<key> for clients that cannot send headersClaude Code
claude mcp add --transport http uni-msg https://uni-msg.com/mcp \
--header "Authorization: Bearer wsa_your_key"Cursor — ~/.cursor/mcp.json
{ "mcpServers": { "uni-msg": {
"url": "https://uni-msg.com/mcp",
"headers": { "Authorization": "Bearer wsa_your_key" }
} } }Gemini CLI — ~/.gemini/settings.json
httpUrl selects Streamable HTTP; url would mean SSE.
{ "mcpServers": { "uni-msg": {
"httpUrl": "https://uni-msg.com/mcp",
"headers": { "Authorization": "Bearer wsa_your_key" }
} } }Claude Desktop
Settings → Connectors → Add custom connector, URL https://uni-msg.com/mcp,
header Authorization: Bearer wsa_your_key.
ChatGPT
Developer mode (Settings → Apps → Advanced), then add a connector with URL
https://uni-msg.com/mcp/wsa_your_key and No authentication. It is the only
client that cannot send a header, which is why the key sits in the path — and
why nginx disables access logging on /mcp.
Running it locally
Not required — the hosted endpoint above needs no install. Use this if you would rather the API calls left your own machine.
{ "mcpServers": { "uni-msg": {
"command": "npx",
"args": ["-y", "uni-msg-mcp-server"],
"env": { "UNIMSG_API_KEY": "wsa_your_key" }
} } }Needs Node 20+. ChatGPT cannot use this form — it has no way to run a local process.
Pairing a number
Three steps, and the tool descriptions walk the assistant through them:
create_devicewith a name and the number in international formatconnect_devicereturns an 8-character pairing code- On the phone holding that number: WhatsApp → Settings → Linked devices → Link a device → Link with phone number instead → type the code
The code expires in about two minutes. If it lapses use request_pairing_code
rather than reconnecting — it is cheaper and avoids churning the session. Poll
get_device_status until it reports connected.
Notes
Sends are immediate and cannot be recalled. The tool descriptions instruct the assistant to confirm the recipient first, but that is guidance, not a guarantee — treat this as you would a shell with production access.
Only a device whose status is connected can deliver. list_devices first
saves a confusing failure later.
Reading message history is exposed: list_conversations finds the peer
value, then read_thread returns that thread newest-first with paging.
Errors come back as tool results rather than thrown exceptions, so the model can read the reason and correct itself. Anything key-shaped in an error is redacted before it reaches the model. Diagnostics go to stderr — stdout is the JSON-RPC stream and a stray byte there corrupts the protocol.
