Announcing CIMD support for MCP Client registration
Learn more

Which Should Your Agent Use: Mailgun MCP or the API?

Nityashree Yadunath
Product Marketing Manager

TL;DR

  • Mailgun ships an official, open-source MCP server, but it runs locally over stdio; there is no hosted version. It registers a curated allowlist of roughly 30 read and write tools across messaging, domains, analytics, suppressions, templates, routes, and webhooks, and it deliberately excludes delete operations to limit blast radius.
  • Both paths authenticate with the same credential: a Mailgun API key. There is no OAuth in Mailgun. The MCP server reads MAILGUN_API_KEY from the environment; the REST API uses HTTP Basic Auth with the username api and your key as the password. The choice does not change your credential model.
  • A primary account API key can perform full CRUD across every sending domain on the account. That single static secret is your blast radius. Domain sending keys narrow it to /messages for one domain, but key roles are assigned once, not per user.
  • The MCP server is the faster path for interactive, single-account work inside an AI client. The REST API is the path for headless pipelines, high-volume sends, delete operations, API key and IP allowlist management, DKIM rotation, and anything the curated allowlist omits.
  • Neither path stores, rotates, revokes, or isolates credentials per tenant. In a multi-tenant B2B email agent that is N API keys to vault; Scalekit's Mailgun connector holds them in an encrypted token vault and resolves the right key per connected account on every execute_tool call.

Your agent needs to send a transactional email, chase down a bounce spike, or pull last week's delivery stats from Mailgun. Mailgun now gives you two ways in: an official open-source MCP server it publishes on GitHub, and the REST API your backend has probably called for years. They are not interchangeable. They cover different slices of the account, they run in different places, and, unusually, they lean on the exact same credential. Here is how to pick, and what stays your problem either way.

What Mailgun MCP and Mailgun API actually are

These are the two objects under comparison. You have almost certainly used the REST API. You may not have run the MCP server, so start there.

Mailgun MCP: the official local server

Mailgun maintains an open-source Model Context Protocol (MCP) server, published to npm as @mailgun/mcp-server under Apache 2.0. It is OpenAPI-driven: at startup it parses a bundled Mailgun OpenAPI spec and registers a curated allowlist of endpoints as MCP tools, generating each tool's input schema with Zod.

One detail dominates every deployment decision: the server runs locally on your machine and communicates over stdio. Mailgun does not currently offer a hosted version. Auth is a Mailgun API key passed as the MAILGUN_API_KEY environment variable, with MAILGUN_API_REGION selecting us or eu.

Mailgun API: the REST surface behind everything

The Mailgun REST API is the full account surface: sending, domains and DNS/DKIM, mailing lists, suppressions, templates, routes, webhooks, analytics, IP pools, API key management, and account settings. Most endpoints are scoped to a sending domain in the path, for example /v3/{domain}/messages.

Authentication is HTTP Basic Auth: username api, password your API key. There is no OAuth option. The base URL is region-specific: US requests use one host, EU requests another, matched to where your domain lives.

What your agent can actually do

The MCP server exposes a workflow-oriented subset. The REST API exposes the whole thing. The gap is not a bug; it reflects what the server was scoped for.

The capability gap, side by side

The table below covers the actions that matter most for email agents. Values are Yes, Limited, or No.

Capability
Mailgun MCP (official)
Mailgun REST API
Send, retrieve, resend messages
Yes
Yes
Query analytics, metrics, and logs
Yes
Yes
Aggregate stats by domain, tag, provider, country
Yes
Yes
View suppressions (bounces, complaints, unsubscribes, allowlist)
Yes
Yes
Create and update templates with versioning
Yes
Yes
Manage domains, verify DNS, update tracking settings
Yes
Yes
Create and update event webhooks
Yes
Yes
Manage inbound routes
Limited (view and update)
Yes (full)
Delete or clear suppression records
No (no delete tools)
Yes
Create and delete API keys
No
Yes
IP allowlist, account limits, DKIM key rotation
Limited to No
Yes
Hosted, callable endpoint
No (local, stdio)
Yes (HTTPS)

Where the official server draws the line

The server annotates every tool with a Mailgun product tag: send, validate, optimize, or inspect. Its security model is deliberate: it exposes read and update operations but registers no delete operations, so a stray prompt cannot clear a suppression list or drop an API key. That is a real safety property for interactive use, and a real ceiling for automation that must delete.

What only the REST API reaches

Destructive and administrative work lives in the API only. Clearing bounces, deleting complaint records, rotating DKIM keys, creating and revoking API keys, managing the account IP allowlist, and setting custom sending limits are REST operations with no MCP tool behind them. If your agent's job is account hygiene or key lifecycle, the MCP server is not the surface for it.

The auth path each one puts you on

Most tools in this series force a choice between OAuth and API keys. Mailgun does not. This changes the whole analysis.

