WhatsApp Community Manager MCP
# WhatsApp Community Manager MCP
**Live MCP URL (Streamable HTTP):** `https://whatsapp-community-mcp.vercel.app/mcp`
Health check: `https://whatsapp-community-mcp.vercel.app/health`
Run your WhatsApp groups from any MCP client. It can list groups, read recent messages, summarise activity, draft posts, and post or schedule them.
It is **generic and bring-your-own-credentials**: every user connects **their own** [Green API](https://green-api.com) instance, and can optionally add their own WhatsApp Cloud API number. The server ships with no shared account.
> **Safety:** every tool that sends something (`post_message`, `schedule_post`, `run_due_posts`) returns a **preview only** unless it is called with `confirm: true`. The assistant should only set `confirm: true` after the user approves that exact text and destination. Message text read from groups is treated as untrusted data, never as instructions.
## Tools
| Tool | Purpose | Sends? |
|---|---|---|
| `connection_status` | Shows which providers are configured and the Green API instance state. Credentials are never shown | No |
| `list_groups` | Lists the groups you're in, with their chat ids | No |
| `group_info` | Group name, description, participant and admin count | No |
| `read_group_messages` | Last N messages, oldest first | No |
| `summarise_activity` | Message volume, top posters, busiest hours (in your timezone), keywords, questions that look unanswered, links shared | No |
| `draft_post` | Announcement, event, reminder, poll, welcome or rules post with WhatsApp formatting, built from your facts | No |
| `post_message` | Sends text, or a file/image from a URL with a caption | **Only with `confirm: true`** |
| `schedule_post` | Queues a post 1 min to 90 days ahead | **Only with `confirm: true`** |
| `list_scheduled_posts` / `cancel_scheduled_post` | Manage the queue | No |
| `run_due_posts` | Sends posts that are due. Call it from a cron | **Only with `confirm: true`** |
## Credentials (yours, never shared)
| Variable / HTTP header | Meaning |
|---|---|
| `GREEN_API_ID_INSTANCE` / `x-green-api-id-instance` | Your Green API idInstance |
| `GREEN_API_TOKEN_INSTANCE` / `x-green-api-token-instance` | Your apiTokenInstance |
| `GREEN_API_URL` / `x-green-api-url` | Your instance's apiUrl from the console, e.g. `https://7103.api.greenapi.com`. Default: `https://api.green-api.com`. Only Green API hosts are accepted |
| `WHATSAPP_CLOUD_TOKEN`, `WHATSAPP_PHONE_NUMBER_ID` (optional) | Meta WhatsApp Cloud API. It can send to individuals only: it can't read group history or post to these groups, and outside the 24 h window it needs approved templates |
On a hosted deployment, each user should send their own credentials as the HTTP headers above. Nothing is stored. Environment variables are a fallback for single-user or stdio setups. If you set them on a shared deployment, every caller acts as that account.
## Example prompts
- "List my WhatsApp groups."
- "Summarise the last 200 messages in Lagos Devs, Africa/Lagos time. Which questions went unanswered?"
- "Draft an event post for our meetup on Sat 18 Oct, 2pm at Yaba, then show me the preview."
- "Schedule that reminder for Friday 9am Lagos time." (The assistant previews it, you approve, then it schedules with confirm.)
## Run locally
```bash
npm install && npm run build
GREEN_API_ID_INSTANCE=... GREEN_API_TOKEN_INSTANCE=... GREEN_API_URL=https://XXXX.api.greenapi.com npm start # http://localhost:3000/mcp
npm run start:stdio
npm test # 14 mocked tests: no network, no sends
npm run smoke # HTTP smoke with credentials stripped: sends nothing
```
Claude Desktop config:
```json
{ "mcpServers": { "whatsapp-community": { "command": "node", "args": ["/path/dist/main-stdio.js"], "env": { "GREEN_API_ID_INSTANCE": "…", "GREEN_API_TOKEN_INSTANCE": "…", "GREEN_API_URL": "https://XXXX.api.greenapi.com" } } } }
```
## Deploy to Vercel
1. Import the repo. `api/mcp.ts` and `vercel.json` are already set up, and the endpoint is `/mcp`.
2. Don't set shared credentials. Users send theirs as headers.
3. **Scheduling on serverless:** the queue is a JSON file under `DATA_DIR`. The default is `~/.whatsapp-community-mcp`, or `/tmp` on Vercel, which does **not** persist. For production scheduling, run the server somewhere with a durable `DATA_DIR`, or swap `src/store.ts` for a KV store. Then trigger `run_due_posts` with `confirm: true` from a cron you control.
## Marketplace reviewer test
1. `npm install && npm run build && npm test`: 14 tests pass. All provider calls are mocked, and the tests show that no request is made without `confirm: true`.
2. `npm run smoke`: 6/6. Previews work, and tools that need credentials fail cleanly.
3. To test with your own number, start with `connection_status`, `list_groups` and then `post_message` **without** confirm. Check the preview, then post to a test group with `confirm: true`.
## Limitations
- Polls are drafted as numbered text, not native WhatsApp polls.
- The summary is statistical. The assistant writes the prose on top of it.
- Green API rate and plan limits apply; HTTP 466 is reported as a quota error.
MIT License © 2026 Segun Cole
## Storage and tenant isolation
- **Hosted:** data is kept in a private **Vercel Blob** store (free Hobby quota) when `BLOB_READ_WRITE_TOKEN` is set, at `<app>/<tenant>/<file>.json`, with ETag-based optimistic concurrency.
- **Tenant key:** a one-way SHA-256 hash of the caller's own credential headers, or of an `x-user-key` header if you send one (recommended if your token rotates). Secrets are never stored and tenants can't see each other's data. Callers with no credentials and no `x-user-key` share a `public-demo` space, so don't put real data there.
- **Local / self-hosted:** without a Blob token it falls back to JSON files under `DATA_DIR` (default `~/.whatsapp-community-mcp/<tenant>/`).
## Scheduled posts and cron
`vercel.json` registers a Vercel Cron job (`/api/cron`, daily at 07:00 UTC: Hobby allows cron jobs at most once a day). It needs a `CRON_SECRET` env var, which Vercel sends as `Authorization: Bearer …`, and it only sends due posts for the **operator's own** credentials set as env vars (a single-tenant, self-hosted deployment). On the shared hosted server no operator credentials are set, so the cron does nothing. Each user's client calls `run_due_posts` (with `confirm: true`) instead. For minute-level timing, upgrade to Pro cron, or call `run_due_posts` from your own scheduler.
TDQS
Scored across 11 tools
Each tool targets a distinct action/resource: raw reads (read_group_messages) vs. aggregation (summarise_activity), drafting (draft_post) vs. sending (post_message), and the scheduling lifecycle is cleanly split into schedule/list/cancel/run. The draft/schedule/run tools all describe their preview-without-confirm behavior consistently, so an agent can reliably pick the right one.
Almost all names follow a predictable verb_noun snake_case pattern (list_groups, read_group_messages, post_message, schedule_post, cancel_scheduled_post). A few are noun-only (connection_status, group_info), which is a minor deviation but still readable and unambiguous.
11 tools is well-scoped for a WhatsApp community manager: connection, group discovery, reading, summarising, drafting, sending, and a full scheduling sub-lifecycle. Every tool earns its place with no redundant entries.
The messaging and scheduling lifecycle is well covered (draft, send, schedule, list, cancel, run due), with read and summary operations for groups. However, group/community administration is absent: no tools to add/remove participants, promote/demote admins, or create/manage groups, which are notable gaps for a 'community manager' server.