pywa-mcp-server
by ianaleck
README.md
# ๐ฌ pywa MCP Server
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](https://github.com/david-lev/pywa)
[](https://opensource.org/licenses/MIT)
[](https://github.com/ianaleck/pywa-mcp-server)
> **Unofficial** Model Context Protocol (MCP) server that exposes the [pywa](https://github.com/david-lev/pywa) WhatsApp Cloud API client as MCP tools.
**โ ๏ธ Disclaimer:** Unofficial, third-party integration. Not affiliated with, endorsed by, or sponsored by WhatsApp, Meta, or the pywa project.
## โจ Features
- ๐ **Full pywa surface** โ ~100 tools auto-discovered from the pywa `WhatsApp` client
- ๐ก๏ธ **Type coercion** โ auto-parses JSON strings, hydrates dataclasses, coerces enums
- ๐ฆ **Smart serialization** โ bytes โ base64, datetime โ ISO, Path โ string, enum โ value, dataclass โ dict
- ๐๏ธ **Allowlist control** โ restrict exposed tools via `PYWA_MCP_TOOLS` env
- โ๏ธ **Var-args support** โ pywa methods with `*args` exposed via an `_args` field
- ๐งช **Unit-tested** โ 37 tests covering serialization, coercion, schema, discovery
- ๐ **MCP compliant** โ works with Claude Code, Claude Desktop, Cursor, Cline, etc.
## ๐ Quick Start
### Prerequisites
- Python 3.13+
- [`uv`](https://docs.astral.sh/uv/)
- A Meta-approved WhatsApp Business phone number + access token
- An MCP-compatible client
### 1. Get pywa credentials
From the [Meta Business dashboard](https://business.facebook.com/):
- **Phone Number ID** โ Meta โ WhatsApp โ API Setup
- **Access token** โ system-user token (permanent) or temporary
- **WABA ID** โ required for templates / flows / QR codes
- **App ID / App secret** โ required for update validation + callback registration
### 2. Register with Claude Code
#### Option A โ `claude mcp add` (recommended, zero-install)
Runs the server directly from PyPI via `uvx` โ no clone required.
Basic syntax:
```bash
claude mcp add [options] <name> -- <command> [args...]
```
Real example:
```bash
claude mcp add --transport stdio --scope user \
--env WHATSAPP_PHONE_ID=<phone-id> \
--env WHATSAPP_TOKEN=<token> \
--env WHATSAPP_WABA_ID=<waba-id> \
--env WHATSAPP_APP_ID=<app-id> \
--env WHATSAPP_APP_SECRET=<app-secret> \
pywa \
-- uvx --from pywa-mcp-server pywa-mcp-server
```
Scope (`--scope` / `-s`):
- `local` (default) โ private to this project
- `user` โ across all your projects
- `project` โ committed via `.mcp.json`
Other useful commands:
```bash
claude mcp list # list all configured servers
claude mcp get pywa # show details + health-check pywa
claude mcp remove pywa # remove from config
claude mcp add-json pywa '<json>' # add via raw JSON string
claude mcp add-from-claude-desktop # import servers from Claude Desktop (Mac/WSL)
claude mcp reset-project-choices # reset approved/rejected project-scoped servers
claude mcp serve # run Claude Code itself as an MCP server
```
To run from latest git (unreleased changes) instead of PyPI:
```bash
... -- uvx --from git+https://github.com/ianaleck/pywa-mcp-server pywa-mcp-server
```
#### Option B โ `.mcp.json` in the project
```bash
cp .mcp.json.example .mcp.json
# edit credentials; .mcp.json is gitignored
```
#### Option C โ Claude Desktop / Cursor / Cline / other clients
Any MCP client that supports stdio works. Add:
```json
{
"mcpServers": {
"pywa": {
"command": "uvx",
"args": ["--from", "pywa-mcp-server", "pywa-mcp-server"],
"env": {
"WHATSAPP_PHONE_ID": "...",
"WHATSAPP_TOKEN": "...",
"WHATSAPP_WABA_ID": "...",
"WHATSAPP_APP_ID": "...",
"WHATSAPP_APP_SECRET": "..."
}
}
}
}
```
### Local development install
If you're modifying the server, clone and run from source:
```bash
git clone https://github.com/ianaleck/pywa-mcp-server.git
cd pywa-mcp-server
uv sync
# then point claude mcp add at:
# uv --directory /absolute/path/to/pywa-mcp-server run pywa-mcp-server
```
## ๐ฏ What You Can Do
Once connected, you can ask Claude to:
### ๐ฌ Messaging
- "Send a WhatsApp text to +27..., 'Order confirmed'"
- "Send the totp template to +27... with code 483921"
- "React to message wamid.xxx with ๐"
### ๐ Templates
- "List all my approved templates"
- "Create a UTILITY template called 'order_shipped' with one body variable"
- "Show me the totp template details"
### ๐ Flows
- "List all published flows"
- "Show metrics for the customer_pick flow over the last 30 days"
- "Fetch the JSON for flow 903243286082414"
### ๐ผ๏ธ Media
- "Upload this image URL and send it to +27..."
- "Download media wamid.xxx to /tmp"
### ๐ QR Codes
- "Create a QR code with the message 'Hi Orana!'"
- "Update QR code XYZ123 with a new prefilled message"
### ๐ฅ Health & Diagnostics
- "Check my WABA health status"
- "What's blocking my business-initiated sends?"
## ๐ ๏ธ Tool Catalog
Auto-discovered from `pywa.WhatsApp`. Full pywa docs at [pywa.readthedocs.io](https://pywa.readthedocs.io).
<details>
<summary><strong>๐ฌ Send messages (16 tools)</strong></summary>
- `send_text` / `send_message`
- `send_image` / `send_video` / `send_audio` / `send_voice`
- `send_document` / `send_sticker`
- `send_location` / `send_contact`
- `send_reaction` / `remove_reaction`
- `send_template`
- `send_catalog` / `send_product` / `send_products`
- `request_location`
</details>
<details>
<summary><strong>๐ Templates (9 tools)</strong></summary>
- `get_template` / `get_templates`
- `create_template` / `update_template` / `delete_template`
- `compare_templates` (uses `_args` for second template ID)
- `unpause_template`
- `upsert_authentication_template`
- `migrate_templates`
</details>
<details>
<summary><strong>๐ Flows (11 tools)</strong></summary>
- `get_flow` / `get_flows` / `get_flow_assets` / `get_flow_metrics`
- `create_flow` / `update_flow_json` / `update_flow_metadata`
- `publish_flow` / `deprecate_flow` / `delete_flow`
- `migrate_flows`
</details>
<details>
<summary><strong>๐ผ๏ธ Media (5 tools)</strong></summary>
- `upload_media` / `download_media`
- `get_media_url` / `get_media_bytes` (returns base64-wrapped bytes)
- `delete_media`
- โ ๏ธ `stream_media` returns a Python generator โ unusable via MCP. Use `get_media_bytes` or `download_media` instead.
</details>
<details>
<summary><strong>๐ QR Codes (5 tools)</strong></summary>
- `create_qr_code`
- `get_qr_code` / `get_qr_codes`
- `update_qr_code`
- `delete_qr_code`
</details>
<details>
<summary><strong>๐ข Business profile & account (5 tools)</strong></summary>
- `get_business_profile` / `update_business_profile`
- `get_business_account`
- `get_commerce_settings` / `update_commerce_settings`
</details>
<details>
<summary><strong>๐ Phone numbers (7 tools)</strong></summary>
- `get_business_phone_number` / `get_business_phone_numbers`
- `get_business_phone_number_settings` / `update_business_phone_number_settings`
- `update_display_name`
- `register_phone_number` / `deregister_phone_number`
</details>
<details>
<summary><strong>โ๏ธ Calling API (6 tools)</strong></summary>
Requires SIP configuration; may be blocked if not enabled.
- `initiate_call` / `terminate_call`
- `pre_accept_call` / `accept_call` / `reject_call`
- `get_call_permissions`
</details>
<details>
<summary><strong>๐ช Webhook configuration (6 tools)</strong></summary>
Note: this server doesn't run a webhook receiver โ registration only.
- `set_app_callback_url`
- `override_phone_callback_url` / `override_waba_callback_url`
- `delete_phone_callback_url` / `delete_waba_callback_url`
- `set_business_public_key`
</details>
<details>
<summary><strong>๐ซ Block users (3 tools)</strong></summary>
- `block_users` / `unblock_users`
- `get_blocked_users`
</details>
<details>
<summary><strong>๐ฌ Conversation utilities (3 tools)</strong></summary>
- `mark_message_as_read`
- `indicate_typing`
- `update_conversational_automation`
</details>
<details>
<summary><strong>๐ง Misc (1 tool)</strong></summary>
- `get_app_access_token`
</details>
## โ๏ธ Environment Variables
| Variable | Required | Notes |
|---|---|---|
| `WHATSAPP_PHONE_ID` / `WA_PHONE_ID` | โ
| Phone Number ID |
| `WHATSAPP_TOKEN` / `WA_TOKEN` | โ
| System-user or business access token |
| `WHATSAPP_WABA_ID` / `WA_BUSINESS_ACCOUNT_ID` | โ ๏ธ | WABA-scoped methods (templates, flows, QR codes) |
| `WHATSAPP_APP_ID` / `WA_APP_ID` | โ ๏ธ | Callback registration with APP scope |
| `WHATSAPP_APP_SECRET` / `WA_APP_SECRET` | โ ๏ธ | Update validation + APP-scoped callbacks |
| `PYWA_MCP_TOOLS` | โ | Comma-separated allowlist. Unset = all minus `DEFAULT_SKIP`. |
## ๐๏ธ Tool Filtering
**Default:** every public pywa method except `listen` (which blocks indefinitely).
**Allowlist:** set `PYWA_MCP_TOOLS=send_text,get_templates,send_template` to expose only those.
## โ ๏ธ Caveats
- **No inbound webhook.** This server only sends/admin. `listen`, `on_*`, `webhook_*` register handlers / wait for inbound updates, but no FastAPI/Flask is run. For inbound support, run pywa's webhook in a separate process.
- **`stream_media`** returns a Python generator โ unusable via MCP JSON transport. Use `get_media_bytes` (base64) or `download_media` (writes to disk, returns path).
- **24-hour window.** Free-form sends to a user require they messaged you in the last 24h. Otherwise use an approved template.
- **WABA health.** Check `get_business_account` / `get_business_phone_number` โ payment, calling SIP, and other issues cause silent send failures (`can_send_message=BLOCKED`).
- **Schema drops type info for unions.** MCP transport may stringify complex args; this server compensates by JSON-parsing strings when target type expects list/dict/dataclass.
## ๐ Response Serialization
| Input | Output |
|---|---|
| `bytes` | `{"_bytes_b64": "...", "size": N}` |
| `pathlib.Path` | string |
| `datetime` / `date` / `time` | ISO 8601 |
| `timedelta` | seconds (float) |
| `enum.Enum` | `.value` |
| dataclass | recursive dict |
| pydantic `BaseModel` | `model_dump(mode="json")` |
| other | JSON if serializable, else `repr()` |
## ๐งช Development
```bash
git clone https://github.com/ianaleck/pywa-mcp-server.git
cd pywa-mcp-server
uv sync
# Run tests
uv run pytest tests/
# With coverage
uv run pytest tests/ --cov=main --cov-report=term-missing
```
37 unit tests, ~70% coverage. Remainder is async server boot (not unit-testable).
## ๐ API Requirements
This server requires a [WhatsApp Cloud API](https://developers.facebook.com/docs/whatsapp/cloud-api) account. You must comply with:
- [WhatsApp Business Platform Terms](https://www.whatsapp.com/legal/business-policy)
- [WhatsApp Cloud API rate limits](https://developers.facebook.com/docs/whatsapp/cloud-api/overview#rate-limits)
- [Meta Platform Terms](https://developers.facebook.com/terms/)
## ๐ค Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes with tests
4. Ensure all tests pass (`uv run pytest tests/`)
5. Commit your changes
6. Open a Pull Request
## ๐ License
MIT โ see [LICENSE](LICENSE).
## ๐ Acknowledgments
- [pywa](https://github.com/david-lev/pywa) by David Lev โ the underlying WhatsApp Cloud API client
- [Model Context Protocol](https://modelcontextprotocol.io/) โ protocol spec
- [Anthropic](https://www.anthropic.com/) โ Claude and the MCP SDK
- [Meta](https://developers.facebook.com/docs/whatsapp/cloud-api) โ WhatsApp Cloud API
## ๐ Support
- ๐ [Bug Reports](https://github.com/ianaleck/pywa-mcp-server/issues)
- ๐ก [Feature Requests](https://github.com/ianaleck/pywa-mcp-server/discussions)
- ๐ [MCP Documentation](https://modelcontextprotocol.io/docs)
- ๐ [pywa Documentation](https://pywa.readthedocs.io)
---
<div align="center">
**Made with โค๏ธ for the MCP community**
[โญ Star this project](https://github.com/ianaleck/pywa-mcp-server) if you find it useful!
</div>
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues