@kieksme/listmonk-mcp
Provides tools for managing a Listmonk instance through its REST API, including subscribers, campaigns, lists, templates, media, bounces, imports, settings, transactional messages, and admin/dashboard operations.
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., "@@kieksme/listmonk-mcpCreate a subscriber list named 'Monthly Digest' and add john@example.com to it."
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.
@kieksme/listmonk-mcp
An MCP (Model Context Protocol) server exposing the full Listmonk REST API (72 tools across 14 categories) to MCP-compatible LLM clients — as a local stdio process your client spawns itself, or as a remote Streamable HTTP deployment any number of clients can connect to.
Built against the Listmonk OpenAPI spec.
Quickstart
Local: let your MCP client spawn the server itself over stdio — nothing to run by hand, no port to open. Add it to your client's config (Claude Code shown here; see Connecting your MCP client below for Cursor, VS Code, Claude Desktop, OpenCode, LM Studio, and ChatGPT):
claude mcp add listmonk \
-e LISTMONK_URL=https://newsletter.example.com \
-e LISTMONK_API_USER=my-api-user \
-e LISTMONK_API_TOKEN=xxxxxxxx \
-- npx -y @kieksme/listmonk-mcp --stdioRemote: start the server once, reachable over HTTP by any number of clients:
LISTMONK_URL=https://newsletter.example.com \
LISTMONK_API_USER=my-api-user \
LISTMONK_API_TOKEN=xxxxxxxx \
npx @kieksme/listmonk-mcpclaude mcp add --transport http listmonk http://localhost:3000/mcpSee Running the server for both modes in more detail, including Docker.
Related MCP server: listmonk-mcp-bridge
Connecting your MCP client
Each client below supports two setups — pick one:
Local (stdio): the client spawns
npx @kieksme/listmonk-mcp --stdioitself as a subprocess and talks MCP over its stdin/stdout. No server to keep running, no port, no reachability concerns — this is generally the simpler default for a single local client.Remote (HTTP): you run the server yourself (see Running the server) and the client connects to its URL. Needed when multiple clients share one server instance, or the server runs somewhere other than your machine.
Using pnpm instead of npx for the local/stdio setup: every local (stdio) example below uses command: "npx" with args: ["-y", "@kieksme/listmonk-mcp", "--stdio"]. If you prefer pnpm, swap in command: "pnpm" with args: ["dlx", "@kieksme/listmonk-mcp", "--stdio"] — and drop the -y. -y is npx's "skip the install confirmation prompt" flag; pnpm dlx has no such prompt to begin with, so it doesn't accept -y at all and exits immediately with ERROR Unknown option: 'y' (surfacing to the client as a generic "Connection closed", since the process dies before it ever speaks MCP). The same swap applies to any CLI form below that starts with npx -y — replace it with pnpm dlx (no -y).
Reachability note for the remote/HTTP setup: a client only needs http://localhost:3000 if it runs on the same machine as the server. Claude Code, Cursor, VS Code, OpenCode, and LM Studio are all local tools, so localhost works directly. Claude Desktop is a local app and can usually reach localhost too. ChatGPT and Claude.ai (the web apps) run in the cloud and cannot reach your localhost — to use this server with them you'd need to deploy it somewhere reachable from the internet (or tunnel it, e.g. with ngrok http 3000) and use that public URL instead. ChatGPT's connectors are HTTP-only, so it has no local/stdio option below.
Claude Code
Local (stdio), project-scoped via .mcp.json in your repo root:
{
"mcpServers": {
"listmonk": {
"command": "npx",
"args": ["-y", "@kieksme/listmonk-mcp", "--stdio"],
"env": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
}
}
}
}Or from the CLI:
claude mcp add listmonk \
-e LISTMONK_URL=https://newsletter.example.com \
-e LISTMONK_API_USER=my-api-user \
-e LISTMONK_API_TOKEN=xxxxxxxx \
-- npx -y @kieksme/listmonk-mcp --stdioRemote (HTTP), once the server is running (see Running the server):
{
"mcpServers": {
"listmonk": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}claude mcp add --transport http listmonk http://localhost:3000/mcpIf you set MCP_SERVER_AUTH_TOKEN on the server, add the header: claude mcp add --transport http listmonk http://localhost:3000/mcp --header "Authorization: Bearer <token>".
Cursor
One-click install (local/stdio, with placeholder credentials you'll need to fill in afterwards in Cursor's MCP settings):
Or configure it manually — local (stdio), via .cursor/mcp.json in your repo root (or globally in ~/.cursor/mcp.json):
{
"mcpServers": {
"listmonk": {
"command": "npx",
"args": ["-y", "@kieksme/listmonk-mcp", "--stdio"],
"env": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
}
}
}
}Remote (HTTP), once the server is running:
{
"mcpServers": {
"listmonk": {
"url": "http://localhost:3000/mcp"
}
}
}If you set MCP_SERVER_AUTH_TOKEN on the server, pass it as a header:
{
"mcpServers": {
"listmonk": {
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer <token>"
}
}
}
}You can also add either setup via Cursor Settings → MCP → Add new MCP server.
VS Code
One-click install (local/stdio, with placeholder credentials you'll need to fill in afterwards in VS Code's MCP settings):
Or configure it manually — local (stdio), via .vscode/mcp.json in your repo root:
{
"servers": {
"listmonk": {
"command": "npx",
"args": ["-y", "@kieksme/listmonk-mcp", "--stdio"],
"env": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
}
}
}
}Remote (HTTP), once the server is running (type is required here, since there's no command to infer it from):
{
"servers": {
"listmonk": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}Claude Desktop
Local (stdio), in claude_desktop_config.json:
{
"mcpServers": {
"listmonk": {
"command": "npx",
"args": ["-y", "@kieksme/listmonk-mcp", "--stdio"],
"env": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
}
}
}
}Remote (HTTP): Settings → Connectors → Add custom connector, and paste http://localhost:3000/mcp as the URL (server must already be running). If your Claude Desktop version's config file supports remote servers directly, the equivalent entry is:
{
"mcpServers": {
"listmonk": {
"url": "http://localhost:3000/mcp"
}
}
}OpenCode
Local (stdio), in opencode.json (project or global config):
{
"mcp": {
"listmonk": {
"type": "local",
"command": ["npx", "-y", "@kieksme/listmonk-mcp", "--stdio"],
"environment": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
},
"enabled": true
}
}
}Remote (HTTP), once the server is running:
{
"mcp": {
"listmonk": {
"type": "remote",
"url": "http://localhost:3000/mcp",
"enabled": true
}
}
}Note on enabled: this flag is OpenCode's own client-side switch — it just turns the whole server connection on/off for that client and has nothing to do with which listmonk tools/categories are exposed. On the remote (HTTP) setup, to limit which tools this particular client sees (without restarting the server or touching LISTMONK_ENABLED_TOOLS), append the tools query parameter to the url itself:
{
"mcp": {
"listmonk": {
"type": "remote",
"url": "http://localhost:3000/mcp?tools=subscribers,campaigns",
"enabled": true
}
}
}On the local (stdio) setup, set LISTMONK_ENABLED_TOOLS in environment instead — see Selecting which tools are available for the full selector syntax.
LM Studio
One-click install (local/stdio, with placeholder credentials you'll need to fill in afterwards in LM Studio's MCP settings):
Or configure it manually, via ~/.lmstudio/mcp.json (Program tab → Install → Edit mcp.json) — local (stdio):
{
"mcpServers": {
"listmonk": {
"command": "npx",
"args": ["-y", "@kieksme/listmonk-mcp", "--stdio"],
"env": {
"LISTMONK_URL": "https://newsletter.example.com",
"LISTMONK_API_USER": "my-api-user",
"LISTMONK_API_TOKEN": "xxxxxxxx"
}
}
}
}Remote (HTTP), once the server is running:
{
"mcpServers": {
"listmonk": {
"url": "http://localhost:3000/mcp"
}
}
}ChatGPT
ChatGPT's Connectors (Settings → Connectors → Create, available on paid plans that support MCP) only accept a publicly reachable HTTP URL — ChatGPT runs in the cloud and can't spawn a local stdio process, so the remote setup is the only option. Deploy the server (see Docker) to a host with a public URL, or tunnel your local instance (e.g. ngrok http 3000), then register https://<your-host>/mcp as the connector URL. If you set MCP_SERVER_AUTH_TOKEN, ChatGPT's connector setup lets you supply a bearer token alongside the URL.
Features
Full API coverage: subscribers, campaigns, lists, templates, media, bounces, import, settings, maintenance, transactional messages, public subscription, logs, admin, and dashboard/misc endpoints.
Selective tool loading — enable only the categories/tools you actually need, so the LLM's context isn't flooded with all 72 tool definitions at once.
Two transports, one package: stdio for a client-spawned local process, stateless Streamable HTTP for a remote deployment (no session state, easy to scale horizontally behind a load balancer).
Optional bearer-token gate in front of
/mcp(HTTP transport only — stdio has no network listener to gate).
Running the server
Local (stdio)
Normally you don't start this by hand — your MCP client spawns it per the config in Connecting your MCP client above. To run it manually (e.g. to sanity-check it outside a client), pass --stdio or set MCP_TRANSPORT=stdio:
LISTMONK_URL=https://newsletter.example.com \
LISTMONK_API_USER=my-api-user \
LISTMONK_API_TOKEN=xxxxxxxx \
npx @kieksme/listmonk-mcp --stdioThe process speaks MCP JSON-RPC on stdout and logs to stderr — it exits when its stdin closes (i.e. when the parent client disconnects). LISTMONK_ENABLED_TOOLS still selects which tools are registered, but there's no per-request override in this mode: one client process, one fixed tool set for its lifetime.
Remote (HTTP)
LISTMONK_URL=https://newsletter.example.com \
LISTMONK_API_USER=my-api-user \
LISTMONK_API_TOKEN=xxxxxxxx \
npx @kieksme/listmonk-mcp
# or
pnpm dlx @kieksme/listmonk-mcpThe MCP endpoint is POST http://localhost:3000/mcp (streamable HTTP, stateless — no session negotiation needed).
Docker
The published image (ghcr.io/kieksme/mcp-listmonk:latest) supports both transports — it's the same entrypoint as npx, so the flags above apply the same way.
Remote (HTTP) — publish the port:
docker run -p 3000:3000 \
-e LISTMONK_URL=https://newsletter.example.com \
-e LISTMONK_API_USER=my-api-user \
-e LISTMONK_API_TOKEN=xxxxxxxx \
-e LISTMONK_ENABLED_TOOLS='["subscribers","campaigns"]' \
ghcr.io/kieksme/mcp-listmonk:latestLocal (stdio) — keep stdin attached (-i) instead of publishing a port; this is what you'd put behind a client's command/args (e.g. docker as the command) if you'd rather run the container than have npx fetch the package:
docker run -i --rm \
-e LISTMONK_URL=https://newsletter.example.com \
-e LISTMONK_API_USER=my-api-user \
-e LISTMONK_API_TOKEN=xxxxxxxx \
ghcr.io/kieksme/mcp-listmonk:latest --stdioConfiguration
Set these environment variables when starting the server:
Variable | Required | Description |
| Yes | Base URL of your Listmonk instance, e.g. |
| Yes | API user name (Listmonk Admin → Users) |
| Yes | API token for that user |
| No |
|
| No | HTTP port to listen on (default |
| No | JSON array (or comma-separated list) of tool/category selectors — see below. Empty/unset = all 72 tools. |
| No | If set, |
Security note: LISTMONK_API_USER/LISTMONK_API_TOKEN authenticate this server to Listmonk, not MCP clients to this server. Without MCP_SERVER_AUTH_TOKEN, anyone who can reach the port gets full Listmonk access at whatever scope the configured API user has. Prefer creating a least-privilege API user in Listmonk scoped only to the categories you intend to enable.
Selecting which tools are available
LISTMONK_ENABLED_TOOLS accepts a JSON array (or comma-separated string) whose entries are, case-insensitively, either:
a category name:
subscribers,campaigns,templates,lists,media,import,bounces,settings,maintenance,public,transactional,logs,admin,miscellaneous— enables every tool in that category, oran exact tool name: e.g.
listmonk_get_subscriber— enables just that one tool.
# Only subscriber management tools
LISTMONK_ENABLED_TOOLS='["subscribers"]'
# A mix of a whole category plus one extra tool
LISTMONK_ENABLED_TOOLS='["campaigns","listmonk_get_health"]'
# Comma-separated form also works
LISTMONK_ENABLED_TOOLS=subscribers,campaignsLeave it unset (or []) to expose all 72 tools.
Per-request override (remote/HTTP only): a single deployed instance can also serve different tool sets to different clients without a restart, via header X-Listmonk-Enabled-Tools or query string ?tools= on the POST /mcp request — same selector syntax as above. This overrides LISTMONK_ENABLED_TOOLS for that one request only. There's no equivalent for the local/stdio transport: each stdio process is spawned fresh per client, so just set LISTMONK_ENABLED_TOOLS in that client's own env/environment config instead.
Since the query string is just part of the URL, this is the easiest way to give one particular client (e.g. one entry in an opencode.json, .mcp.json, or .cursor/mcp.json) a reduced tool set while other clients keep hitting the same server with the full (or a different) set — just set that client's url to http://localhost:3000/mcp?tools=subscribers,campaigns instead of adding server-wide env vars or standing up a second instance. Clients that support custom headers can use X-Listmonk-Enabled-Tools instead, which keeps the URL itself clean.
Tool catalog (72 tools)
subscribers (17)
listmonk_list_subscribers, listmonk_create_subscriber, listmonk_get_subscriber, listmonk_update_subscriber, listmonk_delete_subscriber, listmonk_delete_subscribers_by_ids, listmonk_manage_subscriber_lists_bulk, listmonk_manage_subscriber_list_membership, listmonk_blocklist_subscribers_bulk, listmonk_blocklist_subscriber, listmonk_export_subscriber, listmonk_get_subscriber_bounces, listmonk_delete_subscriber_bounces, listmonk_send_subscriber_optin, listmonk_delete_subscribers_by_query, listmonk_blocklist_subscribers_by_query, listmonk_manage_subscriber_lists_by_query
campaigns (14)
listmonk_list_campaigns, listmonk_create_campaign, listmonk_get_campaign, listmonk_update_campaign, listmonk_delete_campaign, listmonk_get_running_campaign_stats, listmonk_get_campaign_analytics, listmonk_get_campaign_preview, listmonk_preview_campaign_draft, listmonk_preview_campaign_text, listmonk_update_campaign_status, listmonk_update_campaign_archive, listmonk_convert_campaign_content, listmonk_send_campaign_test
templates (8)
listmonk_list_templates, listmonk_create_template, listmonk_get_template, listmonk_update_template, listmonk_delete_template, listmonk_preview_template_draft, listmonk_preview_template, listmonk_set_default_template
lists (5)
listmonk_list_lists, listmonk_create_list, listmonk_get_list, listmonk_update_list, listmonk_delete_list
media (4)
listmonk_list_media, listmonk_upload_media, listmonk_get_media, listmonk_delete_media
import (4)
listmonk_get_import_status, listmonk_import_subscribers, listmonk_stop_import_subscribers, listmonk_get_import_logs
bounces (4)
listmonk_list_bounces, listmonk_delete_bounces, listmonk_get_bounce, listmonk_delete_bounce
settings (3)
listmonk_get_settings, listmonk_update_settings, listmonk_test_smtp_settings
maintenance (3)
listmonk_delete_gc_subscribers, listmonk_delete_gc_campaign_analytics, listmonk_delete_unconfirmed_subscriptions
public (2)
listmonk_get_public_lists, listmonk_create_public_subscription
transactional (1)
listmonk_send_transactional_message
logs (1)
listmonk_get_logs
admin (1)
listmonk_reload_app
miscellaneous (5)
listmonk_get_health, listmonk_get_server_config, listmonk_get_i18n_lang, listmonk_get_dashboard_charts, listmonk_get_dashboard_counts
Notes on a few non-obvious tools
Bulk/query subscriber operations (
listmonk_delete_subscribers_by_query,listmonk_blocklist_subscribers_by_query,listmonk_manage_subscriber_lists_by_query) run against a Listmonk SQL filter expression and act on every matching subscriber with no preview step. Always calllistmonk_list_subscriberswith the samequeryfirst to check the match count.Campaign preview/content tools are intentionally split into four distinct tools because Listmonk exposes four distinct endpoints for them:
listmonk_get_campaign_previewrenders the campaign as currently saved;listmonk_preview_campaign_draftandlistmonk_preview_campaign_textrender an unsaved body without persisting anything;listmonk_convert_campaign_contentperforms and persists a format conversion (e.g. markdown → HTML) — it's not a preview despite the similar area.listmonk_send_campaign_testfetches the campaign's current saved state first and only overrides the fields you explicitly pass, to avoid accidentally blanking out fields Listmonk's own API would otherwise silently overwrite with empty values.
Contributing
Want to build from source, run the test suite, or understand the release process? See CONTRIBUTING.md.
License
MIT © kieksme GbR
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.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server implementation that enables AI assistants to interact with Listmonk instances, providing programmatic access to newsletter and mailing list management functionality including subscriber, list, and campaign operations.36MIT
- FlicenseDqualityAmaintenanceEnables AI agents to manage Listmonk email campaigns, subscribers, lists, and analytics through typed MCP tools with production safety features.371
- FlicenseCqualityDmaintenanceComprehensive MCP server for Mailchimp Marketing API v3.0 with over 104 tools and 15+ React UI apps, enabling management of campaigns, audiences, ecommerce, automations, reports, and more via natural language.1001
- AlicenseDqualityAmaintenanceExposes every endpoint of the Mealie REST API as MCP tools, enabling LLMs to manage recipes, meal plans, shopping lists, and more.2112,0872MIT
Related MCP Connectors
Free public MCP for AI agents — 193 tools, 44 workflows. No API key.
LeadConnector / GoHighLevel MCP Pack — wraps the GoHighLevel CRM for AI agents.
Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.
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/kieksme/mcp-listmonk'
If you have feedback or need assistance with the MCP directory API, please join our Discord server