{
  "markdown": "<div align=\"center\">\n\n<img src=\"assets/banner.png\" alt=\"guarded-whatsapp-mcp\" width=\"100%\">\n\n# guarded-whatsapp-mcp\n\n**Govern & automate WhatsApp safely for AI agents.**\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-22c55e.svg)](LICENSE)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776AB.svg?logo=python&logoColor=white)](pyproject.toml)\n[![MCP server](https://img.shields.io/badge/MCP-server-7c3aed.svg)](https://modelcontextprotocol.io)\n[![status: alpha](https://img.shields.io/badge/status-alpha-f59e0b.svg)](#roadmap)\n[![PRs welcome](https://img.shields.io/badge/PRs-welcome-22c55e.svg)](CONTRIBUTING.md)\n\n</div>\n\nAn [MCP](https://modelcontextprotocol.io) server that lets an AI agent (or any MCP client)\nsend WhatsApp messages and files — but only through a security gate you control: a\nrecipient **allowlist**, **secret scanning**, **file validation**, **rate limiting**, a\n**confirmation gate**, and an append-only **audit log**.\n\nMost WhatsApp bridges send anything, anywhere, with no record. That is fine for a human\nclicking *send*. It is not fine for an autonomous agent. **guarded-whatsapp-mcp is the\ngovernance layer** that makes agent-driven WhatsApp safe enough to trust.\n\n> **This is not a Slack replacement.** No channels, no threads, no workspace UI. It makes\n> the WhatsApp you *already use* safe to automate.\n\n## See it in action\n\n<div align=\"center\">\n<img src=\"assets/demo.gif\" alt=\"Good sends go through, bad sends are blocked, all of it logged\" width=\"92%\">\n<br><sub>Good sends go through · a leaked key and an un-allowlisted number are blocked · files need a preview · everything is logged.</sub>\n</div>\n\n## How it works\n\n<div align=\"center\">\n<img src=\"assets/architecture.png\" alt=\"Architecture: every send passes through the guard\" width=\"92%\">\n</div>\n\n---\n\n## ⚠️ Read this first — unofficial transport & WhatsApp Terms\n\nThis server governs access to a transport; by default that transport is the **unofficial\n[whatsmeow](https://github.com/tulir/whatsmeow)-based bridge** (e.g.\n[`whatsapp-mcp`](https://github.com/lharries/whatsapp-mcp)), which speaks WhatsApp Web's\nprivate protocol.\n\n- An unofficial client **violates WhatsApp's Terms of Service** and **can get a number\n  banned**. A reverse-engineered client cannot avoid this.\n- **Use a secondary / non-critical number.** Never your primary or business-critical one.\n- **Not for production customer messaging** — use the official\n  [WhatsApp Business Cloud API](https://developers.facebook.com/docs/whatsapp). An official\n  Cloud-API backend is on the [roadmap](#roadmap); the guard layer is built to front either\n  transport.\n\nThe guardrails here reduce **operational** risk (wrong recipient, leaked secret, spam).\nThey do **not** change the **Terms-of-Service** risk of the underlying bridge. We are loud\nabout this on purpose so you can choose with eyes open.\n\n---\n\n## Why teams use it\n\n| Without a guard | With guarded-whatsapp-mcp |\n|---|---|\n| Agent can message *any* number it generates | Fail-closed **allowlist** — strangers are refused |\n| A leaked API key sails out in a message | **Secret scan** blocks it before it sends |\n| A runaway loop spams the team 200× | **Rate limit** caps it |\n| Files arrive as `Untitled`; paths unchecked | **ASCII-safe filenames** + type/size checks |\n| No idea what the agent sent | Append-only **audit log** of every attempt |\n| Accidental sends | **Confirmation gate** — risky sends must be previewed |\n\n## Security controls\n\n| Control | What it does |\n|---|---|\n| **Recipient allowlist** | Fail-closed. With `allow_unlisted: false`, only people/groups in your config can be messaged — even a raw number is refused. |\n| **Secret / PII scan** | Text + captions scanned for API keys, private keys, cloud/Slack/GitHub/OpenAI tokens, JWTs, credit cards (Luhn), national IDs. `block` or `warn`. |\n| **File validation** | Extension allowlist + size cap. Filenames sanitized to ASCII (no `Untitled`, no path traversal); copied to a safe name before sending. |\n| **Rate limiting** | Sliding window (per-minute + per-hour) stops runaway loops. |\n| **Confirmation gate** | Risky sends (unlisted / files / all) need a `confirm_token` from `wa_preview` — proof the send was previewed, not accidental. |\n| **Audit log** | Every attempt (sent / blocked / failed) appended to `~/.guarded-whatsapp-mcp/audit.jsonl`, with body stored as preview + hash only. |\n\n## Tools\n\n| Tool | Gated? | Purpose |\n|---|---|---|\n| `wa_list_recipients` | read-only | Show the allowlist (numbers masked). |\n| `wa_preview` | read-only | Dry-run a send: run every check, return a verdict + `confirm_token` if needed. Sends nothing. |\n| `wa_send_message` | **send** | Send text to an allowlisted recipient through the full gate. |\n| `wa_send_file` | **send** | Send a file (auto ASCII-safe name, type/size checked, caption scanned). |\n| `wa_audit_tail` | read-only | Recent audit records. |\n\n## Quickstart\n\n```bash\ngit clone https://github.com/peter-tnc-453/guarded-whatsapp-mcp\ncd guarded-whatsapp-mcp\n\nuv venv --python 3.11 && source .venv/bin/activate   # Python 3.10+\nuv pip install -e .\n\ncp config/allowlist.example.yaml config/allowlist.yaml   # edit your allowlist (git-ignored)\n\n# a WhatsApp bridge exposing POST /api/send must be running (the authenticated session).\n# whatsmeow bridge: https://github.com/lharries/whatsapp-mcp  (first run = QR scan)\n\npython -m wa_guard          # run the MCP server (stdio)\n```\n\n### Register with Claude Code / any MCP client\n\n```json\n{\n  \"mcpServers\": {\n    \"guarded-whatsapp-mcp\": {\n      \"command\": \"/ABSOLUTE/PATH/guarded-whatsapp-mcp/.venv/bin/python\",\n      \"args\": [\"-m\", \"wa_guard\"],\n      \"env\": {\n        \"PYTHONPATH\": \"/ABSOLUTE/PATH/guarded-whatsapp-mcp/src\",\n        \"WA_GUARD_CONFIG\": \"/ABSOLUTE/PATH/guarded-whatsapp-mcp/config/allowlist.yaml\"\n      }\n    }\n  }\n}\n```\n\n## Example — a safe agent flow\n\n```jsonc\n// 1) The agent previews first (read-only, sends nothing)\nwa_preview(recipient=\"Alex\", file_path=\"report.pdf\")\n// → { ok:false, needs_confirm:true, confirm_token:\"a1b2c3d4e5\",\n//     display_filename:\"report.pdf\", recipient:{ name:\"Alex\", allowlisted:true } }\n\n// 2) It sends, passing the token back to prove the preview happened\nwa_send_file(recipient=\"Alex\", file_path=\"report.pdf\", confirm_token=\"a1b2c3d4e5\")\n// → { sent:true, ... }   (and one line is appended to the audit log)\n\n// A blocked attempt is explicit and recorded:\nwa_send_message(recipient=\"+66999999999\", message=\"hi\")\n// → { sent:false, blocked_reason:\"recipient is not allowlisted and allow_unlisted=false\" }\n```\n\n## Configuration\n\nSee [`config/allowlist.example.yaml`](config/allowlist.example.yaml). Key knobs:\n`allow_unlisted` (the fail-closed switch), `require_confirm_for`, `rate_limit`, `files`,\n`secrets.on_detect`, and the `recipients` allowlist. Edits hot-reload on each call.\n\n## Roadmap\n\n- **Pluggable backend** — same guard layer in front of the unofficial bridge *or* the\n  official **WhatsApp Business Cloud API** (compliant path).\n- **Inbound routing** — surface incoming messages to agents (read · classify · route).\n- **Scheduled / templated sends** through the same gate.\n- **Per-recipient policy** (rate limits / confirm rules per contact or group).\n\n## Tests\n\n```bash\nuv pip install pytest && PYTHONPATH=src python -m pytest -q   # 19 passing\n```\n\n## Contributing\n\nPRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). The one rule: **keep the fail-closed\nposture**, and add a test for every new check.\n\n## License\n\nMIT — see [LICENSE](LICENSE). Security model & honest limitations in [SECURITY.md](SECURITY.md).\n\n<!-- mcp-name: io.github.peter-tnc-453/guarded-whatsapp-mcp -->\n\n",
  "bytes": 7658,
  "sha": "0a5ea7e7e9040115b3ff9bcc99a7b3ba6ffa5df757e0d0eaa8ab69ab666c6230",
  "repo_slug": "peter-tnc-453/guarded-whatsapp-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_peter_tnc_453_guarded_whatsapp_ad15d5c8/readme"
}