trackmcp
Back to directory
codeChap

mcp-server-stalwart

View on GitHub

MCP server for Stalwart mail server via JMAP

0 stars RustOthers Updated Aug 26, 2026

Documentation

mcp-server-stalwart

MCP server for Stalwart Mail Server. Provides email operations (search, read, send, delete) via JMAP and optional admin API access for server management.

Requirements

  • Rust (2024 edition)
  • A Stalwart mail server with JMAP enabled

Build

bash
cargo build --release

Binary is output to `target/release/mcp-server-stalwart`.

Configuration

The server connects via stdio and is configured through environment variables.

Required

VariableDescription
`JMAP_SESSION_URL`JMAP session endpoint (e.g. `https://mail.example.com/jmap/session`)
`JMAP_USERNAME`JMAP account email address
`JMAP_PASSWORD`JMAP account password

Optional (other mailboxes)

Switch tools onto another mailbox with `account` (e.g. `hello@codechap.com`) without needing the admin API.

VariableDescription
`JMAP_SECRETS_FILE`Path to a mailman4 `secrets.toml` (`[passwords]` table of `"email" = "password"`)
`JMAP_ACCOUNTS`Inline `email=password;other@host=password` list (overrides file on clash)

Optional (admin API)

VariableDescription
`STALWART_ADMIN_URL`Admin API base URL — `https://mail.example.com` or `https://mail.example.com/api` (both accepted; `/api` is normalized)
`STALWART_ADMIN_USER`Admin username (default: `admin`)
`STALWART_ADMIN_PASSWORD`Admin password (different principal from mailbox passwords)

Password gotcha (learned the hard way)

SecretUsed forNOT used for
`JMAP_PASSWORD` / mailbox passwordSMTP submission (`smtp://user:pass@host:587`), JMAP, IMAP for that accountAdmin API
`STALWART_ADMIN_PASSWORD`Admin API (`/api/principal`, `/api/logs`, …)App mailer DSNs

If an app (invoice mailer, WordPress, etc.) is configured with the admin password as the SMTP secret, Stalwart returns `535 Authentication credentials invalid` and nothing is queued. `check_sent` will correctly show zero submissions. Use `verify_account_auth` to test credentials before chasing delivery.

Claude Code MCP config

json
{
  "mcpServers": {
    "stalwart": {
      "command": "/path/to/mcp-server-stalwart",
      "env": {
        "JMAP_SESSION_URL": "https://mail.example.com/jmap/session",
        "JMAP_USERNAME": "you@example.com",
        "JMAP_PASSWORD": "your-password",
        "JMAP_SECRETS_FILE": "/home/you/.local/share/mailman4/secrets.toml",
        "STALWART_ADMIN_URL": "https://mail.example.com",
        "STALWART_ADMIN_PASSWORD": "admin-password"
      }
    }
  }
}

Tools

get_mailboxes

List all mailboxes/folders with message counts.

ParameterTypeRequiredDescription
`account`stringnoMailbox to list (e.g. `hello@codechap.com`)

create_mailbox

Create a new mailbox/folder.

ParameterTypeRequiredDescription
`name`stringyesMailbox name
`parent_id`stringnoParent mailbox ID for nesting (top-level if omitted)
`role`stringnoStandard role: `archive`, `drafts`, `inbox`, `junk`, `sent`, `trash`

search_emails

Search emails with filters. Returns email IDs -- use `get_emails` to read full content.

ParameterTypeRequiredDescription
`query`stringnoText to search across subject, body, from, to
`from`stringnoFilter by sender address
`to`stringnoFilter by recipient address
`subject`stringnoFilter by subject text
`mailbox_id`stringnoRestrict to a specific mailbox
`position`numbernoPagination offset (default 0)
`limit`numbernoMax results (default 10, max 50)
`account`stringnoMailbox to search (e.g. `hello@codechap.com`)

get_emails

Get full email content by IDs. Returns subject, from, to, date, body text, and metadata.

ParameterTypeRequiredDescription
`ids`string[]yesList of email IDs to retrieve
`account`stringnoMailbox that owns these emails

delete_emails

Permanently delete emails by ID. Cannot be undone.

ParameterTypeRequiredDescription
`ids`string[]yesList of email IDs to delete
`account`stringnoMailbox to delete from

send_email

Send an email with optional HTML body and file attachments. When `html_body` is provided, the email is sent as multipart with both plain text and HTML parts -- the recipient's email client will choose which to display.

ParameterTypeRequiredDescription
`to`string[]yesRecipient email addresses
`subject`stringyesEmail subject
`body`stringyesPlain text body
`html_body`stringnoHTML body. When provided, email is sent as multipart (text/plain + text/html)
`cc`string[]noCC recipients
`bcc`string[]noBCC recipients
`attachments`object[]noFile attachments (see below)
`account`stringnoSend as this mailbox (e.g. `hello@codechap.com`) instead of the default JMAP user

Attachment object:

