AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Postmark Mcp

mcp-activecampaign-postmark-mcp · by ActiveCampaign

Official Postmark MCP server by ActiveCampaign — 24 tools to send, template, search, and diagnose transactional email from Claude, Cursor & other AI assistants.

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add mcp-activecampaign-postmark-mcp

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-activecampaign-postmark-mcp)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Postmark Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Official Postmark MCP Server   [](https://www.npmjs.com/package/@activecampaign/postmark-mcp)  

Send emails with Postmark using Claude and other MCP-compatible AI assistants.

Features

  • Exposes a Model Context Protocol (MCP) server backed by your Postmark account
  • 24 tools spanning email sending (single + batch), templates (CRUD + validation), message search, delivery diagnostics, bounces, suppressions, stats, server info, and webhooks
  • MCP tool annotations (readOnlyHint, destructiveHint) let supporting clients auto-approve safe reads and require confirmation before mutating or destructive operations
  • Simple configuration via environment variables
  • Comprehensive error handling and graceful shutdown
  • Structured JSON logging to stderr with optional log-file persistence; email addresses are partially masked by default
  • HTTPS enforcement and optional domain allowlist for webhook registration
  • Automatic open/click tracking on every send

Useful Docs

Feedback

We'd love to hear from you! Please share your feedback and suggestions using our feedback form.

Follow us on X - @postmarkapp


Setup

Requirements

Installation (Local Development)

Clone the repository:

git clone https://github.com/ActiveCampaign/postmark-mcp
cd postmark-mcp

Install dependencies:

npm install
# or
yarn
# or
bun install

Configuration (Local Development)

Create your own environment file from the example

cp .env.example .env

Edit your .env to contain your Postmark credentials and settings.

Important: This is intended for local development purposes only. Secrets should never be stored in version control and .env type files should be added to .gitignore.

Required

| Variable | Description | |---|---| | POSTMARK_SERVER_TOKEN | Your Postmark server API token | | DEFAULT_SENDER_EMAIL | Default sender email address (must be a verified sender in Postmark) | | DEFAULT_MESSAGE_STREAM | Postmark message stream (e.g., outbound) |

Optional

| Variable | Default | Description | |---|---|---| | AGENT_LABEL | — | A label for this instance (e.g., prod, staging). Sent as X-Agent-Label on every Postmark API request, useful for identifying traffic sources in logs or support tickets. | | WEBHOOK_URL_ALLOWLIST | — | Comma-separated list of HTTPS URL prefixes that createWebhook will accept (e.g., https://hooks.yourapp.com,https://inbound.corp.io). When unset, any valid HTTPS URL is accepted. | | LOG_FILE | — | Path to a file where structured JSON logs are appended in addition to stderr. The file is created if it does not exist. No rotation or size cap is applied — use an external tool such as logrotate to manage the file in long-running deployments. | | LOG_EMAIL_FULL | false | Set to true to log email addresses without masking. By default the mailbox portion is partially masked in logs (u**r@example.com). |

Run the server:

npm start
# or
yarn start
# or
bun start

Smoke test (requires valid .env):

The repo ships two smoke-test example files. Copy each to its non-example name (which is gitignored) before running, so your local edits — including any verified-sender addresses — never end up committed.

# Read-only suite (25 checks). Optionally edit RECIPIENT_WITH_HISTORY.
cp smoke-test.example.mjs smoke-test.mjs
npm run smoke

# Mutating suite (full lifecycles + real email sends).
# REQUIRED: edit SENDER and RECIPIENT to two of your verified addresses.
cp smoke-test-mutating.example.mjs smoke-test-mutating.mjs
node smoke-test-mutating.mjs

The read-only suite spawns the server over stdio and exercises every read tool against your Postmark account, plus the validation paths for editTemplate and createWebhook. Does not send mail or mutate state.

The mutating suite runs full create→edit→delete lifecycles for templates (including layout binding), webhooks, and suppressions, and sends real emails between the two addresses you configure. It cleans up after itself. The script refuses to run while the placeholder values are still in place.

Cursor Quick Install

After installing the MCP, update your configuration to set:

  • POSTMARK_SERVER_TOKEN
  • DEFAULT_SENDER_EMAIL
  • DEFAULT_MESSAGE_STREAM (default: outbound)

MCP Client Configuration

Using npx (recommended — no clone required)

Install directly from npm without managing a local copy:

{
  "mcpServers": {
    "postmark": {
      "command": "npx",
      "args": ["-y", "@activecampaign/postmark-mcp"],
      "env": {
        "POSTMARK_SERVER_TOKEN": "your-postmark-server-token",
        "DEFAULT_SENDER_EMAIL": "your-sender-email@example.com",
        "DEFAULT_MESSAGE_STREAM": "outbound"
      }
    }
  }
}

Using a local clone

{
  "mcpServers": {
    "postmark": {
      "command": "node",
      "args": ["/absolute/path/to/postmark-mcp/index.js"],
      "env": {
        "POSTMARK_SERVER_TOKEN": "your-postmark-server-token",
        "DEFAULT_SENDER_EMAIL": "your-sender-email@example.com",
        "DEFAULT_MESSAGE_STREAM": "outbound"
      }
    }
  }
}

Both snippets work with Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json), Cursor (.cursor/mcp.json), and any other MCP client that accepts the standard JSON configuration format.

Tools

This section provides a complete reference for the Postmark MCP server tools including example prompts and payloads. The server registers 24 tools organized into eight categories.

Table of Contents

  • [Email](#email)
  • [sendEmail](#sendemail)
  • [sendEmailWithTemplate](#sendemailwithtemplate)
  • [sendBatch](#sendbatch)
  • [sendBatchWithTemplate](#sendbatchwithtemplate)
  • [Templates](#templates)
  • [listTemplates](#listtemplates)
  • [getTemplate](#gettemplate)
  • [createTemplate](#createtemplate)
  • [editTemplate](#edittemplate)
  • [deleteTemplate](#deletetemplate)
  • [validateTemplate](#validatetemplate)
  • [Messages](#messages)
  • [searchOutboundMessages](#searchoutboundmessages)
  • [getMessageDetails](#getmessagedetails)
  • [Diagnostics](#diagnostics)
  • [diagnoseDelivery](#diagnosedelivery)
  • [Bounces](#bounces)
  • [searchBounces](#searchbounces)
  • [getBounceDump](#getbouncedump)
  • [activateBounce](#activatebounce)
  • [Suppressions](#suppressions)
  • [listSuppressions](#listsuppressions)
  • [createSuppressions](#createsuppressions)
  • [deleteSuppressions](#deletesuppressions)
  • [Stats & Server](#stats--server)
  • [getDeliveryStats](#getdeliverystats)
  • [getServerInfo](#getserverinfo)
  • [Webhooks](#webhooks)
  • [listWebhooks](#listwebhooks)
  • [createWebhook](#createwebhook)
  • [deleteWebhook](#deletewebhook)

Email

sendEmail

Sends a transactional email to one recipient or up to 50 recipients.

Example Prompt:

Send an email using Postmark to recipient@example.com with the subject "Meeting Reminder" and the message "Don't forget our team meeting tomorrow at 2 PM."

Expected Payload:

{
  "to": "recipient@example.com",
  "subject": "Meeting Reminder",
  "textBody": "Don't forget our team meeting tomorrow at 2 PM.",
  "htmlBody": "Don't forget our team meeting tomorrow at 2 PM.",
  "from": "sender@example.com",
  "cc": "manager@example.com",
  "bcc": "archive@example.com",
  "replyTo": "support@example.com",
  "tag": "meetings"
}

to accepts a single address or an array of up to 50 addresses. htmlBody, from, cc, bcc, replyTo, and tag are optional. If from is omitted, DEFAULT_SENDER_EMAIL is used.

Response:

Email sent successfully!
MessageID: 0a1b2c3d-...
To: recipient@example.com
Subject: Meeting Reminder

sendEmailWithTemplate

Sends an email using a Postmark template.

Example Prompt:

Send the "welcome" template to customer@example.com with name "John Doe" and login_url "https://myapp.com/login".

Expected Payload:

{
  "to": "customer@example.com",
  "templateAlias": "welcome",
  "templateModel": {
    "name": "John Doe",
    "login_url": "https://myapp.com/login"
  },
  "from": "sender@example.com",
  "tag": "onboarding"
}

Provide either templateId (number) or templateAlias (string), not both.

Response:

Template email sent successfully!
MessageID: 0a1b2c3d-...
To: customer@example.com
Template: welcome

sendBatch

Sends up to 500 emails in a single API call. Each message is fully independent — its own recipient, subject, and body. This wraps Postmark's synchronous batch endpoint (POST /email/batch), which returns immediate per-message results.

> Note: Postmark also offers an asynchronous bulk email API (POST /email/bulk) for large-volume jobs with no message-count cap and a 50 MB payload limit. That endpoint uses a submit-and-poll workflow and is not currently wrapped by this MCP server.

Expected Payload:

{
  "messages": [
    {
      "to": "alice@example.com",
      "subject": "Order #1234 confirmed",
      "textBody": "Thanks Alice — your order is on its way.",
      "tag": "order-confirmation"
    },
    {
      "to": "bob@example.com",
      "subject": "Order #1235 confirmed",
      "textBody": "Thanks Bob — your order is on its way.",
      "tag": "order-confirmation"
    }
  ]
}

Per-message fields: to, subject, textBody are required. htmlBody, from, cc, bcc, replyTo, and tag are optional. If from is omitted on a message, DEFAULT_SENDER_EMAIL is used.

Response:

Sent 2/2 successfully

Successes:
  - alice@example.com — abc-123-def
  - bob@example.com — abc-456-ghi

When some messages fail at submission (e.g., suppressed recipients), failures are listed first with their ErrorCode and reason:

Sent 8/10 successfully (2 failed)

Failures:
  - blocked@example.com — 406: Address has been suppressed.
  - bad@example.com — 300: Inactive recipient
...

sendBatchWithTemplate

Sends up to 500 templated emails — same template, per-recipient template models. Ideal for "render this onboarding template for each new user" flows.

Expected Payload:

{
  "templateAlias": "welcome",
  "from": "hello@yourapp.com",
  "tag": "onboarding",
  "recipients": [
    { "to": "alice@example.com", "templateModel": { "name": "Alice", "plan": "Pro" } },
    { "to": "bob@example.com", "templateModel": { "name": "Bob", "plan": "Free" } }
  ]
}

Provide either templateId (number) or templateAlias (string). Top-level from and tag apply to all recipients but can be overridden per-recipient. Each recipient also accepts optional cc, bcc, and replyTo.

Response: same format as sendBatch.


Templates

listTemplates

Lists saved templates on this server. Returns the first 100 templates; if a server has more than 100, pagination is not yet supported and the response will indicate that results are truncated.

Response:

Found 2 templates:

• **Welcome**
  - ID: 12345678
  - Alias: welcome
  - Subject: Welcome to {{product_name}}

getTemplate

Retrieves a single template's full content (HTML body, text body, subject, type).

Payload: { "templateIdOrAlias": "welcome" } — accepts numeric ID or string alias.

createTemplate

Creates a new template. Requires name. At least one of htmlBody or textBody must be provided.

subject is required for Standard templates and must be omitted for Layout templates — Postmark rejects the field on Layouts.

layoutTemplate (Standard only) binds the new template to an existing Layout by alias. Without it, the new template renders unwrapped (no chrome from any layout).

Expected Payload:

{
  "name": "Order Confirmation",
  "subject": "Your order #{{order_id}} is confirmed",
  "htmlBody": "Thanks {{name}}",
  "textBody": "Thanks {{name}}",
  "alias": "order-confirmation",
  "templateType": "Standard",
  "layoutTemplate": "basic"
}

templateType may be "Standard" (default) or "Layout".

editTemplate

Updates an existing template. Requires templateIdOrAlias plus at least one updated field (name, subject, htmlBody, textBody, alias, or layoutTemplate).

Pass "layoutTemplate": null to unbind a template from its current Layout (the MCP translates this to the empty-string the Postmark API requires for clearing the association).

deleteTemplate

Permanently deletes a template by ID or alias. Layout templates cannot be deleted while Standard templates are still bound to them — unbind via editTemplate first.

Payload: { "templateIdOrAlias": "order-confirmation" }

validateTemplate

Validates template content (Mustachio syntax, undefined variables) without saving. At least one of subject, htmlBody, or textBody is required.

Expected Payload:

{
  "subject": "Order #{{order_id}}",
  "htmlBody": "Thanks {{name}}",
  "textBody": "Thanks {{name}}",
  "testRenderModel": { "order_id": 42, "name": "John" },
  "templateType": "Standard"
}

Messages

searchOutboundMessages

Searches the outbound message history.

Expected Payload (all filters optional):

{
  "recipient": "user@example.com",
  "fromEmail": "sender@example.com",
  "tag": "marketing",
  "subject": "Welcome",
  "status": "sent",
  "messageStream": "outbound",
  "fromDate": "2025-05-01",
  "toDate": "2025-05-15",
  "count": 50,
  "offset": 0
}

status is one of queued, sent, processed. count is 1–500 (default 50).

getMessageDetails

Retrieves full details and event timeline for a single outbound message.

Payload: { "messageId": "0a1b2c3d-..." }


Diagnostics

diagnoseDelivery

Composite triage tool. Answers "did my email reach X, and if not, why?" by running message search, suppression check, and bounce history lookups in parallel against a recipient address, then synthesizing a plain-English recommendation.

This is a diagnostic tool: it composes multiple Postmark API calls into a single coherent answer rather than mirroring a single endpoint.

Example Prompt:

Did my email to recipient@example.com get delivered? If not, what should I do?

Expected Payload:

{
  "recipient": "recipient@example.com",
  "messageId": "0a1b2c3d-...",
  "fromDate": "2026-04-21",
  "toDate": "2026-04-28",
  "messageStream": "outbound"
}

All fields except recipient are optional. If messageId is omitted, the most recent message to the recipient is used. The default search window is the last 7 days.

Sample response:

Delivery Diagnosis: recipient@example.com
────────────────────────────────────────────────

Suppression: not suppressed on stream "outbound"

Most recent message:
  MessageID: fadeae4e-fb04-4102-9303-9876078c7b81
  Subject:   Welcome to MyApp
  Sent:      2026-04-27T18:42:19.0000000-04:00
  Status:    Sent
  Events:    Delivered, Opened×2, Clicked

Bounce history: none

Recommended action:
  Email was delivered. If recipient says they didn't see it, check their
  spam folder or ask them to whitelist the sender domain.

When the recipient is suppressed, the recommendation differs based on reason: SpamComplaint is permanent, HardBounce may be reactivatable, ManualSuppression can be deleted via deleteSuppressions.


Bounces

searchBounces

Searches the bounce log with optional filters by type, recipient, tag, message ID, messag

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.