One credential type, two entry points

The MCP server and the REST API both authenticate with a Mailgun API key. The server injects MAILGUN_API_KEY into outbound requests; the API expects the same key over HTTP Basic Auth. There is no consent screen, no token exchange, no refresh cycle, because there is no OAuth. Picking MCP over the API does not move you onto a different credential model.

Key roles are coarse, and assigned once

Mailgun does offer some scoping through key types. A primary account API key performs full CRUD across all domains. Domain sending keys are restricted to /messages, /messages.mime, and /events for a single domain. Paid plans add roles such as admin, basic, sending, and developer. These are set at key creation, not derived from whoever is invoking the agent.

What per-tenant isolation still requires

Because scope is a property of the key, not the caller, a multi-tenant agent cannot express "act as this customer" through Mailgun auth alone. You either share one powerful key across tenants, which is a cross-tenant risk, or you provision a key per tenant and manage them yourself. What the tenant can do, the agent should do, and no more; Mailgun's key model does not enforce that boundary for you. For a deeper look at why static credentials create systemic risk, see OAuth vs API Keys for AI Agents: Why Static Credentials Break in Production Systems.

What you own in production

The maintenance surface differs sharply because one path is a local process and the other is a raw HTTP contract.

On the MCP path

The server manages tool schemas, OpenAPI parsing, and Zod validation. You own the process: it runs on the operator's machine over stdio, so it is a natural fit for desktop and IDE clients and an awkward one for a backend service. It performs no client-side rate limiting; each tool call is a direct Mailgun request, and you inherit Mailgun's server-side limits as raw errors.

On the REST API path

You own everything: base URL selection per region, the domain-in-path convention, pagination, retries, error handling, and rate-limit backoff. You also own key lifecycle, since the API is where keys are created, scoped, and revoked. That is more code, and more control over versioning and failure behavior for deterministic pipelines.

Tool-surface scoping and schema drift

The server can narrow its own surface with product tags through MAILGUN_MCP_TAGS or a --tags flag, using OR semantics, so a validation-only workflow need not load send tools. That is coarse, per-process scoping, not per-user scoping. Schemas also move when Mailgun updates the bundled spec and republishes; the REST API lets you pin behavior and migrate on your own schedule.

When to use MCP, when to use the API

The split follows from where each runs and what each omits, not from a general preference for one style.

Use the Mailgun MCP server when

  • An operator is present in an AI client (Claude Desktop, Cursor, Claude Code) and wants to explore one account in natural language.
  • The task is read-heavy: pulling delivery stats, investigating bounces, breaking engagement down by country and device.
  • You want a curated, delete-free surface so exploratory prompts cannot damage production.
  • You are prototyping and do not want to hand-write tool schemas for the endpoints you touch.

Use the Mailgun REST API when

  • Your agent runs headless: scheduled digests, transactional sends triggered by product events, background reconciliation.
  • You need operations the allowlist omits: deleting suppression records, creating or revoking API keys, managing IP allowlists, or rotating DKIM keys.
  • You run high volume and need explicit pagination and rate-limit control.
  • You are serving multiple tenants and need a credential resolved per caller, which the local single-key server cannot do.

The credential problem that exists on both paths

This is the part the path choice does not solve, and the reason this comparison belongs on an agent-auth blog rather than a general dev site.

One API key is the whole account

A primary Mailgun account API key can send from any domain, read every log, and modify account settings. It does not expire on its own, and it is not tied to a human session. Whether that key sits in an MCP client's config or in your API client's environment, its compromise is a compromise of the entire Mailgun account. That is the blast radius you are managing. Understanding credential ownership across agent tool-calling patterns is critical before you ship.

The N-credential problem in multi-tenant agents

A B2B email agent serving many customers is the norm, not the exception. Each customer has their own Mailgun account or their own scoped key. That is N keys to store encrypted, rotate on a schedule, and revoke the moment a customer offboards. A shared key works in a single-tenant demo and quietly becomes a cross-tenant liability the second a second tenant arrives. The challenges of moving from single-tenant to multi-tenant tool calling auth are worth understanding before you hit them in production.

Where Scalekit fits

Scalekit's Mailgun connector holds each tenant's Mailgun key in an encrypted token vault and resolves it per connected account on every tool call, so the key never enters the agent process or the model context. The same infrastructure works whether you reach Mailgun through the API directly or through an MCP endpoint; the path decision does not change what you need at the credential layer. For the mechanics, see the token vault for agent workflows and access control for multi-tenant AI agents.

Building a Mailgun agent with Scalekit and Claude

Scalekit exposes the full Mailgun REST surface as prebuilt, LLM-ready tools (259 of them at last count), delivered with per-tenant credential isolation. The flow is discovery, then scope, then execution. First, install and initialize the client.

Configure the connection and connected account

