Skip to main content
Glama
WhatsApp MCP Server

WhatsApp MCP Server

README.md
# WhatsApp MCP Server

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![MCP Spec](https://img.shields.io/badge/MCP-2024--11--05-brightgreen.svg)](https://modelcontextprotocol.io/)

A native **Model Context Protocol (MCP)** server for WhatsApp on macOS.

This server bridges local WhatsApp Catalyst SQLite storage (`ChatStorage.sqlite`) with native OS messaging, enabling AI agents to read conversations, search message history, inspect media attachments, and send/draft messages with hardware-enforced biometric authorization (Apple Touch ID / Windows Hello).

---

## Key Features

- **Read-Only SQLite Storage Parsing**: Connects directly to WhatsApp's sandboxed CoreData SQLite database using URI mode (`file:...?mode=ro`) with read-only pragmas and automatic WAL lock snapshot fallback. Never locks or alters the desktop client database.
- **Hardware-Enforced Biometrics**: All message sending operations are gated by native OS biometric prompts (macOS Touch ID / Windows Hello) with interactive recipient and text preview before dispatch.
- **Flexible Message Dispatch**:
  - `auto`: Focuses WhatsApp, stages the message, and automatically dispatches via native AppleScript Return keystroke.
  - `draft`: Opens the chat and stages the message text in the input box for manual human review and dispatch.
- **Rich Media & Context Resolution**: Inspects images, documents, PDFs, voice notes, and contact cards, resolving local filesystem paths and disk presence.
- **Cross-Version CoreData Schema Adaptation**: Automatically inspects table metadata at runtime to adapt across macOS Catalyst updates.

---

## Architectural Overview

```
                      ┌────────────────────────────────┐
                      │    AI Agent / MCP Client       │
                      │  (Claude, Cursor, Antigravity) │
                      └───────────────┬────────────────┘
                                      │ stdio (JSON-RPC)
                                      ▼
                      ┌────────────────────────────────┐
                      │      WhatsApp MCP Server       │
                      └───────┬────────────────┬───────┘
                              │                │
            [Read-Only Layer] │                │ [Write Layer]
      (Zero-Friction SQLite)  │                │ (Biometric Guard)
                              ▼                ▼
            ┌───────────────────┐    ┌───────────────────┐
            │ ChatStorage.sqlite│    │ Native Biometrics │
            │ (mode=ro + WAL    │    │ (Touch ID / Hello)│
            │  snapshot safe)   │    └─────────┬─────────┘
            └───────────────────┘              │
                                               ▼
                                     ┌───────────────────┐
                                     │   WhatsApp.app    │
                                     │ (URL Scheme + UI) │
                                     └───────────────────┘
```

---

## Prerequisites & Permissions

### 1. macOS Full Disk Access (FDA)
WhatsApp for macOS stores its SQLite database inside a sandboxed Group Container:
`~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqlite`

To allow the MCP server (or your terminal / IDE) to read the database:
1. Open **System Settings** -> **Privacy & Security** -> **Full Disk Access**.
2. Click the `+` button.
3. Add your terminal application (e.g., Terminal, iTerm2, Ghostty) or your MCP client host (e.g., Cursor, VS Code, Antigravity) or Python executable.
4. Restart your terminal / IDE.

To verify access at any time, run:
```bash
whatsapp-mcp --status
```

---

## Installation

### Using `uv` (Recommended)
```bash
# Clone the repository
git clone https://github.com/hemelbesem90s/WhatsApp-MCP.git
cd WhatsApp-MCP

# Create environment and install
uv venv .venv --python 3.13
source .venv/bin/activate
uv pip install -e ".[dev]"
```

### Using standard pip
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

---

## Configuration

Settings can be specified in a `.env` file or passed as environment variables:

| Variable | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `WHATSAPP_MCP_DB_PATH` | Path | `~/Library/Group Containers/.../ChatStorage.sqlite` | Path to WhatsApp SQLite database |
| `WHATSAPP_MCP_MEDIA_PATH` | Path | `~/Library/Group Containers/.../Message/Media` | Path to WhatsApp media directory |
| `WHATSAPP_MCP_ENABLE_WRITE_TOOLS` | bool | `true` | Enable write tools (`send_message`, `draft_message`) |
| `WHATSAPP_MCP_REQUIRE_BIOMETRIC` | bool | `true` | Require Touch ID / Windows Hello for write actions |
| `WHATSAPP_MCP_SEND_MODE` | str | `auto` | Message dispatch mode (`auto` or `draft`) |
| `WHATSAPP_MCP_LOG_LEVEL` | str | `INFO` | Logging level (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |

---

## MCP Tool Reference

### Read Tools (Zero Friction, Read-Only)

| Tool Name | Parameters | Description |
| :--- | :--- | :--- |
| `check_connection_status` | *(none)* | Tests WhatsApp installation, database readability, and Full Disk Access status with summary stats. |
| `list_chats` | `search`, `include_archived`, `unread_only`, `limit`, `offset` | Lists recent 1:1 and group chats with unread counts and message previews. |
| `get_chat` | `chat_id` *(required)* | Retrieves full chat metadata, group membership roster, and media breakdown. |
| `list_messages` | `chat_id`, `since`, `until`, `sender`, `media_type`, `search`, `limit`, `offset`, `order` | Lists messages across chats or within a chat with rich timestamp/media filtering. |
| `search_messages` | `query` *(required)*, `chat_id`, `limit`, `offset` | Full-text substring search across message history. |
| `search_contacts` | `query` *(required)*, `limit` | Searches contacts by name, push name, phone number, or JID. |
| `get_message_context` | `message_id` *(required)*, `before`, `after` | Retrieves chronological conversation context surrounding a message ID. |
| `list_media` | `chat_id`, `media_type`, `limit`, `offset` | Lists media attachments with local file disk verification. |
| `get_media_path` | `media_id`, `message_id` | Resolves absolute filesystem path, disk presence, size, and MIME type. |

### Write Tools (Biometric-Gated)

| Tool Name | Parameters | Description |
| :--- | :--- | :--- |
| `send_message` | `recipient` *(required)*, `text` *(required)*, `confirm=true` *(required)* | Sends a message to a phone number or JID via native desktop WhatsApp. Gated by Touch ID. |
| `draft_message` | `recipient` *(required)*, `text` *(required)*, `confirm=true` *(required)* | Stages a message draft in WhatsApp for manual human review without sending. Gated by Touch ID. |

---

## Client Integration Examples

### Claude Desktop (`claude_desktop_config.json`)
```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "/path/to/whatsapp-mcp/.venv/bin/whatsapp-mcp",
      "args": [],
      "env": {
        "WHATSAPP_MCP_ENABLE_WRITE_TOOLS": "true",
        "WHATSAPP_MCP_REQUIRE_BIOMETRIC": "true",
        "WHATSAPP_MCP_SEND_MODE": "auto"
      }
    }
  }
}
```

### Antigravity / Gemini CLI (`mcp_config.json`)
```json
{
  "mcpServers": {
    "whatsapp": {
      "command": "/path/to/whatsapp-mcp/.venv/bin/whatsapp-mcp",
      "args": [],
      "env": {
        "WHATSAPP_MCP_ENABLE_WRITE_TOOLS": "true",
        "WHATSAPP_MCP_REQUIRE_BIOMETRIC": "true",
        "WHATSAPP_MCP_SEND_MODE": "auto"
      }
    }
  }
}
```

---

## Development & Testing

```bash
# Run unit test suite with coverage
make test

# Run linter
make lint

# Run type checker
make typecheck

# Full test and verification suite
make check
```

---

## License

MIT License. See [LICENSE](LICENSE) for details.