@cyanheads/mailchimp-mcp-server
Allows drafting, testing, and sending Mailchimp campaigns, managing audiences, subscribers, segments, templates, files, and reports, with safe-by-default send gates.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@cyanheads/mailchimp-mcp-serverDraft a campaign for the upcoming webinar"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Tools
Eighteen always-on tools plus two conditional ones — mailchimp_assets (when MAILCHIMP_ASSETS_DIR is set) and mailchimp_local_templates (when MAILCHIMP_TEMPLATES_DIR is set). Workflow helpers orchestrate common flows end-to-end, primitive tools expose fine-grained CRUD, and the instruction tool returns procedural guidance merged with live account state.
Tool Name | Description |
| Account profile, plan, data center, total subscribers, and the Chimp Chatter activity feed. |
| Manage audiences (lists) — read, create/update, per-audience analytics, signup-form config. No delete. |
| One-call audience health digest: info, stats, growth history, top email clients, merge-field schema. |
| Subscriber CRUD + tags/notes/activity. |
| Add or update a subscriber idempotently with status, merge fields, tags, and optional note. |
| Locate a subscriber by email in one audience or across the account. |
| Batch add/update subscribers (capped at 500/call). Status defaults to |
| CRUD for audience segments (saved, static, fuzzy) plus member listing and batch add/remove. |
| Read + create/update custom subscriber attributes. No delete — drops data across all subscribers. |
| Campaign record management: list/get/create/update, replicate, content, checklist, RSS/resend controls. |
| Compose and send (or schedule/test) a campaign in one call. Elicits human confirmation on send/schedule. |
| Duplicate a campaign with optional overrides, then draft/test/send/schedule. Same elicit + cleanup semantics. |
| Campaign reports — generic slicer across ten dimensions (clicks, opens, locations, etc.). |
| Post-send analytics digest — headline metrics + top 5 slices in one response. |
| Email template read/write — reads ( |
| File Manager (Content Studio) — upload, list, fetch, rename, delete files on Mailchimp's CDN. Embed the returned |
| Global search across members or campaigns. Lightweight discovery — use |
| Local-assets surface. List your assets dir, inspect cache state, pre-warm uploads ahead of a send. Most workflows don't call this directly — |
| Local-template authoring surface. List/get/render-preview your |
| Returns a structured procedural playbook merged with live account state. Advice-only, no writes. |
mailchimp_send_campaign
Compose and send (or schedule/test) a campaign in one call.
Chains create → content → checklist → optional test → send/schedule
Requests human confirmation via
ctx.elicitwhenmode: 'send' | 'schedule'and the client supports elicitationAuto-deletes aborted or failed drafts when
cleanupOnError: true(default)Supports
html,plaintext, andtemplateId + mergeDatacontent forms
mailchimp_replicate_campaign
Duplicate an existing campaign with optional overrides, then send/schedule/test or leave as draft.
Overrides: subject, from name, reply-to, audience, segment, content
Same elicit confirmation + cleanup semantics as
mailchimp_send_campaignTuned for the common "send v2 of last week's newsletter with an updated intro" pattern
mailchimp_upsert_subscriber
Add or update a subscriber in one idempotent call.
Declarative tag sync — pass the desired active set and the tool computes the add/remove delta
preserveTagsprotects named segment memberships (Mailchimp stores static-segment membership as tags)status: 'pending'triggers Mailchimp's double-opt-in email;'subscribed'requires documented consentPUT
/members/{hash}for create path, PATCH for update to skip re-validating pre-existing merge fields
mailchimp_import_subscribers
Batch add (and optionally update) subscribers in one call.
Capped at 500 rows per call — chunk larger imports client-side
Status defaults to
pending(double-opt-in) to prevent accidental mass-sendsReturns per-row succeeded/failed with error reasons
mailchimp_campaign_report
Aggregated post-send analytics for a campaign.
Headline delivery metrics: sent, bounces, abuse reports
Engagement: opens, clicks, unsubscribes
Top-N clicked links, locations, recent unsubscribes
Industry benchmarks when available
Use
mailchimp_reportswithoperation: 'slice'for a single dimension in detail
mailchimp_audience_overview
Single-call audience health digest — answers "what does this audience look like?" in one request.
Audience info + live stats
Configurable months of growth history
Top email clients
Full merge-field schema
Recent activity
mailchimp_playbook
Returns a structured procedural playbook merged with live account state. Advice-only — the agent executes subsequent steps with other tools.
Topics:
send,post-send-review,deliverability,list-hygiene,onboarding,subscriber-triage,design-campaignReturns markdown instructions + a live-state snapshot
nextToolSuggestionspre-fills arguments for the next likely tool call
Related MCP server: Mailchimp MCP Server
Resources and prompts
Type | Name | Description |
Resource |
| Account info snapshot — profile, plan, data center, total subscribers. |
Resource |
| Audience snapshot — name, contact, stats, double-opt-in status. |
Resource |
| Campaign snapshot — status, settings, recipients summary. |
Resource |
| Post-send campaign report headline metrics. |
Prompt |
| User-invokable starter — compose a monthly editorial newsletter from a URL or brief. Chains into |
All resource data is also reachable via tools. Large collections (audiences, campaigns) are not exposed as resources — use the list operation on the corresponding tool instead. Design reference for the prompt: docs/email-design-playbook.md.
Features
Built on @cyanheads/mcp-ts-core:
Declarative tool, resource, and prompt definitions — single file per primitive, framework handles registration and validation
Unified error handling — handlers throw, framework catches, classifies, and formats
Pluggable auth:
none,jwt,oauthStructured logging with optional OpenTelemetry tracing
STDIO and Streamable HTTP transports
Mailchimp-specific:
Auto-derives the API base URL from the
-dcsuffix on the API keySafe-by-default send workflows — elicit confirmation, pending-status imports, no permanent deletes from agent surface
Workflow tools parallelize related sub-requests under a configurable concurrency limit
Domain normalization shapes sparse upstream payloads into compact, LLM-friendly output without fabricating values
Getting started
Add the following to your MCP client configuration file. See docs/api-key.md for how to generate a Mailchimp API key.
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/mailchimp-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"MAILCHIMP_API_KEY": "your-key-with-dc-suffix-e.g.-us22"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/mailchimp-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"MAILCHIMP_API_KEY": "your-key-with-dc-suffix-e.g.-us22"
}
}
}
}Or with Docker:
{
"mcpServers": {
"mailchimp-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "MAILCHIMP_API_KEY=your-key-with-dc-suffix-e.g.-us22",
"ghcr.io/cyanheads/mailchimp-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 MAILCHIMP_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.3.2 or higher (or Node.js v24+).
A Mailchimp Marketing API key — the key's
-dcsuffix (e.g.-us22) identifies your data center and is parsed at startup.
Installation
Clone the repository:
git clone https://github.com/cyanheads/mailchimp-mcp-server.gitNavigate into the directory:
cd mailchimp-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env and set MAILCHIMP_API_KEYConfiguration
Variable | Description | Default |
| Required. Mailchimp Marketing API key including | — |
| Override API base URL (for mock servers or tests). |
|
| Per-request timeout in milliseconds. |
|
| Max retry attempts for transient upstream failures (0-10). |
|
| Max in-flight upstream requests per workflow tool (1-10). |
|
| Absolute path to a local assets directory. When set (Node-only), enables the | unset |
| Absolute path to a local templates directory. When set (Node-only), enables the | unset |
| Transport: |
|
| HTTP server hostname. |
|
| HTTP server port. |
|
| MCP endpoint path. |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for log files (Node.js only). |
|
| Enable OpenTelemetry. |
|
See .env.example for the full list of optional overrides.
Local assets (optional)
Set MAILCHIMP_ASSETS_DIR to enable a local-image workflow on top of Mailchimp's File Manager. Drop image files into the directory, reference them in HTML as @assets/<relative-path>, and the server uploads + rewrites at send time.
export MAILCHIMP_ASSETS_DIR=/Users/me/Pictures/email-assetsThen in a campaign:
<img src="@assets/hero.png" alt="Hero">
<a href="@assets/whitepaper.pdf">Download</a>When mailchimp_send_campaign (or mailchimp_campaigns set-content / mailchimp_replicate_campaign contentOverride) sees these references, it:
Hashes each referenced file (SHA-256).
Uploads cache misses to Mailchimp File Manager via the
mailchimp_filestool surface.Caches
sha256 → file_id + URLat<assetsDir>/.mailchimp-cache.json(atomic writes; safe to delete to force re-upload).Rewrites every
@assets/<path>to the public CDN URL before passing content upstream.
The mailchimp_assets tool exposes list, info, sync (pre-warm), and clear-cache for direct inspection — most workflows don't need it.
Caveats:
Mailchimp caps images at 1 MB and other files at 10 MB. Oversize files fail before upload with an actionable error.
Allowed extensions: see the
mailchimp_filestool description. WebP and AVIF are NOT in the allowlist — convert to PNG/JPG.Path traversal is rejected (
../and absolute paths throwForbidden).The
mailchimp_assetstool is Node-only; on Cloudflare Workers it isn't registered.
Local templates (optional)
Set MAILCHIMP_TEMPLATES_DIR to enable a local-template authoring workflow on top of Eta (v4 — fast, ESM-native, supports partials/conditionals/loops). This is the canonical write path for templates on free-tier Mailchimp accounts, where the upstream /templates API is read-only.
export MAILCHIMP_TEMPLATES_DIR=/Users/me/email-templatesemail-templates/
welcome.eta # body + optional YAML frontmatter
newsletter.eta
partials/
header.eta
footer.etaTemplate (welcome.eta) — YAML frontmatter on top, Eta body below:
---
subject: "Welcome to {{brand}}"
previewText: "Onboarding starts here"
vars:
- firstName
- brand
---
<%~ include('partials/header', it) %>
<h1>Hello <%= it.firstName %></h1>
<p>Welcome to <%= it.brand %>.</p>
<img src="@assets/hero.png" alt="Hero">Frontmatter is optional — a body with no --- block is treated as a meta-less template. All meta fields are optional too. The vars: list is informational only (declared variables aren't schema-enforced).
Sidecar fallback (legacy): prior to v0.3.1, meta lived in a separate
<name>.meta.yamlfile next to the body. That form still works for backward compatibility — if a.etahas no frontmatter, the loader falls back to reading the sidecar. Frontmatter takes precedence when both exist.
Reference from any campaign tool:
{
"audienceId": "abc123",
"subject": "Welcome to Acme",
"fromName": "Casey",
"replyTo": "casey@acme.com",
"content": {
"localTemplate": "welcome",
"localTemplateVars": { "firstName": "Sam", "brand": "Acme" }
},
"mode": "draft"
}The render pipeline:
Eta renders
welcome.etawithit = { firstName: 'Sam', brand: 'Acme' }.If L1 is configured,
@assets/hero.pngis uploaded to Mailchimp File Manager and rewritten to a CDN URL.Final HTML is set on the campaign via Mailchimp's
set-content.
The mailchimp_local_templates tool exposes list, get, render-preview (returns HTML without sending), and seed-from-mailchimp (reads a Mailchimp base/user template by ID and writes it to disk as a starting point — useful on free where you can read but not write upstream).
Example templates in this repo
The templates/ directory holds working examples — point MAILCHIMP_TEMPLATES_DIR at it directly to try them, or copy them into your own dir as a starting point:
Template | What it shows |
Minimal body — frontmatter declaring | |
Full inline-styled HTML newsletter. Demonstrates the recommended split: Mailchimp merge tags ( |
Caveats:
localTemplateis mutually exclusive withhtmlandtemplateIdon the same content block.Var validation isn't enforced by the schema — missing/extra vars surface as Eta render errors at send time.
Path traversal is rejected.
Node-only; not available on Workers.
Running the server
Local development
Watch mode (transport via
MCP_TRANSPORT_TYPE):bun run dev # stdio (default) MCP_TRANSPORT_TYPE=http bun run dev # httpBuild and run:
bun run rebuild bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t mailchimp-mcp-server .
docker run --rm -e MAILCHIMP_API_KEY=your-key-us22 -p 3010:3010 mailchimp-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/mailchimp-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Prompt definitions ( |
| Mailchimp client wrapper — HTTP plumbing, retries, normalization, typed surface. |
| Vitest tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped loggingRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/mailchimp-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server