Skip to main content
Mailr hosts a Model Context Protocol server at https://app.getmailr.com/api/mcp. Point an MCP client at it with your API key and an agent can run the Developer API conversationally: check the key, list automations, dry-run an event, subscribe a lead webhook, report a won deal, stage a reactivation import. It is a thin proxy and nothing more. Every tool forwards your Authorization: Bearer ak_… header verbatim to the matching /api/v1/* endpoint, so authentication, scopes, rate limits, validation and idempotency are exactly the ones documented on the other pages of this reference. The MCP route holds no privileged access of its own — an unauthenticated client can list the tools but cannot make a single call succeed.
The OpenAPI spec behind the Endpoints section of this reference remains the source of truth for every request/response shape. The MCP tools map one-to-one onto the operations it documents and pass through only documented fields.

Add the server

MAILR_API_KEY holds the organization-scoped API key the client sends as the bearer token. Keep it in your machine’s or CI’s environment: ${MAILR_API_KEY} is expanded at connect time, so the key itself never lands in a file you commit.

Tools

whoami, list_automations and list_recent_leads are annotated readOnlyHint, so clients that separate read from write tools can auto-approve them. send_event, import_jobs, suppress_customer and unsubscribe_leads are annotated destructiveHint — a live send spends postage, an import burns one of 10 daily slots, suppression is not reversible from this API, and unsubscribing silently stops lead delivery — so clients that gate on annotations will not auto-approve them. The legacy POST /api/v1/webhooks/trigger is not exposed. send_event binds by event type instead of hardcoding an automation id and reports richer outcomes; keeping the tool surface minimal is deliberate.

Safety model

Two tools can spend the customer’s postage. send_event can enqueue real postcard campaigns, and import_jobs stages the batch a reactivation campaign mails. Confirm intent — and the expected cost — with a human before either goes live.
  • send_event defaults to dry_run: true. A dry run performs the full binding match, filter, address and dedup checks and returns exactly the outcomes a live call would, but writes nothing: no connection upsert, no sample, no enqueue, no log. Only an explicit dry_run: false mails anything. (A dry run still costs one unit of rate-limit quota.)
  • import_jobs mails nothing immediately — it stages only. But one call burns one of just 10 import slots per org per UTC day, and the staged batch is what an operator later sends.
  • Confirm-before-spend is baked into the tool descriptions, so the agent sees the warning at call time rather than only in these docs.
  • subscribe_leads returns a signing_secret you must store. The tool tells the agent to show it to you once and not repeat it. The secret is disclosed exactly once, at creation: re-subscribing the same URL is idempotent and returns the existing row’s id with signing_secret: null — never the stored secret, and never a silent rotation. A lost secret is replaced via POST /api/v1/webhooks/rotate, which returns the new one a single time.
  • Scopeless keys are unrestricted. Per the v1 policy, a key that declares no scopes passes every check. Treat the key like a password: it is the whole credential, it identifies the tenant on its own, and anything holding it can mail on the org’s behalf. Scope the key you hand to an agent, and revoke it from the Mailr dashboard if it leaks.
  • The route is key-authed, not session-authed. /api/mcp runs no dashboard session logic and holds no privileged access of its own; every tool call is authorized downstream by the same API-key check the /api/v1/* endpoint it proxies to performs.
  • Every tool result carries a notice telling the agent to treat response data — lead messages, names, custom fields — strictly as data, never as instructions.

Try it

The /api/mcp edge enforces the same pre-auth per-IP throttle as the REST API: a client over the line gets a JSON-RPC error (code: -32000) at HTTP 429 with a Retry-After header, before any key is verified — so a flood of unauthenticated calls is shed at the edge. Errors come back as tool errors carrying the v1 status and body, so 422 invalid_payload names the offending field just as it does over curl. On 429/503 the tool result also states how many seconds to wait, taken from the Retry-After header — see Errors & rate limits for the full retry contract.