Integrations
MCP server
Connect Cursor (or any MCP client) to MailParrot over a hosted Streamable HTTP endpoint. No local package, Node install, or compile — just a URL and an API key.
New to MCP? See what AI agents can do with MailParrot and copyable connection config.
Install with your agent
Copy and paste the following prompt into your agent. The agent will complete the installation automatically.
Please help me set up a new custom MCP server via the following endpoint, and complete the authorization process, https://api.mailparrot.app/mcp. Authorization is an API key in the x-api-key header (create one under Dashboard → Settings → API Keys).Point and go
Manual setup. Add this to your Cursor mcp.json. Create an API key in Dashboard → Settings.
{
"mcpServers": {
"mailparrot": {
"url": "https://api.mailparrot.app/mcp",
"headers": {
"x-api-key": "mp_your_key_here"
}
}
}
}Staging: https://api.test.mailparrot.app/mcp. Alias domains: to.mailparrot.app (prod) / to.test.mailparrot.app (staging). Authorization: Bearer mp_… also works.
Malformed JSON
The hosted endpoint is a Cloud Function. The Functions runtime parses Content-Type: application/json before MailParrot runs, and it does not hand a parse failure to the function. A body that is not valid JSON (for example {not json) is HTTP 400 with Express's HTML Bad Request page, even when no API key is sent. There is no supported setting to turn that parser off.
An empty JSON body does reach the server. After the API key is accepted, the MCP SDK responds with HTTP 400 and JSON-RPC error -32700. The same JSON-RPC parse error is what a direct Express process (local HTTP) returns for invalid JSON, because that process is the first parser.
Agent flow
- Call
get_usageto confirm credits remain. - Create a project and alias (
create_project,create_alias). - Send the app under test to the returned inbox address.
- Call
wait_for_auth_code(orlist_messages) to retrieve the OTP. The wait ignores codes already stored on the alias and returns one ingested after the call starts. PassincludeExisting: trueto accept a code that is already there.
Credits and payment gating
When remaining credits hit zero, inbound mail is not stored, and the messages and latestAuthCode GraphQL operations fail with PAYMENT_REQUIRED. Project, alias, webhook, and usage tools still work. Buy packs in Settings → Credits.
See also the messages and latestAuthCode API reference.
Tools
Argument names, types, and whether each one is required come from the MCP tool schemas.
get_usage
Get MailParrot credit usage (used, remaining, total, unlock fields). Available even at 0 credits. Call this before wait_for_auth_code when unsure about balance.
No arguments.
list_credit_packs
List available Stripe credit pack sizes (priceId + credits). Purchases happen in the dashboard Settings → Credits page (not via MCP).
No arguments.
list_projects
List all MailParrot projects for the authenticated account.
No arguments.
create_project
Create a new MailParrot project to group disposable inboxes (aliases).
name(string, required): Project display name
update_project
Rename an existing MailParrot project.
projectId(string, required): Project idname(string, required): New project display name
delete_project
Permanently delete a project and its aliases, messages, and webhooks.
projectId(string, required): Project id
list_aliases
List disposable inbox aliases for a project.
projectId(string, required): Project id
create_alias
Create a disposable inbox. Domains: to.mailparrot.app (prod) or to.test.mailparrot.app (staging). Returns the full emailAddress to use in tests.
projectId(string, required): Project idlocalPart(string, required): Local part before @, e.g. qa-user-42domain(string, required): to.mailparrot.app or to.test.mailparrot.app
set_alias_active
Enable or disable an alias inbox.
projectId(string, required): Project idaliasId(string, required): Alias idactive(boolean, required): True to receive mail, false to drop it
delete_alias
Delete an alias inbox.
projectId(string, required): Project idaliasId(string, required): Alias id
list_messages
List messages for an alias (paginated). Fails with PAYMENT_REQUIRED when the account has no remaining credits.
projectId(string, required): Project idaliasId(string, required): Alias idpage(integer, optional): Page number (default 1)limit(integer, optional): Page size, 1-100 (default 20)sortOrder("asc" | "desc", optional): Sort by receivedAt: "asc" or "desc" (default desc)
get_latest_auth_code
Return the most recently extracted OTP/auth code for an alias, or null if none. With no since or afterMessageId, this is the latest code even when it arrived earlier. Pass since and/or afterMessageId to ignore codes that are not strictly newer. since is compared to storedAt (server insert time). Fails with PAYMENT_REQUIRED when out of credits.
projectId(string, required): Project idaliasId(string, required): Alias idsince(string | integer, optional): Only return a code stored strictly after this time. ISO-8601 timestamp or epoch milliseconds (a whole number below 1e11 is read as epoch seconds). Compared to storedAt (server clock at insert, millisecond precision), not the email Date header and not Mailgun's whole-second receivedAt.afterMessageId(string, optional): Only return a code whose message id sorts after this id (MongoDB ObjectId order). The given id is excluded. Use this to ignore a code you already consumed, including when two emails share a second.
wait_for_auth_code
Poll until an auth code is stored after this call starts, or the wait elapses (default 50000ms). Codes already on the alias are ignored, so a reused inbox cannot hand back a stale OTP. Pass includeExisting: true to accept a code that is already stored. since (ISO-8601 or epoch ms) overrides that cutoff and is compared to storedAt, the server insert time, not the email Date or Mailgun's whole-second receivedAt. afterMessageId skips that message id and anything older, which separates two codes that share a second. The time cutoff still applies; pass includeExisting or an earlier since to accept an older stored code with a newer id. timeoutMs above 50000ms is accepted and capped to 50000ms on this server instead of being rejected. Hosted MCP (https://api.mailparrot.app/mcp) caps near 50s because Firebase Hosting closes the connection at 60s; local stdio caps at 300000ms. Always returns a tool result (OTP, PAYMENT_REQUIRED, or timeout). Call again to keep polling. Pre-checks usage and aborts immediately on PAYMENT_REQUIRED / 0 credits (inbound mail is not stored when empty).
projectId(string, required): Project idaliasId(string, required): Alias idtimeoutMs(integer, optional): Max wait in ms (default 50000). Larger values are accepted and capped to 50000ms on this server.intervalMs(integer, optional): Poll interval in ms (default 2000)since(string | integer, optional): Only return a code stored strictly after this time. ISO-8601 timestamp or epoch milliseconds (a whole number below 1e11 is read as epoch seconds). Compared to storedAt (server clock at insert, millisecond precision), not the email Date header and not Mailgun's whole-second receivedAt.afterMessageId(string, optional): Only return a code whose message id sorts after this id (MongoDB ObjectId order). The given id is excluded. Use this to ignore a code you already consumed, including when two emails share a second.includeExisting(boolean, optional): When true, a code already stored before this call may be returned (the previous behaviour). Default false: only a code ingested after the call starts is returned. An explicit since or afterMessageId still applies.
list_webhooks
List outgoing webhooks configured for an alias.
projectId(string, required): Project idaliasId(string, required): Alias id
create_webhook
Register a webhook URL for an alias. Use event types transactional_email_arrived and/or auth_code_extracted.
projectId(string, required): Project idaliasId(string, required): Alias idurl(string, required): HTTPS endpoint that receives eventseventTypes(string[], required): Event names, e.g. transactional_email_arrived and auth_code_extracted
update_webhook
Update a webhook URL, event types, or active flag. Use event types transactional_email_arrived and/or auth_code_extracted.
projectId(string, required): Project idaliasId(string, required): Alias idwebhookId(string, required): Webhook idurl(string, optional): Replacement endpoint URLeventTypes(string[], optional): Replacement event namesactive(boolean, optional): Enable or disable delivery
delete_webhook
Delete a webhook from an alias.
projectId(string, required): Project idaliasId(string, required): Alias idwebhookId(string, required): Webhook id
list_webhook_logs
List recent delivery attempts for a webhook.
projectId(string, required): Project idaliasId(string, required): Alias idwebhookId(string, required): Webhook id
