
Your agent needs to send transactional email, then answer the question every support thread eventually asks: did it actually arrive, and if not, why. Postmark ships an official MCP server and a REST API that has been stable for years. They cover overlapping but not identical ground, and unlike Notion or Slack, the choice between them does not change your auth model at all. That last part is the interesting bit, and it is where most teams get the architecture wrong. Here is the decision framework.
Two objects, one credential model. Establishing both precisely matters, because the differences show up in capability coverage and deployment shape, not in authentication.
The Postmark MCP server is maintained by ActiveCampaign and published to npm as @activecampaign/postmark-mcp. It started in Postmark Labs with four tools and reached v2.1.1 with 24 tools across eight categories in July 2026. Node.js v20 or higher is required.
You run it as a local process. The documented configuration is npx -y @activecampaign/postmark-mcp in your MCP client config, with POSTMARK_SERVER_TOKEN, DEFAULT_SENDER_EMAIL, and DEFAULT_MESSAGE_STREAM supplied as environment variables. Every tool carries readOnlyHint, destructiveHint, and idempotentHint annotations so a client can auto-approve reads and gate sends. The source is on the official postmark-mcp repository.
The Postmark REST API is a JSON API over HTTPS at api.postmarkapp.com, organized into fifteen endpoint groups: Email, Bulk, Bounce, Templates, Server, Servers, Message Streams, Messages, Domains, Sender signatures, Stats, Inbound rule triggers, Webhooks, Suppressions, and Data Removal.
Authentication is header based. Server-level operations use X-Postmark-Server-Token; account-level operations such as creating servers or managing domains use X-Postmark-Account-Token. There are no LLM affordances here: schema handling, pagination, per-message error inspection, and retry logic are all yours.
For most tools in this series, the MCP server introduces an OAuth path that the API did not require. Postmark does not work that way. Both paths use the same two static tokens, which means the MCP decision is purely about capability surface and deployment shape. That simplifies one thing and complicates another, as the next section shows.
Four dimensions decide this: what the agent can do, how it authenticates, what breaks in production, and which workloads each path actually suits.
The MCP server covers the outbound sending and deliverability loop well. Everything that touches account configuration, inbound mail, or stream topology lives only in the API.
Two of those gaps are architectural rather than temporary. Inbound email is an entire half of Postmark's product with its own message search, processing statuses, retry semantics, and blocking rules; none of it is reachable through MCP. Message stream management is the other: a server holds up to 10 streams, and creating, archiving, or reconfiguring one is an API-only operation.
The Bulk API gap is worth calling out separately. sendBatch sends up to 500 distinct messages. The Bulk API sends one message body to a large recipient list with per-recipient template variables, using a submit-and-poll workflow. The MCP server does not wrap it.
diagnoseDelivery is genuinely better than what the API gives you. Answering "did this reach the recipient" through the raw API means a message search, a message detail lookup, a suppression check, and a bounce query, then reconciling four payloads. The MCP tool runs those in parallel, tolerates individual failures, and returns a recommended action that varies by suppression reason: SpamComplaint is permanent, HardBounce may be reactivatable, ManualSuppression can simply be deleted.
That is outcome-shaped tool design, not endpoint wrapping. If your agent's job is deliverability triage, it is a real reason to reach for the MCP path.
Neither path involves OAuth, browser consent, refresh tokens, or per-user delegation. Postmark's API authentication model defines exactly two credentials, both sent as HTTP headers, both long lived, and neither sub-scopable.
A Server Token authorizes every operation on one Postmark server: sends, template deletion, webhook registration, suppression edits. An Account Token authorizes account-level operations across servers. The official repo is explicit that neither type supports narrower permissions, and recommends a structural workaround: create a dedicated Postmark server used only for agent traffic, so a compromise is bounded to that server's data.
This is the point that determines your production posture. A Postmark credential does not represent a person. It represents a sending server. So the identity question for a Postmark agent is not "which user authorized this," it is "which tenant's sending infrastructure is this agent currently acting on."
For a single-product team sending its own mail, one token is fine. For an agency, a platform, or any B2B product where each customer brings their own Postmark server, you have N long-lived full-access secrets to hold. That shape is closer to multi-tenant access control than to user-delegated OAuth.
On the MCP path, ActiveCampaign owns the tool schemas, the validation rules, and the composite diagnostics. You own the process. Because the server is a local stdio binary keyed to one POSTMARK_SERVER_TOKEN, serving multiple tenants means running one subprocess per tenant with a distinct environment, or swapping the env var between runs. Neither pattern survives concurrency.
You also own the log surface. The server emits structured JSON per tool invocation to stderr, with email addresses partially masked unless LOG_EMAIL_FULL is set, and an optional LOG_FILE that has no rotation or size cap.
On the API path you own everything, including three behaviors that catch agents specifically.
Postmark returns HTTP 429 when request rate exceeds acceptable use, without publishing a fixed per-endpoint tier table, so your backoff has to be adaptive rather than pre-tuned. Payload limits are hard: 10 MB for the Email API, 50 MB total for the Batch API, surfaced as HTTP 413.
The batch semantic is the one that silently breaks pipelines. Batch sends return per-message error codes inside an HTTP 200 response. An agent that checks only the status code will report success on a batch where a third of the recipients were rejected as inactive.
Reach for the MCP server when a human is in the loop and the Postmark account is yours.
Reach for the API when the agent runs without a human and without a fixed account.
Both paths hand your agent a static secret and stop. Neither gives you a vault, a rotation schedule, or a revocation flow. For a Postmark agent that problem has a different shape than for an OAuth tool, and the difference matters.
Run one agent across 200 customer Postmark servers and you are holding 200 long-lived tokens, each granting full send, template delete, webhook create, and suppression edit rights on its server. There is no scope you can trim. A leak of the store is a leak of every tenant's sending identity at once.
That is a large blast radius for a credential that usually ends up in an environment variable or a config row.
OAuth agents fail at refresh. Postmark agents fail at rotation. A server token does not expire on its own, so nothing forces the question; the token from the integration you shipped fourteen months ago is still valid, still full access, and still in whatever store you first put it in.
Rotation is manual: mint a new token in the Postmark dashboard, update every runtime holding the old one, then revoke. Doing that across N tenants without downtime is infrastructure work, and it is the same work whether you chose MCP or the API. For a deeper look at secure token management for AI agents at scale, the patterns apply directly here.
The Scalekit Postmark connector registers each tenant's Server API token once, stores it in an encrypted token vault, and resolves the correct one on every tool call by identifier. Credentials never enter the agent runtime or the model context.
It exposes 59 tools, which covers the inbound, message stream, webhook update, and Bulk API surface the official MCP server omits. Because tokens are scoped per server, you create one Scalekit connection per Postmark server token, which is also how you get tenant isolation for free.
Setup is once per environment. Everything after that is tool calls keyed by an identifier you choose.
Copy the Server API token from the API Tokens tab of the Postmark server you want to connect. In the Scalekit dashboard, go to AgentKit, then Connections, then Create Connection, find Postmark, paste the token, and save.
The connection name you pick in the dashboard is the string you pass in code. It must match exactly. This is the single most common integration error, and it fails as a not-found rather than an auth error, which sends people looking in the wrong place.
Before the agent loop runs, the agent loads the tools bound to this identifier's connected account, not a flat catalog of every Postmark action Scalekit knows about. For a Postmark agent the identifier is usually a tenant key rather than an end user, because the credential represents a sending server.
list_scoped_tools returns those definitions with input_schema already in Anthropic's tool-use format, so no conversion step is needed.
The loop below is a deliverability triage agent: it searches the tenant's outbound history, inspects bounces, and checks the suppression list before recommending an action. execute_tool resolves the tenant's Postmark token at call time.
The connector uses a postmark_ prefix and mirrors Postmark's own resource names. The ones a triage agent converges on:
Full input schemas live on the Postmark connector docs page.
The Node SDK mirrors the Python shape. listScopedTools returns the same definitions; executeTool takes connector where Python takes connection_name.
Scalekit returns native StructuredTool objects, so there is no schema reshaping between the connector and the agent. For more on how LangChain tool calling works and where it needs additional infrastructure, see LangChain tool calling: how it works, where it stops.
More adapters are on the AgentKit code samples pages, including Google ADK, OpenAI, Vercel AI, and Mastra.
If you want the MCP shape without the local-subprocess constraint, a Virtual MCP server gives you a hosted, per-tenant endpoint over the same connector.
A standard MCP server exposes every tool it has. A Virtual MCP server exposes only what you list. For a triage agent that reads deliverability data and never sends, that distinction is the difference between a read-only surface and one that can delete templates.
The mcp_server_url is static and shared. The per-tenant part is the session token, minted fresh before each run and passed as bearer auth. Default expiry is about one hour, and create_session_token is also the remint call; there is no separate refresh endpoint.
The official MCP server hands every connecting client all 24 tools, including four destructive ones and four that send real mail. Its own documentation recommends never auto-approving sends in untrusted environments, which is sound advice and also an admission that the surface is wide by default.
Scoping to five read tools removes that risk class before the model sees it, and cuts the tool definitions loaded into every context window. A server with 40 tools at roughly 200 tokens each burns about 8,000 tokens before the agent does any work.
Most real Postmark agents are not Postmark-only. A support triage agent reads a ticket, checks delivery, and posts a summary. One Virtual MCP server can expose Postmark alongside Slack, Gmail, or Freshdesk, each scoped to its own tool list, with one session token covering the whole set for that tenant.
Attribution is the part teams notice they are missing three months in, usually during an incident.
A Postmark server token is anonymous by design. Once an agent holds it, Postmark's own activity view shows a send; it does not show which agent run triggered it or which tenant context it ran under. The official MCP server improves on this with X-Postmark-Client and X-Agent-Label headers, but that identifies the integration, not the request.
Scalekit's agent logs record the full delegation chain on every call: which identifier authorized it, which agent ran it, which tool, and what came back. Logs are exportable to your SIEM, which is what turns an audit trail for agent auth into something a security questionnaire can be answered with.
A failed postmark_send_email has three possible causes: the credential is bad, the tenant's Postmark server rejected the payload, or the agent constructed bad arguments. Those failures look identical in an application log and require three different fixes.
Separating them by source is the difference between a 20-minute diagnosis and an afternoon. executeTool returns an executionId alongside the result so a specific call can be traced end to end. This kind of per-call observability is exactly what agent tool observability requires in production.
The shape of your deployment decides this, not the capability table.
Use the official MCP server. It is the fastest route to conversational deliverability work on a Postmark account you own, and diagnoseDelivery is a better answer to "did this arrive" than anything you would build in an afternoon against the raw API. Point it at a dedicated Postmark server, set WEBHOOK_URL_ALLOWLIST, and never auto-approve the sending or destructive tools.
Build against the API, and hold the tokens somewhere that is not your application database. Every path to Postmark ends at the same long-lived, full-access, un-scopable server token. Solve custody, per-tenant resolution, rotation, and attribution at the infrastructure layer, and the MCP versus API question turns back into what it should be: a capability question with a short answer. For teams thinking about who holds the token across agent tool-calling patterns, Postmark is a clean case study.
Browse the Postmark agent connector or read the Postmark connector docs to see the full tool list. Compare related email connectors for SendGrid, Mailgun, and Resend, or start from an agent template if you want a working pattern first. Pricing is on the AgentKit pricing page.
Building something specific with Postmark and want a second pair of eyes on the architecture? Join the Scalekit Slack community, or talk to an engineer if you need an answer today.