A Model Context Protocol server that exposes the full Campaign Monitor (createsend) v3.3 API β 117 tools across 9 resource categories β to MCP-compatible clients like Claude Desktop, Claude Code, and the MCP Inspector.
Authenticates with a Campaign Monitor API key (simplest, recommended) or via OAuth 2.0 with an auto-refreshing access token. Runs locally over stdio.
- Complete API coverage β account, clients, campaigns, lists, segments, subscribers,
templates, transactional email, and journeys. Includes destructive/sending operations
(send campaign, send transactional email, delete) β these are flagged with
β οΈ in their descriptions and tagged with the MCPdestructiveHintannotation. - Simple auth β drop in an API key and go. OAuth 2.0 is available as an optional alternative (with automatic refresh-token rotation persisted to a local store).
- Category filtering β expose only the categories you need via
CM_ENABLED_CATEGORIESto keep the tool surface small.
You don't need to clone or build β run it straight from npm with npx, which is also how
you point an MCP client at it (-y auto-confirms the one-time download):
{
"mcpServers": {
"campaign-monitor": {
"command": "npx",
"args": ["-y", "@kanopi/campaign-monitor-mcp"],
"env": { "CM_API_KEY": "your-api-key" }
}
}
}Or install the CLI globally: npm install -g @kanopi/campaign-monitor-mcp, then the
campaign-monitor-mcp command is available on your PATH.
See Registering the MCP server for per-client setup. To run from source instead (for development), see Running from source.
- Node.js 20+
- A Campaign Monitor account and an API key (Account settings β API keys). OAuth credentials are an optional alternative β see Using OAuth instead.
npm install # also builds via the prepare hook
npm run build # or build manuallyCopy the example env file and fill it in:
cp .env.example .env-
In Campaign Monitor, click your account name (top-right) β Account settings β API keys, and copy the API key.
- The account-level key (top-level account settings) can access every client, so
the
accountandclientstools work. A client-level key (inside a specific client's settings) is scoped to just that client.
- The account-level key (top-level account settings) can access every client, so
the
-
Set it in
.envβ this is the only credential you need:CM_API_KEY=your-api-key-hereLeave the OAuth variables blank. The server uses the API key automatically whenever no OAuth refresh token is present.
OAuth lets the server use short-lived, scoped, revocable tokens instead of a static key. It takes more setup. Skip this entirely if you're using an API key.
-
Register an OAuth application. Log in, open Integrations in the top nav (select a client first if prompted), then OAuth Registration in the right sidebar. Fill in an application name, a description, and set the Redirect / Callback URI to
http://127.0.0.1:53682/callback(it must matchCM_REDIRECT_URIexactly). Submit to get a Client ID and Client Secret. -
Put
CM_CLIENT_IDandCM_CLIENT_SECRETin.env. -
Run the one-time bootstrap β it opens your browser, you approve the scopes, and a refresh token is stored (and printed so you can paste
CM_REFRESH_TOKENinto.envas a backup):npm run auth
When all three OAuth variables are present they take precedence over CM_API_KEY.
npm run smoke # auth + GET /clients + GET /billingdetails (no writes)
npm run inspector # build + open the MCP Inspector against the serverThe server is a local stdio process: an MCP client launches it with npx and talks to
it over stdin/stdout. You register it once per client by pointing the client at the package
and supplying credentials as environment variables.
The only prerequisite is Node.js 20+. npx -y @kanopi/campaign-monitor-mcp downloads
and runs the package on first use (and caches it) β no clone, no build, no paths to manage.
The credentials block is the same for every client β just your API key:
Tip: you can omit
enventirely if you keepCM_API_KEYin the project's.envfile β the server loads it on startup. (Using OAuth instead? PutCM_CLIENT_ID,CM_CLIENT_SECRET, andCM_REFRESH_TOKENin theenvblock instead ofCM_API_KEY.)
Edit claude_desktop_config.json (create it if missing):
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"campaign-monitor": {
"command": "npx",
"args": ["-y", "@kanopi/campaign-monitor-mcp"],
"env": {
"CM_API_KEY": "your-api-key"
}
}
}
}Save and fully quit and reopen Claude Desktop. The tools appear under the π (MCP) icon in the chat input.
Register with one command (no manual JSON editing):
claude mcp add campaign-monitor \
--env CM_API_KEY=your-api-key \
-- npx -y @kanopi/campaign-monitor-mcpAdd --scope user to make it available in every project (default is the current project
only). Verify with claude mcp list, and inside a session run /mcp to see the tools.
Remove with claude mcp remove campaign-monitor.
Any client that supports local stdio MCP servers uses the same shape. Add to the client's
MCP config (e.g. Cursor's ~/.cursor/mcp.json or a project .cursor/mcp.json):
{
"mcpServers": {
"campaign-monitor": {
"command": "npx",
"args": ["-y", "@kanopi/campaign-monitor-mcp"],
"env": {
"CM_API_KEY": "your-api-key"
}
}
}
}117 tools is a lot to load at once. To register only the categories you need, add
CM_ENABLED_CATEGORIES to the env block, e.g.:
"env": { "CM_ENABLED_CATEGORIES": "campaigns,lists,subscribers", "...": "..." }Before wiring into a client, confirm the server boots and lists tools with the Inspector:
npm run inspector # opens the MCP Inspector against node dist/index.jsFor development (or to run a local build instead of the published package), clone the repo,
install, and point the client at the built entry file with node:
git clone https://github.com/kanopi/campaign-monitor-mcp.git
cd campaign-monitor-mcp
npm install # builds via the prepare hookThen use this config shape instead of the npx one above (use the absolute path):
{
"mcpServers": {
"campaign-monitor": {
"command": "node",
"args": ["/absolute/path/to/campaign-monitor-mcp/dist/index.js"],
"env": { "CM_API_KEY": "your-api-key" }
}
}
}- "No Campaign Monitor credentials found" β the
envblock is missing/misspelled, or (from source).envisn't being read. Provide credentials in the client config'senv. - Server doesn't appear / "failed to start" β ensure
node(v20+) is on the client's PATH; some GUI clients don't inherit your shell PATH, so use an absolute path tonpx(runwhich npx) or tonode. From source, also confirm you rannpm install/npm run buildand used an absolute path todist/index.js. npxcan't find the package β confirm the scoped name@kanopi/campaign-monitor-mcpis spelled correctly and published; clear a stale cache withnpx clear-npx-cache.- 401 / authentication errors at runtime β using an API key: confirm it's correct and
not revoked (and that an account-level key is used for
account/clientstools). Using OAuth: the refresh token expired or was revoked β re-runnpm run auth.
| Variable | Purpose |
|---|---|
CM_API_KEY |
API key (recommended). Used unless OAuth credentials are present. |
CM_ENABLED_CATEGORIES |
Comma-separated list to limit exposed tool categories |
CM_CLIENT_ID / CM_CLIENT_SECRET |
OAuth application credentials (optional) |
CM_REFRESH_TOKEN |
OAuth seed refresh token, from npm run auth (optional) |
CM_REDIRECT_URI |
OAuth redirect URI (default http://127.0.0.1:53682/callback) |
CM_SCOPES |
Scopes requested during npm run auth |
CM_TOKEN_STORE |
Path to the OAuth token store file |
Tools follow a cm_<verb>_<resource> naming convention. Counts by category:
| Category | Tools | Examples |
|---|---|---|
| account | 13 | cm_list_clients, cm_get_billing_details, cm_add_admin |
| clients | 30 | cm_create_client, cm_get_client_lists, cm_suppress_emails |
| campaigns | 15 | cm_create_campaign, cm_send_campaign cm_get_campaign_summary |
| lists | 22 | cm_create_list, cm_create_custom_field, cm_create_webhook |
| segments | 7 | cm_create_segment, cm_get_segment_subscribers |
| subscribers | 7 | cm_add_subscriber, cm_import_subscribers, cm_unsubscribe_subscriber |
| templates | 5 | cm_create_template, cm_copy_template |
| transactional | 9 | cm_send_smart_email cm_send_classic_email cm_get_transactional_statistics |
| journeys | 9 | cm_get_journey, cm_copy_journey, cm_publish_event |
- Destructive tools are enabled by default (per the build spec). Your MCP client's
permission prompts are the safety gate. To hard-disable a category, omit it from
CM_ENABLED_CATEGORIES. - Responses are returned as JSON. XML responses are not supported.
- Rate limiting (HTTP 429) is honored with a single bounded retry using
Retry-After. - Custom field keys are passed including their brackets, e.g.
[MyField].
MIT