wacrm/mcp-server/README.md
Arnas Donauskas 78f2f79d3b Add MCP server for the public API
Introduce mcp-server/ — a stdio Model Context Protocol server that
wraps the /api/v1 public API so MCP clients (Claude, Cursor, etc.) can
drive a self-hosted wacrm instance in natural language.

- Thin wrapper over the existing REST API; all auth, scoping, and rate
  limiting stay server-side. No new backend surface.
- Read-only by default: write and broadcast tools are only registered
  when WACRM_ENABLE_WRITES / WACRM_ENABLE_BROADCASTS are set, layered
  on top of the API key's own scopes. send_broadcast also requires an
  explicit confirm and is marked destructive.
- Registry-ready: server.json manifest, package.json mcpName linked to
  it (io.github.arnasdon/wacrm-mcp), and glama.json for discovery.
- Docs: docs/mcp.md + README bullet + mcp-server/README.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 17:30:24 +03:00

115 lines
4.8 KiB
Markdown

# wacrm MCP server
A [Model Context Protocol](https://modelcontextprotocol.io) server for
**[wacrm](https://github.com/ArnasDon/wacrm)** — the self-hostable
WhatsApp CRM. It lets MCP clients (Claude Desktop, Claude Code, Cursor,
and others) drive your CRM in natural language:
> "How many conversations are still open?"
> "Find the contact for +1 415 555 0123 and show the last few messages."
> "Draft and send an order-update template to Jane."
It's a thin wrapper over wacrm's public [`/api/v1`](../docs/public-api.md)
REST API. All auth, scoping, and rate limiting are enforced by your
wacrm instance — this server just exposes the API as MCP tools.
## Prerequisites
1. A running wacrm instance (your own self-hosted deploy).
2. An API key: in the dashboard go to **Settings → API keys → New API
key** and grant only the scopes you need. The key is shown once.
## Install & configure
The server reads two required environment variables and two optional
write guards:
| Variable | Required | Purpose |
| ------------------------- | -------- | -------------------------------------------------------------- |
| `WACRM_BASE_URL` | yes | Your instance URL, e.g. `https://crm.example.com` |
| `WACRM_API_KEY` | yes | An API key from the dashboard |
| `WACRM_ENABLE_WRITES` | no | `true` to expose contact writes + message sending |
| `WACRM_ENABLE_BROADCASTS` | no | `true` to expose mass broadcasts (needs `WACRM_ENABLE_WRITES`) |
### Claude Desktop / Claude Code / Cursor
Add to your MCP client config (e.g. `claude_desktop_config.json`, or
`.mcp.json` for Claude Code):
```jsonc
{
"mcpServers": {
"wacrm": {
"command": "npx",
"args": ["-y", "wacrm-mcp"],
"env": {
"WACRM_BASE_URL": "https://crm.example.com",
"WACRM_API_KEY": "wacrm_live_xxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
```
That configuration is **read-only** — the safe default. To let the
assistant change data or send messages, add the write guards:
```jsonc
"env": {
"WACRM_BASE_URL": "https://crm.example.com",
"WACRM_API_KEY": "wacrm_live_xxxxxxxxxxxxxxxxxxxxxxxx",
"WACRM_ENABLE_WRITES": "true",
"WACRM_ENABLE_BROADCASTS": "true"
}
```
## Tools
Read tools are always available. Write and broadcast tools appear only
when their guard is set.
| Tool | Group | Scope needed | What it does |
| -------------------- | --------- | -------------------- | ----------------------------------------------- |
| `whoami` | read | _(any valid key)_ | Show the account + scopes the key carries |
| `list_contacts` | read | `contacts:read` | List/search contacts (paginated) |
| `get_contact` | read | `contacts:read` | Read one contact |
| `list_conversations` | read | `conversations:read` | List conversations, filter by status/contact |
| `get_conversation` | read | `conversations:read` | Read one conversation |
| `list_messages` | read | `messages:read` | List a conversation's messages |
| `get_broadcast` | read | `broadcasts:send` | Poll a broadcast's delivery status |
| `send_message` | write | `messages:send` | Send a WhatsApp message (text/template/media) |
| `create_contact` | write | `contacts:write` | Create (find-or-create) a contact |
| `update_contact` | write | `contacts:write` | Update a contact / replace its tags |
| `send_broadcast` | broadcast | `broadcasts:send` | Launch a template broadcast (requires `confirm`)|
## Safety model
Sending WhatsApp messages through an LLM is a real-world side effect, so
the server layers three guards:
1. **Read-only by default.** Write and broadcast tools are not even
registered — the model can't see them — unless you opt in via
`WACRM_ENABLE_WRITES` / `WACRM_ENABLE_BROADCASTS`.
2. **API-key scopes.** Whatever the guards allow, your wacrm instance
still enforces the key's scopes. A call without the right scope
returns a clean `forbidden` error. Issue a read-only key for a
read-only assistant.
3. **Explicit broadcast confirmation.** `send_broadcast` refuses to run
unless called with `confirm: true`, and is marked `destructive` so
compliant clients prompt the user first.
## Development
```bash
npm install
npm run build # compile to dist/
npm run typecheck
npm start # run the compiled server (needs the env vars)
```
Logs go to **stderr** — stdout is reserved for the MCP protocol.
## License
MIT — same as wacrm.