NimbleBrainInc/mcp-mailchimp
If you are the rightful owner of mcp-mailchimp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
MCP server for Mailchimp Marketing API, enabling management of email marketing campaigns, audiences, and analytics.
Mailchimp MCP Server
MCP server for Mailchimp Marketing API. Manage email marketing campaigns, audiences, members, segments, and analytics with comprehensive automation features.
Features
- Audience Management: Create and manage subscriber lists
- Member Operations: Add, update, and organize subscribers
- Campaign Management: Create, send, and schedule email campaigns
- Segmentation: Target specific audience groups
- Tags: Organize and categorize members
- Analytics: Track campaign performance metrics
- Templates: Manage email templates
- Automation: Workflow automation support
Setup
Prerequisites
- Mailchimp account (free or paid)
- API key with data center identifier
Environment Variables
MAILCHIMP_API_KEY
(required): Your Mailchimp API key with data center
How to get credentials:
- Go to mailchimp.com
- Log in to your account
- Click your profile icon → Account & Billing
- Go to Extras → API keys
- Click "Create A Key"
- Copy the API key (format:
abc123-us1
) - Store as
MAILCHIMP_API_KEY
Direct link: https://admin.mailchimp.com/account/api/
Understanding API Key Format:
- API keys include a data center identifier after the dash
- Example:
abc123def456-us1
- The
us1
part is the data center (can be us1-us20, etc.) - This determines your API base URL:
https://us1.api.mailchimp.com/3.0
Rate Limits
- Standard: 10 requests per second for most endpoints
- Batch operations: 1 request per second
- Higher limits available for paid accounts
- HTTP 429 response when limit exceeded
Available Tools
Audience Management
list_audiences
List all audience lists.
Parameters:
count
(int, optional): Number of audiences to return (default: 10, max: 1000)offset
(int, optional): Number to skip for pagination (default: 0)
Example:
audiences = await list_audiences(count=20)
# Returns:
# {
# "lists": [
# {
# "id": "abc123",
# "name": "Newsletter Subscribers",
# "stats": {
# "member_count": 5432,
# "unsubscribe_count": 123,
# "open_rate": 23.5,
# "click_rate": 4.2
# }
# }
# ],
# "total_items": 5
# }
get_audience
Get audience details and statistics.
Parameters:
list_id
(string, required): Audience list ID
Example:
audience = await get_audience(list_id="abc123")
# Returns detailed stats:
# - member_count, unsubscribe_count
# - open_rate, click_rate
# - date_created, modules (signup forms, etc.)
# - contact info, permission_reminder
# - campaign_defaults (from_name, from_email, subject)
Member Management
list_audience_members
List members in an audience.
Parameters:
list_id
(string, required): Audience list IDstatus
(string, optional): Filter by statuscount
(int, optional): Number to return (default: 10, max: 1000)offset
(int, optional): Number to skip (default: 0)
Member Status Values:
- subscribed: Active subscribers
- unsubscribed: Unsubscribed members
- cleaned: Bounced or invalid emails
- pending: Awaiting opt-in confirmation
- transactional: Transactional-only subscribers
Example:
# All members
members = await list_audience_members(list_id="abc123")
# Active subscribers only
active = await list_audience_members(
list_id="abc123",
status="subscribed",
count=100
)
# Unsubscribed members
unsubscribed = await list_audience_members(
list_id="abc123",
status="unsubscribed"
)
add_member
Add a member to an audience.
Parameters:
list_id
(string, required): Audience list IDemail_address
(string, required): Member emailstatus
(string, optional): Member status (default: subscribed)merge_fields
(dict, optional): Custom fieldstags
(list, optional): Tag names to applyvip
(bool, optional): Mark as VIP (default: false)
Common Merge Fields:
FNAME
: First nameLNAME
: Last namePHONE
: Phone numberBIRTHDAY
: Birthday (MM/DD format)ADDRESS
: Address object- Custom fields defined in your audience
Example:
# Simple subscription
member = await add_member(
list_id="abc123",
email_address="user@example.com",
status="subscribed"
)
# Full member with custom fields
member = await add_member(
list_id="abc123",
email_address="john@example.com",
status="subscribed",
merge_fields={
"FNAME": "John",
"LNAME": "Doe",
"PHONE": "+1-555-0123"
},
tags=["customer", "vip"],
vip=True
)
# Pending confirmation (double opt-in)
member = await add_member(
list_id="abc123",
email_address="user@example.com",
status="pending"
)
update_member
Update member information.
Parameters:
list_id
(string, required): Audience list IDemail_address
(string, required): Member emailstatus
(string, optional): Updated statusmerge_fields
(dict, optional): Updated fieldsvip
(bool, optional): Updated VIP status
Example:
# Update status (subscribe)
member = await update_member(
list_id="abc123",
email_address="user@example.com",
status="subscribed"
)
# Update information
member = await update_member(
list_id="abc123",
email_address="user@example.com",
merge_fields={
"FNAME": "Jane",
"PHONE": "+1-555-9999"
}
)
# Unsubscribe member
member = await update_member(
list_id="abc123",
email_address="user@example.com",
status="unsubscribed"
)
# Make VIP
member = await update_member(
list_id="abc123",
email_address="user@example.com",
vip=True
)
delete_member
Remove a member from audience (permanent deletion).
Parameters:
list_id
(string, required): Audience list IDemail_address
(string, required): Member email
Example:
result = await delete_member(
list_id="abc123",
email_address="user@example.com"
)
# Note: This permanently deletes the member
# To unsubscribe instead, use update_member with status="unsubscribed"
Campaign Management
list_campaigns
List email campaigns.
Parameters:
status
(string, optional): Filter by statuscount
(int, optional): Number to return (default: 10, max: 1000)offset
(int, optional): Number to skip (default: 0)
Campaign Status Values:
- save: Draft campaign
- paused: Paused campaign
- schedule: Scheduled to send
- sending: Currently sending
- sent: Completed campaign
Example:
# All campaigns
campaigns = await list_campaigns(count=20)
# Sent campaigns only
sent = await list_campaigns(status="sent")
# Draft campaigns
drafts = await list_campaigns(status="save")
get_campaign
Get campaign details and statistics.
Parameters:
campaign_id
(string, required): Campaign ID
Example:
campaign = await get_campaign(campaign_id="xyz789")
# Returns:
# - id, type, status
# - settings (subject_line, from_name, reply_to, etc.)
# - recipients (list_id, segment info)
# - send_time, create_time
# - report_summary (opens, clicks, etc.)
create_campaign
Create a new email campaign.
Parameters:
campaign_type
(string, required): Campaign typelist_id
(string, required): Audience list IDsubject_line
(string, required): Email subjectfrom_name
(string, required): Sender namereply_to
(string, required): Reply-to emailtitle
(string, optional): Internal campaign title
Campaign Types:
- regular: Standard email campaign
- plaintext: Plain text only
- absplit: A/B split test
- rss: RSS-driven campaign
- variate: Multivariate test
Example:
# Create regular campaign
campaign = await create_campaign(
campaign_type="regular",
list_id="abc123",
subject_line="Monthly Newsletter - October 2025",
from_name="Company Name",
reply_to="hello@company.com",
title="October Newsletter"
)
# Create A/B test campaign
ab_campaign = await create_campaign(
campaign_type="absplit",
list_id="abc123",
subject_line="Subject Line A",
from_name="Company",
reply_to="hello@company.com"
)
# After creation, add content with Mailchimp's content endpoints
send_campaign
Send or schedule a campaign.
Parameters:
campaign_id
(string, required): Campaign IDschedule_time
(string, optional): ISO 8601 datetime for scheduling
Example:
# Send immediately
result = await send_campaign(campaign_id="xyz789")
# Schedule for later
result = await send_campaign(
campaign_id="xyz789",
schedule_time="2025-10-15T10:00:00Z"
)
# Note: Campaign must have content before sending
list_templates
List email templates.
Parameters:
count
(int, optional): Number to return (default: 10, max: 1000)offset
(int, optional): Number to skip (default: 0)
Example:
templates = await list_templates(count=50)
# Returns:
# {
# "templates": [
# {
# "id": 123,
# "name": "Newsletter Template",
# "type": "user",
# "category": "custom"
# }
# ]
# }
Analytics
get_campaign_reports
Get campaign performance metrics.
Parameters:
campaign_id
(string, required): Campaign ID
Example:
report = await get_campaign_reports(campaign_id="xyz789")
# Returns comprehensive stats:
# {
# "id": "xyz789",
# "type": "regular",
# "emails_sent": 10000,
# "opens": {
# "opens_total": 2500,
# "unique_opens": 2100,
# "open_rate": 21.0
# },
# "clicks": {
# "clicks_total": 450,
# "unique_clicks": 380,
# "click_rate": 3.8
# },
# "bounces": {
# "hard_bounces": 15,
# "soft_bounces": 25
# },
# "unsubscribed": 12,
# "industry_stats": {
# "open_rate": 18.5,
# "click_rate": 2.3
# }
# }
Segmentation
list_segments
List audience segments.
Parameters:
list_id
(string, required): Audience list IDcount
(int, optional): Number to return (default: 10, max: 1000)offset
(int, optional): Number to skip (default: 0)
Example:
segments = await list_segments(list_id="abc123")
# Returns:
# {
# "segments": [
# {
# "id": 456,
# "name": "VIP Customers",
# "member_count": 250,
# "type": "saved"
# }
# ]
# }
create_segment
Create a new segment.
Parameters:
list_id
(string, required): Audience list IDname
(string, required): Segment namestatic_segment
(list, optional): List of member emails (for static segments)
Example:
# Static segment with specific members
segment = await create_segment(
list_id="abc123",
name="Beta Testers",
static_segment=[
"user1@example.com",
"user2@example.com",
"user3@example.com"
]
)
# For dynamic segments, use Mailchimp's condition builder in the UI
# or advanced API endpoints
Tags
list_tags
List audience tags.
Parameters:
list_id
(string, required): Audience list IDcount
(int, optional): Number to return (default: 10, max: 1000)offset
(int, optional): Number to skip (default: 0)
Example:
tags = await list_tags(list_id="abc123")
# Returns:
# {
# "tags": [
# {
# "id": 789,
# "name": "customer"
# },
# {
# "id": 790,
# "name": "vip"
# }
# ]
# }
add_tags_to_member
Tag audience members.
Parameters:
list_id
(string, required): Audience list IDemail_address
(string, required): Member emailtags
(list, required): Tag names to addis_syncing
(bool, optional): External sync flag (default: false)
Example:
# Add tags to a member
result = await add_tags_to_member(
list_id="abc123",
email_address="user@example.com",
tags=["customer", "premium", "engaged"]
)
# Tags are useful for:
# - Segmentation
# - Campaign targeting
# - Automation triggers
# - Member categorization
Common Workflows
Newsletter Signup Flow
# 1. Add new subscriber
member = await add_member(
list_id="abc123",
email_address="new@example.com",
status="subscribed",
merge_fields={
"FNAME": "Sarah",
"LNAME": "Smith"
},
tags=["newsletter", "new-subscriber"]
)
# 2. Create welcome campaign
campaign = await create_campaign(
campaign_type="regular",
list_id="abc123",
subject_line="Welcome to Our Newsletter!",
from_name="Company Name",
reply_to="hello@company.com"
)
# 3. Send campaign
await send_campaign(campaign_id=campaign["id"])
Campaign Creation and Analysis
# 1. Create campaign
campaign = await create_campaign(
campaign_type="regular",
list_id="abc123",
subject_line="Special Offer - 20% Off",
from_name="Company Store",
reply_to="sales@company.com",
title="October Sale Campaign"
)
# 2. Schedule for optimal time
await send_campaign(
campaign_id=campaign["id"],
schedule_time="2025-10-15T09:00:00Z"
)
# 3. After sending, check performance
report = await get_campaign_reports(campaign_id=campaign["id"])
print(f"Open Rate: {report['opens']['open_rate']}%")
print(f"Click Rate: {report['clicks']['click_rate']}%")
print(f"Unsubscribes: {report['unsubscribed']}")
Segmentation for Targeted Campaigns
# 1. Get audience members
members = await list_audience_members(
list_id="abc123",
status="subscribed"
)
# 2. Tag engaged members
for member in members["members"]:
if member.get("stats", {}).get("avg_open_rate", 0) > 25:
await add_tags_to_member(
list_id="abc123",
email_address=member["email_address"],
tags=["engaged", "high-open-rate"]
)
# 3. Create segment for VIP campaign
segment = await create_segment(
list_id="abc123",
name="Engaged Subscribers"
)
Member Management
# Update member status
member = await update_member(
list_id="abc123",
email_address="user@example.com",
status="subscribed",
merge_fields={
"FNAME": "John",
"LNAME": "Updated"
}
)
# Add VIP status
await update_member(
list_id="abc123",
email_address="vip@example.com",
vip=True
)
# Tag for specific campaign
await add_tags_to_member(
list_id="abc123",
email_address="user@example.com",
tags=["product-launch-2025"]
)
Best Practices
- Double opt-in: Use
status="pending"
for GDPR compliance - Merge fields: Collect useful data during signup
- Tags: Organize members for better segmentation
- Segments: Target specific groups for campaigns
- VIP members: Prioritize high-value subscribers
- Test campaigns: Use A/B testing for optimization
- Monitor analytics: Track open rates and click rates
- Clean lists: Remove bounced emails regularly
- Respect unsubscribes: Update status immediately
- Rate limiting: Implement retry logic for 429 errors
Merge Field Examples
Common merge fields for personalization:
merge_fields = {
"FNAME": "John", # First name
"LNAME": "Doe", # Last name
"PHONE": "+1-555-0123", # Phone number
"BIRTHDAY": "05/15", # Birthday (MM/DD)
"ADDRESS": { # Address object
"addr1": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "US"
},
"COMPANY": "Acme Corp", # Company name
"WEBSITE": "example.com" # Website
}
Use merge tags in email content: *|FNAME|*
, *|LNAME|*
Campaign Performance Metrics
Key metrics to track:
- Open Rate: % of recipients who opened
- Click Rate: % of recipients who clicked
- Bounce Rate: Invalid/rejected emails
- Unsubscribe Rate: % who unsubscribed
- Revenue: E-commerce tracking (if enabled)
- Industry Averages: Compare to your industry
Error Handling
Common errors:
- 401 Unauthorized: Invalid API key or wrong data center
- 400 Bad Request: Invalid parameters or missing required fields
- 404 Not Found: List, campaign, or member not found
- 429 Too Many Requests: Rate limit exceeded (10 req/sec)
- 500 Internal Server Error: Mailchimp service issue