Skip to main content
Automation August 5, 2026 · 11 min read

How to Connect Listmonk to Any Tool via MCP

Connect Listmonk to Claude Desktop, VS Code, and Cursor via MCP in 15 minutes. Full setup with uvx, API tokens, health checks, and 18 ready-to-use MCP tools.

Edward Chalupa

Edward Chalupa

Founder, Whtnxt · Dallas, TX

How to Connect Listmonk to Any Tool via MCP

I ran Listmonk in production for six months and 43 campaigns before I connected it to an AI assistant. The manual path worked: log in, click through subscribers, build a campaign, paste the template, schedule the send. Each one cost me 12 to 18 minutes of clicking. The n8n pipeline I built cut that to zero, but it still had a gap. When someone asked “how many subscribers are on the Houston list?” or “add these 5 emails to the onboarding flow,” I either opened the dashboard or edited a workflow. There was no middle ground.

The Model Context Protocol (MCP) server for Listmonk closes that gap. One config block in Claude Desktop, VS Code, or Cursor, and the assistant can check health, add subscribers, create lists, pull campaigns, and manage templates with plain language. No dashboard clicks, no workflow edits for one-off asks. I tested this across my own Listmonk instance and it works. Here is exactly how I set it up, including the two pitfalls that cost me 20 minutes each.

What You’re Building

An MCP server that bridges an AI assistant to the Listmonk REST API. The server is a small Python process that exposes Listmonk operations as 18 MCP tools. Your assistant talks to those tools over the MCP protocol, and the tools call Listmonk on your behalf using an API token.

Listmonk MCP Architecture

The architecture is three layers: your assistant (Claude Desktop, VS Code, Cursor, Windsurf), the listmonk-mcp server running locally, and your Listmonk instance with its API and Postgres database. The assistant never touches your database directly, and Listmonk never sees your assistant. The MCP server is the only authenticated bridge.

Info: MCP is the open standard Anthropic released in late 2024 for connecting assistants to external tools and data, documented at modelcontextprotocol.io{target=“_blank”}. If you need the broader picture before diving in, I wrote a full breakdown in MCP Servers for Marketers. This post is the practical setup.

What You’ll Need

RequirementDetails
Listmonk instanceRunning v3.0+, with API access enabled
Python3.11+ (the MCP server requires it)
uv or uvxThe recommended installer, or use pip
API user and tokenCreated in Listmonk Admin > Users
MCP-capable clientClaude Desktop, VS Code, Cursor, or Windsurf
15 minutesTotal setup time, once Listmonk is running

If you do not have Listmonk running yet, the official Listmonk repo{target=“_blank”} has a one-command Docker Compose setup. I cover the full self-hosted stack in Automate Listmonk Campaigns with n8n and the email-specific build in Automated Email Marketing with n8n and Listmonk. Both assume you can get a Listmonk instance up on a $6 VPS.

Step 1: Run Listmonk (If You Do Not Have It)

For a local test, the project ships a Docker Compose file. From the repo directory:

docker compose -f docs/listmonk-docker-compose.yml up -d

Or pull the official compose file directly:

curl -LO https://github.com/knadh/listmonk/raw/master/docker-compose.yml
docker compose up -d

Listmonk comes up on port 9000. Default credentials are admin / listmonk. You will be forced to change the admin password on first login. The database (Postgres) runs in a second container, so the full stack is two containers.

Tip: If you already run Listmonk in production, skip this step entirely. The MCP server works against any reachable Listmonk instance, local or remote. Mine runs on a $15 Digital Ocean droplet alongside n8n, and the MCP server connects to it over the network.

Step 2: Create the API User and Token

The MCP server does not use your admin login password. It uses a dedicated API user with a generated token. This is the single most important detail in this post, and the README is explicit about it.

  1. Log into the Listmonk admin interface at http://localhost:9000/admin
  2. Go to Admin > Users
  3. Click “Add new” and create a user, for example api-user
  4. Save the user, then click into it
  5. Click “Generate API token” and copy the token

The token is a long string. Treat it like a password. Listmonk expects it in the Authorization: token <username>:<token> format, which the MCP server builds for you.

Listmonk MCP Setup Flow