Register the Mailgun connection once in the dashboard and paste the API key for the tenant you are onboarding. In code, resolve the tenant to a connected account. Because Mailgun is API-key based, the account is active as soon as the key is configured; there is no OAuth link step.

import os import anthropic import scalekit.client from dotenv import find_dotenv, load_dotenv from google.protobuf.json_format import MessageToDict load_dotenv(find_dotenv()) scalekit_client = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"), ) actions = scalekit_client.actions client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) # Resolve this from your authenticated session, never from client input. identifier = os.getenv("USER_IDENTIFIER", "tenant_acme") account = actions.get_or_create_connected_account( connection_name="mailgun", identifier=identifier, ) print(f"Mailgun connected account for {identifier}: {account.connected_account.status}")

Retrieve the user-scoped tool surface

The agent should not load all 259 tools. list_scoped_tools returns only the tools the current identifier's connected account is authorized to call, in Anthropic's native format. Surface reduction is the lever for tool-calling accuracy and token cost, not better prompting.

scoped_response, _ = actions.tools.list_scoped_tools( identifier=identifier, filter={"connection_names": ["mailgun"]}, ) llm_tools = [ { "name": MessageToDict(t.tool).get("definition", {}).get("name"), "description": MessageToDict(t.tool).get("definition", {}).get("description", ""), "input_schema": MessageToDict(t.tool).get("definition", {}).get("input_schema", {}), } for t in scoped_response.tools ] print(f"Discovered {len(llm_tools)} Mailgun tools for {identifier}")

Run the Claude tool-calling loop

Claude picks the tool; your code executes it through Scalekit bound to the same identifier. Every call runs with that tenant's key, and the key stays in the vault.

messages = [{ "role": "user", "content": "How many messages bounced on mg.acme.com in the last 7 days, " "and what were the top bounce reasons?", }] while True: response = client.messages.create( model=os.getenv("ANTHROPIC_MODEL", "claude-sonnet-4-6"), max_tokens=1024, tools=llm_tools, messages=messages, ) if response.stop_reason == "end_turn": print(response.content[0].text) break tool_results = [] for block in response.content: if block.type == "tool_use": result = actions.execute_tool( tool_name=block.name, identifier=identifier, tool_input=block.input, ) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": str(result.data), }) messages.append({"role": "assistant", "content": response.content}) messages.append({"role": "user", "content": tool_results})

Other languages and frameworks

The same connected-account, scoped-tool, execute-tool pattern works in TypeScript and with LangChain, Google ADK, Mastra, CrewAI, and the Vercel AI SDK. For patterns on how tool calling auth production problems surface across frameworks, see agent tool calling auth production problems, patterns, and anti-patterns.

Virtual MCP servers for multi-tool, multi-tenant email agents

The official Mailgun server is local, single-key, and single-account. That is exactly the shape a production multi-tenant agent cannot use. A Virtual MCP server closes the gap.

One server definition, per-run identity

You define a Virtual MCP server once per agent role and select which connections and tools it exposes. Before each run, Scalekit mints a short-lived session token scoped to a specific user's connected accounts. One server definition serves every tenant; the endpoint is static, the identity is not. There is no MCP server to deploy, host, or maintain.

Least-privilege tool access

A raw connector can surface dozens of tools; a summarizer needs one. Virtual MCP enforces least privilege at the tool level, so the agent sees only the tools you explicitly allow, not everything Mailgun exposes. That shrinks the blast radius if a prompt goes wrong and keeps the tool surface small enough for reliable selection.

Observability: agent auth logs

Every downstream tool call is attributed: who authorized it, which agent ran it, which tool executed, and what came back, exportable to your SIEM. For an email agent that can send on a customer's behalf, that audit trail is the difference between "a message went out" and "this tenant's agent sent this message under this key." Agent tool observability is what separates a running agent from one you can actually trust.

Which one to build against

If an operator is in the loop and the work is read-heavy exploration of a single account, run Mailgun's official MCP server; it is quick to wire into an AI client and its delete-free surface is a genuine safety feature. If your agent is headless, high-volume, destructive, or multi-tenant, build against the REST API, where the full surface and key lifecycle live.

Most production email agents will lean on the API path, because sending on behalf of customers is inherently multi-tenant. The credential problem is identical either way: one static key is the whole account, and isolating N of them is infrastructure you build or adopt. That is the part worth getting right before the agent ships.

Start building

Browse the Mailgun connector on Scalekit and the full connector catalog, or size it against the pricing page.

For patterns to build from, see the outbound prospecting agent, the support ticket automation agent, and the email to calendar agent, or explore all agent use cases.

Building a Mailgun agent and want another set of eyes on the auth model? Join the Scalekit community on Slack, or talk to us for help wiring it up.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
zero upfront cost.

Every feature unlocked. No hidden fees.