A Model Context Protocol server that wraps the MailerLite v3 REST API so AI agents can manage subscriber lists, automations, and campaigns through clean tool calls instead of guess-and-check HTTP probes.
Built for indie authors, creators, and small teams who use Claude / other LLM agents to drive their email operations. Not affiliated with MailerLite, UAB.
The MailerLite REST API is well-built but sparsely documented in places that matter for agentic workflows — particularly around automation step email updates, where field names that work on read silently fail on write, plain-text bodies cap at 1000 characters, and the difference between "designed" legacy emails and new-builder emails determines whether HTML body writes work at all.
This MCP codifies those constraints once, exposes them as proper error types and inline documentation, and saves every downstream user the discovery tax.
8 tools across 4 surfaces. All read operations are safe; write operations are clearly marked.
| Tool | Surface | Read/Write | Purpose |
|---|---|---|---|
server_info |
meta | R | Check connectivity, API quota, account ID |
groups_list |
subscribers | R | List all subscriber groups + member counts |
subscribers_list |
subscribers | R | List subscribers, filterable by group + status |
automations_list |
automations | R | List all automations + enabled status |
automation_get |
automations | R | Full automation detail incl. steps + email metadata |
automation_email_update |
automations | W | Update email metadata (subject, from, from_name, reply_to, preheader, plain_text). Does NOT update HTML body — see Constraints. |
campaign_create |
campaigns | W | Create a draft campaign with HTML content. Campaign emails (unlike automation step emails) DO accept HTML content writes. |
campaign_schedule |
campaigns | W | Schedule a draft campaign for a specific send time + recipient group |
A roadmap for v0.2+ expansion (subscriber writes, full analytics, test sends, form management) lives in DESIGN.md.
Requires Python 3.11+ and uv.
git clone https://github.com/acato/mailerlite-mcp.git
cd mailerlite-mcp
uv syncGet a MailerLite API token: log in → bottom-left Integrations → Developer API → Generate new token.
Configure via environment variable:
export MAILERLITE_API_KEY=eyJ0eXAiOiJKV1Q...Edit ~/.claude.json (or your project-local .claude.json):
{
"mcpServers": {
"mailerlite": {
"command": "uv",
"args": [
"run",
"--no-sync",
"--project",
"/absolute/path/to/mailerlite-mcp",
"mailerlite-mcp"
],
"env": {
"MAILERLITE_API_KEY": "eyJ0eXAiOiJKV1Q..."
}
}
}
}Edit claude_desktop_config.json (location varies by OS):
{
"mcpServers": {
"mailerlite": {
"command": "uv",
"args": [
"run",
"--no-sync",
"--project",
"/absolute/path/to/mailerlite-mcp",
"mailerlite-mcp"
],
"env": {
"MAILERLITE_API_KEY": "eyJ0eXAiOiJKV1Q..."
}
}
}
}Restart Claude. Tools should appear under the mailerlite__ namespace.
These are codified into the tool behavior so you don't have to learn them the hard way.
The REST API's PUT /api/automations/{auto_id}/emails/{email_id} endpoint silently accepts (but does not persist) writes to the content field on legacy classic-builder emails. Field names html, body, html_content, design all behave the same way.
What this MCP does: automation_email_update accepts and persists subject, from, from_name, reply_to, preheader, and plain_text — and explicitly raises MailerLiteUnsupportedOperation if you try to pass html_content, with a documented workaround: use campaign_create instead (campaigns DO accept HTML content) or use the MailerLite web editor.
Automation step email plain-text bodies cap at 1000 chars. Sending more returns HTTP 422.
What this MCP does: automation_email_update validates length client-side and raises MailerLiteValidationError with a clear message before the HTTP call.
PUT /api/automations/{auto_id}/steps/{step_id} on partial bodies can create a new email object and orphan the previous one. The fix is to pass the existing email_id explicitly in the body.
What this MCP does: automation_email_update operates on the email endpoint directly (not the step endpoint) precisely to avoid this footgun. The MCP never creates a new email_id when you intended to update an existing one.
Some endpoints require body wrapped in {"data": {...}}; others accept top-level fields directly. The MailerLite docs don't always say which.
What this MCP does: the client handles wrapper conventions internally per endpoint. You never write {"data": ...} from a tool call.
See DESIGN.md for the full constraint catalog + reasoning.
If you're using this MCP inside an organization or agent workflow, we strongly recommend adopting this policy:
All MailerLite interactions go through this MCP. No ad-hoc REST. No one-off scripts. Any missing capability is a BUG in the MCP — file an issue, extend the tool surface, ship.
The reason: every undocumented MailerLite API behavior is a discovery tax. Pay it once (by extending this MCP), not every time anyone touches MailerLite. The maintainers built this MCP after one such tax — see DESIGN.md §9 (Discovery log).
- v0.1: Beta. 8 tools, all behaviors discovered and codified through manual investigation against a live account on 2026-06-05.
- Tested against MailerLite v3 API as of 2026-06-05.
- Active maintenance.
Apache License 2.0 — see LICENSE.
Pull requests welcome. See CONTRIBUTING.md. New tools should:
- Codify any field-name / wrapper / quota constraints discovered during implementation, in DESIGN.md and inline in code
- Surface errors via the project's exception hierarchy (
mailerlite_mcp.errors) — not rawhttpx.HTTPError - Be covered by tests using
respxfor HTTP mocking