Warning: The LISTMONK_MCP_PASSWORD environment variable holds the API token, NOT the user’s login password. If you put your login password there, every call fails with “invalid session” or a 403. I burned 20 minutes on exactly this on my first setup because the variable name says password.

Step 3: Set the Environment Variables

The MCP server reads three required variables plus a few optional ones:

export LISTMONK_MCP_URL=http://localhost:9000
export LISTMONK_MCP_USERNAME=api-user
export LISTMONK_MCP_PASSWORD=your-generated-api-token

Optional settings:

export LISTMONK_MCP_TIMEOUT=30
export LISTMONK_MCP_MAX_RETRIES=3
export LISTMONK_MCP_LOG_LEVEL=INFO
VariablePurposeDefault
LISTMONK_MCP_URLYour Listmonk server URLrequired
LISTMONK_MCP_USERNAMEAPI user created in Admin > Usersrequired
LISTMONK_MCP_PASSWORDAPI token, not the login passwordrequired
LISTMONK_MCP_TIMEOUTRequest timeout in seconds30
LISTMONK_MCP_MAX_RETRIESRetry count for failed calls3

Verify the credentials work before you wire up the assistant. The server uses the same token auth as Listmonk’s API, so a curl health check tells you everything:

curl -H "Authorization: token api-user:your-generated-api-token" \
  http://localhost:9000/api/health

A 200 with {"data": true} means the URL, user, and token are all correct. A 401 means the token is wrong. A connection refused means Listmonk is not running or you have the wrong port. I spent another 20 minutes on a port mismatch when Listmonk was bound to 9000 in Docker but I was hitting 8080.

Info: If you prefer an all-in-one deployment, the project also ships a Docker setup (documented in the Listmonk MCP docs{target=“_blank”}) that runs the MCP server as a container next to Listmonk. I use the local process approach because I want the assistant on my laptop talking to a remote server.

Step 4: Install and Run the MCP Server

The server is published to PyPI as listmonk-mcp{target=“_blank”}. The recommended install uses uvx, which downloads and runs it without polluting your Python environment:

# Run directly (installs if needed)
uvx listmonk-mcp --help

# Or install globally
uvx install listmonk-mcp
listmonk-mcp --help

If you prefer pip:

pip install listmonk-mcp

You can verify the server starts and prints its version:

listmonk-mcp --version

Warning: If uvx is not on your PATH, install uv first with pip install uv, or use the pip route. On my Ubuntu box, a fresh shell did not see uvx until I added the uv binary directory to PATH.

Step 5: Connect Claude Desktop

Claude Desktop is the fastest client to test with because it reloads MCP servers on restart. Edit your config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Add the server block:

{
  "mcpServers": {
    "listmonk": {
      "command": "uvx",
      "args": ["listmonk-mcp"],
      "env": {
        "LISTMONK_MCP_URL": "http://localhost:9000",
        "LISTMONK_MCP_USERNAME": "api-user",
        "LISTMONK_MCP_PASSWORD": "your-generated-api-token"
      }
    }
  }
}

Restart Claude Desktop completely, not just the window. In the chat, ask something simple:

“Check the Listmonk server health.”

If the server connected, you will see the listmonk tools available (the tools icon or the hammer-and-wrench indicator in the UI), and Claude will call check_listmonk_health and report the result. If you see “no MCP tools found,” the config JSON has a syntax error or the server failed to start. Check the env values first.

This is the same pattern I used for Postiz MCP with Claude Desktop, and it is the fastest way to test any MCP server: one JSON block, restart, ask.

Step 6: Connect VS Code, Cursor, and Windsurf

VS Code uses the same server, configured in user settings rather than a separate file. Add to ~/.config/Code/User/settings.json:

{
  "mcp": {
    "servers": {
      "listmonk": {
        "command": "uvx",
        "args": ["listmonk-mcp"],
        "env": {
          "LISTMONK_MCP_URL": "http://localhost:9000",
          "LISTMONK_MCP_USERNAME": "api-user",
          "LISTMONK_MCP_PASSWORD": "your-generated-api-token"
        }
      }
    }
  }
}

Reload the VS Code window (Command Palette > Developer: Reload Window), then open the MCP panel to confirm the server shows as running. Cursor and Windsurf follow the same shape with their own settings files, and Cline has a dedicated config page in the MCP server docs{target=“_blank”}.

