MCP server for Migadu email hosting — manage domains, mailboxes, aliases, identities, forwardings, and rewrites.
Project description
Migadu MCP Server
Control your Migadu email hosting from AI assistants via the Model Context Protocol.
What is Migadu?
Migadu is a Swiss email host that prices on actual usage instead of mailbox count, with standard SMTP/IMAP/POP3 and no lock-in.
What this does
Covers the full Migadu API surface as MCP tools:
- Domains — create, update, activate, DNS records, diagnostics, usage
- Mailboxes — CRUD, autoresponders, password resets
- Aliases — forwarding rules without a mailbox behind them
- Identities — send-as addresses on a mailbox
- Forwardings — external delivery copies with confirmation flow
- Rewrites — pattern-based routing rules
Setup
Get an API key at Migadu Admin → My Account → API Keys.
Add to your MCP client config (e.g. Claude Desktop, ~/.claude.json, etc.):
{
"mcpServers": {
"migadu": {
"command": "uvx",
"args": ["migadu-mcp"],
"env": {
"MIGADU_EMAIL": "you@example.com",
"MIGADU_API_KEY": "your-api-key",
"MIGADU_DOMAIN": "example.com"
}
}
}
}
Or via the Claude Code CLI:
claude mcp add migadu \
--env MIGADU_EMAIL=you@example.com \
--env MIGADU_API_KEY=your-api-key \
--env MIGADU_DOMAIN=example.com \
-- uvx migadu-mcp
MIGADU_DOMAIN is optional. It's the default domain used by tools like list_mailboxes when you don't pass one explicitly. Skip it if you manage multiple domains and prefer to pass domain on every call.
Example usage
Once configured, ask your AI assistant things like:
- "Onboard a new domain
acme.example— walk me through DNS setup and activation" - "Create mailboxes for alice@acme.example and bob@acme.example"
- "Set up
support@acme.exampleas an alias to both Alice and Bob" - "Configure an autoresponder on
vacation@acme.exampleuntil January 15th" - "Delete the mailboxes for everyone who left: list of addresses..."
Three built-in prompts are registered to scaffold common workflows: mailbox_creation_wizard, bulk_operation_planner, domain_onboarding.
Tools
Domain
list_domains, get_domain, create_domain, update_domain, get_domain_records, get_domain_diagnostics, activate_domain, get_domain_usage
Mailbox
list_mailboxes, get_mailbox, create_mailbox, update_mailbox, delete_mailbox, reset_mailbox_password, set_autoresponder
Alias
list_aliases, get_alias, create_alias, update_alias, delete_alias
Identity
list_identities, get_identity, create_identity, update_identity, delete_identity
Forwarding
list_forwardings, get_forwarding, create_forwarding, update_forwarding, delete_forwarding
Rewrite
list_rewrites, get_rewrite, create_rewrite, update_rewrite, delete_rewrite
All mutation tools (create_*, update_*, delete_*, activate_*, set_autoresponder, reset_mailbox_password) accept a list[dict] of items and return a bulk-result envelope with per-item success/failure. A single-item list works too.
Resources
Read-only views addressable by URI:
domains://— all domains on the accountdomain://{name}— one domain's full configdomain-records://{name}— required DNS records for setupdomain-usage://{name}— message + storage metricsmailboxes://{domain}— mailboxes for a domainmailbox://{domain}/{local_part}— one mailboxidentities://{domain}/{mailbox}— identities on a mailboxforwardings://{domain}/{mailbox}— forwardings on a mailboxaliases://{domain}— aliases for a domainrewrites://{domain}— rewrite rules for a domain
Notes
- Migadu's API returns HTTP 500 on successful DELETE (known quirk). The client treats 200/204/404/500 as success on DELETE; other codes raise.
- One long-lived
httpx.AsyncClientper server process, closed on shutdown via FastMCP lifespan hook. list_*tools pass responses through a static summarizer when they exceed ~2000 tokens, returning a count plus a sample instead of flooding context.
Development
git clone https://github.com/Michaelzag/migadu-mcp.git
cd migadu-mcp
uv sync --group dev
# Quality gates (same as CI)
uv run ruff format --check .
uv run ruff check migadu_mcp/ tests/
uv run ty check migadu_mcp/
uv run pytest
uv run bandit -r migadu_mcp/
Tests use respx to mock the Migadu API — no credentials needed. Integration tests (behind @pytest.mark.integration) hit the real API and are skipped by default.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file migadu_mcp-3.6.0.tar.gz.
File metadata
- Download URL: migadu_mcp-3.6.0.tar.gz
- Upload date:
- Size: 56.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca59ca4ae64fe0d05ff7d0e38aa0e6851b832ae273a3e8699d333bf9ca186ce7
|
|
| MD5 |
8e7c3d325721830ed5095ee496ee3a70
|
|
| BLAKE2b-256 |
ff6fb854729df7abc69f2637d1621801c4af2c0a6f3f8bd0ce790893b5ae9e16
|
Provenance
The following attestation bundles were made for migadu_mcp-3.6.0.tar.gz:
Publisher:
main.yml on Michaelzag/migadu-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
migadu_mcp-3.6.0.tar.gz -
Subject digest:
ca59ca4ae64fe0d05ff7d0e38aa0e6851b832ae273a3e8699d333bf9ca186ce7 - Sigstore transparency entry: 1355477328
- Sigstore integration time:
-
Permalink:
Michaelzag/migadu-mcp@9862af8c18840266c14d0cfe4eb8880bb172ff7e -
Branch / Tag:
refs/tags/v3.6.0 - Owner: https://github.com/Michaelzag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@9862af8c18840266c14d0cfe4eb8880bb172ff7e -
Trigger Event:
release
-
Statement type:
File details
Details for the file migadu_mcp-3.6.0-py3-none-any.whl.
File metadata
- Download URL: migadu_mcp-3.6.0-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbf9a29b6aea2059eccfd8579b40dfa8bc4e9c348bce4ebf62f021fcaa785d61
|
|
| MD5 |
29f731de05eb26d048acbf348c331060
|
|
| BLAKE2b-256 |
2312ccf6d665be64d7be49970dab14fbddf2b949f07a6418965bf8e9eced9f35
|
Provenance
The following attestation bundles were made for migadu_mcp-3.6.0-py3-none-any.whl:
Publisher:
main.yml on Michaelzag/migadu-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
migadu_mcp-3.6.0-py3-none-any.whl -
Subject digest:
bbf9a29b6aea2059eccfd8579b40dfa8bc4e9c348bce4ebf62f021fcaa785d61 - Sigstore transparency entry: 1355477334
- Sigstore integration time:
-
Permalink:
Michaelzag/migadu-mcp@9862af8c18840266c14d0cfe4eb8880bb172ff7e -
Branch / Tag:
refs/tags/v3.6.0 - Owner: https://github.com/Michaelzag
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@9862af8c18840266c14d0cfe4eb8880bb172ff7e -
Trigger Event:
release
-
Statement type: