MCP server

Email for agents, as MCP tools

A hosted Model Context Protocol server at https://api.mailgi.xyz/mcp. Point Claude Code, Claude Desktop or Cursor at it and the agent can register an address, send, read and file mail — with nothing to install on the server side.

Every tool is the REST API, called for you. Same limits, same billing, same errors.
Streamable HTTP · Stateless · Headers for auth
# endpoint
https://api.mailgi.xyz/mcp
# headers decide which tools work
Authorization: Bearer amb_… → agent tools
X-Mailgi-Session: <token> → org tools
(neither) → public tools only

What it is

The MCP server runs inside the Mailgi API itself. Each tool forwards to an existing REST endpoint and returns that endpoint's response, so a tool call and the equivalent curl behave identically: the same validation, the same rate limits, the same metering against the same wallet. Nothing is cached or reshaped in between. The server is stateless — there is no MCP session to keep alive — and credentials travel as HTTP headers on the connection, not as tool arguments.

The server also exposes one resource, mailgi://skill, which serves SKILL.md — the plain-language guide to the API — so a client can load it as context without fetching the website.

Connect a client

Transport is Streamable HTTP. Already have an API key? Add it as the Authorization header and you're done. Don't have one yet? Start without headers and follow the bootstrap below.

Claude Desktop's config file only launches local processes, so it reaches a remote server through the mcp-remote bridge, which needs Node.js. Cursor speaks HTTP directly.

# With an agent API key
claude mcp add --transport http mailgi https://api.mailgi.xyz/mcp \
  --header "Authorization: Bearer amb_..."

# Org tools as well — add the dashboard session header
claude mcp add --transport http mailgi https://api.mailgi.xyz/mcp \
  --header "Authorization: Bearer amb_..." \
  --header "X-Mailgi-Session: <session token>"

# No credentials yet — public tools only, for bootstrap
claude mcp add --transport http mailgi https://api.mailgi.xyz/mcp
// claude_desktop_config.json
{
  "mcpServers": {
    "mailgi": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://api.mailgi.xyz/mcp",
        "--header", "Authorization:${MAILGI_AUTH}"
      ],
      "env": { "MAILGI_AUTH": "Bearer amb_..." }
    }
  }
}
// The env indirection keeps the space in "Bearer amb_..."
// from being split when the arguments are passed on.
// .cursor/mcp.json (project) or ~/.cursor/mcp.json (global)
{
  "mcpServers": {
    "mailgi": {
      "url": "https://api.mailgi.xyz/mcp",
      "headers": {
        "Authorization": "Bearer amb_..."
      }
    }
  }
}

Bootstrap: from nothing to a key

The server has no OAuth, so a credential can't be attached to the connection for you. The agent obtains one through a tool, and a human puts it into the client config once.

01

An agent of its own

Connect with no headers and ask the agent to call register_agent (optionally with a label, or a domainToken and localPart to claim an address on a company domain). It returns the email address and an API key starting amb_ — shown exactly once. Re-add the server with Authorization: Bearer amb_… and the agent tools appear. In Claude Code that is claude mcp remove mailgi followed by the add command above.

02

Org admin, by emailed code

For the organisation tools — domains, members, registration tokens, the org wallet — the agent calls org_login_request_code with a human's email address. Mailgi emails that person a six-digit code; they tell the agent, which passes it to org_login_verify and gets back a dashboard session token. Add it to the connection as X-Mailgi-Session. Call org_logout to end that session when you're done with it.

03

Both at once

The two headers are independent. Send both and the connection has agent and org tools together — for example an admin agent that creates a registration token with regtoken_create and hands it to another agent to self-register on the company domain.

All 67 tools

Tool names map one-to-one to REST endpoints, and each behaves exactly like the endpoint it names. For request and response fields, read the endpoint in the API docs or SKILL.md. Tools that delete, revoke or remove carry the MCP destructiveHint annotation, so a client that honours it asks before calling them.

Agent tools · 25 · need Authorization: Bearer amb_…

Everything an agent does with its own mailbox and wallet.

Agent tools
ToolREST endpointWhat it does
agent_getGET /v1/agents/meThis agent's profile and address
agent_usageGET /v1/agents/me/usageThis agent's usage, by day
agent_deleteDELETE /v1/agents/meDelete the agent — permanent, burns the address destructive
mail_listGET /v1/mailList messages
mail_getGET /v1/mail/{id}Read a message with its body
mail_sendPOST /v1/mail/sendSend a message (metered exactly like REST)
mail_deleteDELETE /v1/mail/{id}Move a message to Trash destructive
mail_movePATCH /v1/mail/{id}/moveMove a message to another mailbox
mail_set_flagsPATCH /v1/mail/{id}/flagsSet seen / flagged
mailbox_listGET /v1/mailboxesList mailboxes (folders)
mailbox_createPOST /v1/mailboxesCreate a mailbox
mailbox_renamePATCH /v1/mailboxes/{id}Rename a mailbox
mailbox_deleteDELETE /v1/mailboxes/{id}Delete a mailbox destructive
apikey_listGET /v1/apikeysList API keys
apikey_createPOST /v1/apikeysCreate an API key
apikey_revokeDELETE /v1/apikeys/{keyId}Revoke an API key destructive
billing_getGET /v1/billingWallet balance, prices, how to top up
billing_topupPOST /v1/billing/topupCreate a card top-up link for a human to pay
billing_transactionsGET /v1/billing/transactionsWallet ledger
webhook_listGET /v1/webhook-endpointsList webhook endpoints
webhook_createPOST /v1/webhook-endpointsRegister a webhook endpoint for inbound mail
webhook_deleteDELETE /v1/webhook-endpoints/{id}Delete a webhook endpoint destructive
webhook_deliveriesGET /v1/webhook-endpoints/{id}/deliveriesRecent delivery attempts
webhook_resendPOST /v1/webhook-endpoints/{id}/deliveries/{deliveryId}/resendRe-queue a delivery
webhook_enablePOST /v1/webhook-endpoints/{id}/enableRe-enable an endpoint switched off by failures

Org tools · 35 · need X-Mailgi-Session

What a human does in the dashboard at app.mailgi.xyz, with that human's role in each organisation.

Organisation tools
ToolREST endpointWhat it does
org_meGET /v1/auth/meThe signed-in user and their orgs
org_listGET /v1/orgsList organisations
org_createPOST /v1/orgsCreate an organisation
org_getGET /v1/orgs/{orgId}Get an organisation
org_renamePATCH /v1/orgs/{orgId}Rename an organisation
org_member_listGET /v1/orgs/{orgId}/membersList members
org_member_set_rolePATCH /v1/orgs/{orgId}/members/{userId}Change a member's role
org_member_removeDELETE /v1/orgs/{orgId}/members/{userId}Remove a member (or leave) destructive
org_invite_createPOST /v1/orgs/{orgId}/invitesInvite someone by email
org_invite_listGET /v1/orgs/{orgId}/invitesList pending invites
org_invite_revokeDELETE /v1/orgs/{orgId}/invites/{inviteId}Revoke an invite destructive
invite_acceptPOST /v1/invites/acceptAccept an invite
domain_attachPOST /v1/orgs/{orgId}/domainsAttach a custom domain
domain_listGET /v1/orgs/{orgId}/domainsList custom domains
domain_getGET /v1/orgs/{orgId}/domains/{domainId}Verification status and the DNS records to publish
domain_detachDELETE /v1/orgs/{orgId}/domains/{domainId}Detach a custom domain destructive
domain_verifyPOST /v1/orgs/{orgId}/domains/{domainId}/verifyRe-check DNS
domain_usageGET /v1/orgs/{orgId}/usage/domains/{domainId}Usage for one domain, by day
org_usageGET /v1/orgs/{orgId}/usageUsage for the organisation, by day
org_billing_getGET /v1/orgs/{orgId}/billingOrganisation wallet
org_billing_topupPOST /v1/orgs/{orgId}/billing/topupCreate a card top-up link for the org wallet
org_billing_transactionsGET /v1/orgs/{orgId}/billing/transactionsOrganisation wallet ledger
org_webhook_listGET /v1/orgs/{orgId}/webhook-endpointsList the org's webhook endpoints
org_webhook_createPOST /v1/orgs/{orgId}/webhook-endpointsCreate a webhook endpoint for one of the org's inboxes
org_webhook_deleteDELETE /v1/orgs/{orgId}/webhook-endpoints/{id}Delete a webhook endpoint destructive
org_webhook_deliveriesGET /v1/orgs/{orgId}/webhook-endpoints/{id}/deliveriesRecent delivery attempts
org_webhook_resendPOST /v1/orgs/{orgId}/webhook-endpoints/{id}/deliveries/{deliveryId}/resendRe-queue a delivery
org_webhook_enablePOST /v1/orgs/{orgId}/webhook-endpoints/{id}/enableRe-enable an endpoint
regtoken_createPOST /v1/orgs/{orgId}/domains/{domainId}/registration-tokensCreate a registration token (shown once)
regtoken_listGET /v1/orgs/{orgId}/domains/{domainId}/registration-tokensList registration tokens
regtoken_revokeDELETE /v1/orgs/{orgId}/domains/{domainId}/registration-tokens/{tokenId}Revoke a registration token destructive
domain_inbox_listGET /v1/orgs/{orgId}/domains/{domainId}/agentsList inboxes on a domain
domain_inbox_createPOST /v1/orgs/{orgId}/domains/{domainId}/agentsCreate an inbox with a chosen local part
domain_inbox_deleteDELETE /v1/orgs/{orgId}/domains/{domainId}/agents/{agentId}Remove an inbox from a domain destructive
org_logoutPOST /v1/auth/logoutEnd the dashboard session

Public tools · 7 · no credentials

Bootstrap, paying for any agent's wallet by address, and a health check.

Public tools
ToolREST endpointWhat it does
register_agentPOST /v1/agents/registerRegister an agent; returns the API key once
org_login_request_codePOST /v1/auth/email/request-codeEmail a 6-digit login code
org_login_verifyPOST /v1/auth/email/verify-codeVerify the code; returns a session token
topup_lookupGET /v1/topup/lookupWho a top-up for an address would pay for
topup_startPOST /v1/topupStart a card payment for any agent's wallet
topup_statusGET /v1/topup/sessions/{sessionId}Status of a top-up payment
healthGET /health/readyReadiness of the API and mail server

Not exposed over MCP: DID authentication (not available in the API either), OAuth sign-in redirects, signup attribution, and the inbound webhooks from Mailgi's own providers.

Limits, stated plainly

01

One config edit after bootstrap

A key obtained through register_agent or a session from org_login_verify doesn't attach itself to the connection. A human has to add the header to the client config and reconnect. Until then only the public tools work.

02

No OAuth, so no hosted connectors yet

claude.ai and ChatGPT add remote MCP servers as hosted custom connectors, which authenticate with OAuth rather than a header you type in. The server doesn't implement OAuth, so it can't be used from those today. Clients where you control the headers — Claude Code, Claude Desktop through mcp-remote, Cursor — work.

03

Org tools give an agent admin reach

A session token carries the signed-in human's role. An agent holding an owner's or admin's session can detach domains, remove members, revoke tokens and delete inboxes. The destructiveHint annotation only helps if your client asks before acting on it — only add X-Mailgi-Session to a connection you would trust with the dashboard, and end it with org_logout.

04

Same limits and prices as REST

MCP is not a separate tier. A mail_send is metered and rate-limited exactly like POST /v1/mail/send — see pricing — and errors come back as the endpoint's own error.

Not using MCP?

The same API is plain HTTP, a CLI and a TypeScript SDK, and SKILL.md teaches any agent to use it directly.