Tip: One server, four clients. You do not install separate MCP servers per tool. The same uvx listmonk-mcp process serves any MCP-capable client, so once the env vars are right, the JSON block is copy-paste.

Step 7: Do Something Real

The server exposes 18 tools. The ones I use weekly: check_listmonk_health, add_subscriber, update_subscriber, list_subscribers, get_mailing_lists, create_mailing_list, get_campaigns, and the template tools. Here is what a real session looks like.

Add a subscriber:

“Add jane@example.com to the newsletter list.”

The assistant calls add_subscriber with the email and list ID, Listmonk writes the row to Postgres, and the assistant confirms. The whole exchange takes seconds.

Adding a Subscriber Through MCP

Pull a campaign list:

“What campaigns went out in the last 30 days and what were their click rates?”

The assistant calls get_campaigns, reads the stats from the JSON, and summarizes. This replaced the dashboard tab I used to keep open, and it feeds the same data I otherwise push into the Listmonk analytics dashboard. When you need the same visibility across every channel, not just email, the marketing analytics dashboards I build for clients pull Listmonk, n8n, and ad platforms into one view.

Create a list:

“Create a list called ‘Q3 leads’ with the tag ‘organic’.”

That maps to create_mailing_list, and the new list is ready for imports immediately. For bulk subscriber imports from a CSV or a CRM export, I still reach for the n8n pipeline in Automate Listmonk Campaigns with n8n, because scheduled, repeatable imports belong in a workflow, not in a chat. For one-off adds, fixes, and reports, MCP is faster than both the dashboard and n8n. If you are turning raw inbound leads into subscribers, this is the subscriber side of a lead generation system: capture, clean, route, and nurture on one self-hosted stack.

The Pitfalls I Hit

Three problems cost me real time, and all three are documented here so you skip them.

  1. API token vs login password. The LISTMONK_MCP_PASSWORD variable takes the generated API token, not the user’s login password. Wrong value, every call returns “invalid session” or 403. Verify with the curl health check in Step 3 before touching client config.
  2. Port mismatch. Listmonk in Docker listens on 9000, but my first compose file mapped it to 8080 on the host. The MCP server connected to nothing and the error said connection refused. Check docker ps for the actual host port mapping, then set LISTMONK_MCP_URL to match.
  3. Client restart is mandatory. Editing the Claude Desktop config JSON does nothing until the app fully restarts. On Linux, I had to quit the process entirely; a window close was not enough. Same for VS Code: use Developer: Reload Window, not a tab reload.

When to Use This (And When Not To)

Use the MCP server when you need conversational access to Listmonk: ad-hoc subscriber adds, list lookups, campaign checks, template edits, and answers to “what is the state of our email program” questions. It is also the right choice when you want an assistant to act on your Listmonk data as part of a larger agent workflow, because the 18 tools give the assistant real operations, not just read access.

Do not use it as your primary automation engine. Scheduled campaign sends, bulk imports of thousands of subscribers, deduplication runs, and anything that must fire at 6 AM on a timer belong in n8n. My marketing automation engine handles the scheduled layer, and the MCP server handles the interactive layer. They complement each other: n8n runs the pipeline, MCP answers the questions about it.

Warning: The MCP server gets write access to your Listmonk data. Give the API user the minimum role your workflow needs, and never put the MCP config in a shared repo with real tokens. Use a .env file or your client’s secret storage. This is production email infrastructure, not a toy.

What’s Next

The natural next step is to point the same assistant at your campaign analytics and let it explain performance instead of just listing it. I built a Listmonk campaign analytics dashboard with n8n that tracks the same data, and pairing the dashboard with the MCP tools gives you both the scheduled report and the on-demand answers.

If you want the full picture of where MCP fits in a marketing stack, start with MCP Servers for Marketers, then come back here and wire up your own Listmonk instance. If your email program needs the scheduled automation layer too, I have written up the exact n8n setup in Automate Listmonk Campaigns with n8n. When you want this built for your business, including custom MCP servers and marketing automation services, get in touch and I will show you what the stack looks like for your email program.

listmonkmcpmodel context protocolclaude desktopemail automationself-hostedapitutorial
Share: