stalwart-jmap-mcp
# stalwart-jmap-mcp
Unofficial [MCP](https://modelcontextprotocol.io) server for [Stalwart Mail Server](https://stalw.art) — talks to the **JMAP management API** (`/jmap`, Stalwart v1.0+).
> ⚠️ Stalwart 0.16+ removed the legacy REST management API in favor of JMAP. Most existing "stalwart MCP" projects target the old REST API and won't work on modern Stalwart. This server uses the `x:`-prefixed JMAP management methods directly.
## Features (v0.4 — 39 tools, verified live on Stalwart v1.0.0)
### Mail surface (v0.4 — standard JMAP mail)
| Tool | Description |
|------|-------------|
| `stalwart_list_mailboxes` | Folders + email counts (inbox/trash/junk/sent/...) |
| `stalwart_search_emails` | Search by mailbox role + free text (from/to/subject/body) |
| `stalwart_get_email` | Full email: headers, body, raw blob |
| `stalwart_list_identities` | Sending identities (From addresses) |
| `stalwart_get_vacation_response` | Auto-reply settings |
| `stalwart_list_sieve_scripts` | Sieve filter scripts |
> ⚠️ Admin token punya permission `impersonate` — parameter `account_id` bisa dipakai untuk membaca mailbox user lain. Gunakan dengan hati-hati.
### Read (v0.1)
| Tool | Description |
|------|-------------|
| `stalwart_server_info` | Edition, username, capabilities |
| `stalwart_list_accounts` | Mail accounts (users) with email/domain/created |
| `stalwart_get_account` | Full account detail by id or email (secrets masked) |
| `stalwart_list_domains` | Configured mail domains |
| `stalwart_list_principals` | Users/groups/lists/domains/roles/tenants |
| `stalwart_list_dkim_signatures` | DKIM keys: selector, stage, algorithm |
| `stalwart_list_queue` | Outgoing mail queue |
| `stalwart_list_api_keys` | API keys (masked) |
| `stalwart_list_objects` | Generic listing: tasks, alerts, roles, mailing lists, tenants, certificates, cluster nodes, applications, webhooks, tracers, ACME providers, DNS servers, spam rules, blocked/allowed IPs |
### Write (v0.2)
| Tool | Description |
|------|-------------|
| `stalwart_create_account` | Create mail account (user) |
| `stalwart_delete_account` | Delete account (requires confirm) |
| `stalwart_set_account_password` | Reset account password |
| `stalwart_create_domain` | Add mail domain |
| `stalwart_delete_domain` | Delete domain (requires confirm) |
| `stalwart_generate_dkim` | Generate DKIM key (RSA 2048 / Ed25519) |
| `stalwart_create_api_key` | Create API key (token shown once) |
| `stalwart_delete_api_key` | Delete API key (requires confirm) |
| `stalwart_reschedule_queue_message` | Set next retry time of a queued message |
| `stalwart_delete_queue_message` | Delete message from queue (requires confirm) |
| `stalwart_block_ip` / `stalwart_unblock_ip` | Block / unblock IP (reason enum: rcptToFailure, authFailure, loitering, portScanning, manual, other) |
| `stalwart_allow_ip` / `stalwart_unallow_ip` | Allowlist / remove IP from allowlist |
| `stalwart_create_mailing_list` | Create mailing list (name + domain) |
| `stalwart_delete_mailing_list` | Delete mailing list (requires confirm) |
### Admin (v0.3)
| Tool | Description |
|------|-------------|
| `stalwart_reload_settings` | Hot-reload server settings |
| `stalwart_reload_tls_certificates` | Reload TLS certificates |
| `stalwart_queue_pause` / `stalwart_queue_resume` | Pause/resume MTA queue |
| `stalwart_invalidate_caches` | Invalidate (all|negative) caches |
| `stalwart_troubleshoot_dmarc` | Live SPF/DKIM/ARC/DMARC troubleshoot |
| `stalwart_classify_spam` | Spam score + tags for a message |
## Install
```bash
# local development
git clone https://github.com/fredogemilang/stalwart-jmap-mcp
cd stalwart-jmap-mcp && uv sync
# or via uvx (PEP 503 index hosted on GitHub Pages)
uvx --extra-index-url https://<user>.github.io/stalwart-jmap-mcp/simple stalwart-jmap-mcp
```
## Configure
```bash
export STALWART_URL=https://mail.example.com
export STALWART_TOKEN=API_xxxx
```
Get an API token from the Stalwart web admin (`mail.example.com/login`) → API keys.
## Claude Code
### Option A — uvx (install langsung dari GitHub Pages index)
Tambah ke `.mcp.json` di project root (atau `claude mcp add`):
```json
{
"mcpServers": {
"stalwart": {
"command": "uvx",
"args": ["--refresh", "--extra-index-url", "https://fredogemilang.github.io/stalwart-jmap-mcp/simple", "stalwart-jmap-mcp"],
"env": {
"STALWART_URL": "https://mail.example.com",
"STALWART_TOKEN": "your-api-key"
}
}
}
}
```
### Option B — local development
```bash
claude mcp add stalwart --env STALWART_URL=https://mail.example.com \
--env STALWART_TOKEN=API_xxxx -- uv --directory /path/to/stalwart-jmap-mcp \
run stalwart-jmap-mcp
```
## Development
```bash
uv run python scripts/smoke_test.py # end-to-end test via stdio
```
## License
MIT
TDQS
Scored across 39 tools
Most tools target distinct resources (accounts, domains, queue, IPs, emails), but list_accounts and list_principals overlap since accounts are principals of type 'individual', and list_objects can list many types already covered by dedicated list tools. Descriptions mostly clarify, but the duplication creates minor ambiguity.
All tools use the stalwart_ prefix and mostly follow verb_noun naming (list_accounts, create_domain, delete_queue_message). Exceptions like server_info (noun-only) and queue_pause/queue_resume (noun-verb instead of verb-noun) break the uniform pattern, but the overall style is still predictable.
With 39 tools, this server is excessively large for an MCP interface. Even for a broad mail server admin domain, the sheer number of tools makes selection harder and suggests over-fragmentation, exceeding the 25+ threshold for 'too many'.
The tool set covers many admin operations (accounts, domains, queue, IP blocks, mailing lists) but only provides read-only access to identities, vacation responses, and Sieve scripts—no create/update/delete for these. This leaves notable gaps for full lifecycle management.