FieldTypeRequiredDescription
`path`stringyesAbsolute path to the file on disk
`filename`stringyesFilename for the attachment
`content_type`stringnoMIME type (auto-detected from extension if omitted)

download_attachments

Download all attachments from an email to a local directory.

ParameterTypeRequiredDescription
`email_id`stringyesEmail ID to download attachments from
`download_dir`stringyesDirectory path to save attachments to

create_account (admin)

Create a new email account on the server. Requires admin API configuration.

ParameterTypeRequiredDescription
`email`stringyesPrimary email address
`password`stringyesAccount password
`description`stringnoDisplay name
`quota`numbernoDisk quota in bytes (0 for unlimited)
`permissions`string[]noPermissions to grant at creation (e.g. `email-send`, `authenticate`, `imap-authenticate`). Without permissions, the account cannot authenticate or submit mail — either supply them here or call `update_account_permissions` afterwards.

list_accounts (admin)

List all accounts, or get details for one. Requires admin API configuration.

ParameterTypeRequiredDescription
`name`stringnoAccount name for details. If omitted, lists all accounts.

manage_aliases (admin)

Add or remove an email alias on an account. Requires admin API configuration.

ParameterTypeRequiredDescription
`account`stringyesAccount name
`action`stringyes`add` or `remove`
`alias`stringyesAlias email to add/remove

update_account_permissions (admin)

Update an account's `enabledPermissions`. Newly-created principals start with no permissions and cannot authenticate, send, or receive mail until permissions are granted. Requires admin API configuration.

ParameterTypeRequiredDescription
`account`stringyesTarget account name
`action`stringno`set` (replace list, default), `add` (grant), or `remove` (revoke)
`permissions`string[]yesPermission names (e.g. `email-send`, `authenticate`, `imap-authenticate`, `imap-append`)

reset_password (admin)

Reset an account's password. If `password` is omitted, a strong 24-character random password is generated. The new password is returned in plaintext in the response so it can be delivered to the user. Requires admin API configuration.

ParameterTypeRequiredDescription
`account`stringyesTarget account name
`password`stringnoNew password. Auto-generated if omitted.

get_dsn_accounts (admin)

List email addresses that have DSN (Delivery Status Notification) delivery reports enabled. Requires admin API configuration.

set_dsn_accounts (admin)

Set which email addresses receive DSN delivery reports (SUCCESS + FAILURE). Replaces the full list. Requires admin API configuration.

ParameterTypeRequiredDescription
`accounts`string[]yesEmail addresses to enable delivery reports for

check_sent (admin)

The first tool to reach for when verifying any outbound email — contact forms, WordPress `wp_mail()`, invoice/statement mailers, password resets, transactional mail — anything needing *"did this leave the server?"*.

Reads Stalwart's `/api/logs` (authoritative) and groups by `queueId`: submission → delivery attempt → final status (`delivery.delivered` / `delivery.dsn-success` / `delivery.failed`) plus upstream MX `code`/`hostname`.

Do NOT search mailboxes first — SMTP submissions are not auto-saved to Sent. Start here.

How the log fetch works (production lesson):

Stalwart's server-side `filter=` query often hangs on multi-GB daily log files. By default this tool fetches the newest `scan_limit` rows unfiltered and applies `to`/`from`/`filter` client-side (fast: ~300ms for 1000 rows). Pass `use_server_filter=true` only if you know you need it (e.g. a unique queueId on a quiet host).

Common use cases:

  • "Did the invoice mailer / contact form send to `ap@client.com`?"
  • "Was a transactional email delivered — what did Gmail return?"
  • "Why bounce — remote SMTP code?"
ParameterTypeRequiredDescription
`to`stringnoRecipient email or domain (client-side substring). Prefer this for contact-form checks.
`from`stringnoSender email or domain (client-side substring).
`filter`stringnoExtra client-side substring (e.g. queueId).
`since`stringnoRFC3339 lower bound on event timestamps.
`scan_limit`numbernoNewest log rows to fetch (default 500, max 5000). Raise if the send is older than the window.
`use_server_filter`boolnoDefault `false`. If `true`, pass filter to Stalwart (can timeout on busy hosts).

Returns `messages_found`, `delivered_count`, `failed_count`, per-message timelines (`mx_code` / `mx_hostname`), plus `auth_events` (submission auth success/failure) and a `log_window`.

verify_account_auth

Test whether a username/password is accepted by Stalwart (same secret as SMTP port 587). Use when `check_sent` shows no submission — usually the app has the wrong password.

ParameterTypeRequiredDescription
`username`stringyesAccount email (e.g. `hello@codechap.com`)
`password`stringyesCandidate password (mailbox secret, not admin)

Frequently asked questions

What is mcp-server-stalwart?

mcp-server-stalwart is MCP server for Stalwart mail server via JMAP

How do I install mcp-server-stalwart?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is mcp-server-stalwart open source?

Yes — it is hosted on GitHub at https://github.com/codeChap/mcp-server-stalwart.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP