MCP Server

@receiverdotemail/mcp gives any MCP client four tools to create inboxes, wait for email and read it. It runs locally over stdio.

Requirements

  • Node.js 20 or later (the client starts the server with npx).
  • A project API key (recv_live_...). Create one in your project's settings; see Quick Start.
VariableDescription
RECEIVER_API_KEYRequired. The project the tools work in comes from the key.
RECEIVER_API_URLOptional. Defaults to https://api.receiver.email/api/v1.

Install

Claude Code

bash
claude mcp add receiver \
  -e RECEIVER_API_KEY=recv_live_your_key \
  -- npx -y @receiverdotemail/mcp

Add --scope project to share it with your team through .mcp.json; keep the key itself out of the file by setting RECEIVER_API_KEY in each person's environment.

Claude Desktop

Edit claude_desktop_config.json (Settings, Developer, Edit Config) and restart the app:

json
{
  "mcpServers": {
    "receiver": {
      "command": "npx",
      "args": ["-y", "@receiverdotemail/mcp"],
      "env": { "RECEIVER_API_KEY": "recv_live_your_key" }
    }
  }
}

Cursor

Add the same mcpServers block to ~/.cursor/mcp.json for every project, or to .cursor/mcp.json in one repository.

VS Code

Add it to .vscode/mcp.json. VS Code can prompt for the key so it never lands in the file:

json
{
  "inputs": [
    { "id": "receiver-key", "type": "promptString", "description": "Receiver.email API key", "password": true }
  ],
  "servers": {
    "receiver": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@receiverdotemail/mcp"],
      "env": { "RECEIVER_API_KEY": "${input:receiver-key}" }
    }
  }
}

Windsurf and other clients

Any client that launches stdio servers works with the command npx -y @receiverdotemail/mcp and the RECEIVER_API_KEY environment variable. In Windsurf, add the mcpServers block above to ~/.codeium/windsurf/mcp_config.json.

Tools

Every tool returns its result as JSON text. Tool descriptions are written for the model: they say what the tool is for and when to call it.

create_inbox: Mint an Address

Returns a new address under your project. Nothing is stored until mail arrives. Pass the returned since to wait_for_email.

InputTypeDescription
prefixstring, optionalStart of the address, e.g. "signup". A random suffix is added so parallel calls never collide. Allowed: a to z, 0 to 9 and . _ + -, up to 40 characters.
json
{ "address": "[email protected]",
  "since": "2026-11-05T10:00:00.000Z" }

wait_for_email: Wait for the Next Email

Waits for an email to the address received after since, and returns it.

InputTypeDescription
addressstringThe address to wait on.
sinceISO 8601, optionalOnly mail received strictly after this time. Use the since from create_inbox. Default: the last 60 seconds.
timeoutSecondsnumber, optionalHow long to wait. Default 60, max 300.
extract"otp" | "links" | "none"Also return the verification code, or the links. Default "none".
json
{ "status": "received",
  "email": {
    "id": "email_xyz",
    "from": "[email protected]",
    "subject": "Your Acme code",
    "receivedAt": "2026-11-05T10:00:04.120Z",
    "text": "Your verification code is 847291..."
  },
  "otp": { "code": "847291", "candidates": ["847291"] } }

text is the first 4,000 characters of the plain text body. otp appears with extract: "otp"; candidates lists the codes found in that email, and otp is null when the email has no code. links (an array of URLs) appears with extract: "links".

list_emails: Recent Emails

InputTypeDescription
addressstring, optionalOnly mail to this address. Default: the whole project.
limitnumber, optionalDefault 10, max 50.
json
{ "emails": [
  { "id": "email_xyz", "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Your Acme code", "receivedAt": "2026-11-05T10:00:04.120Z" }
] }

get_email: Read One Email

InputTypeDescription
idstringAn email id from wait_for_email or list_emails.
format"text" | "html"Which body to return. Default "text".
json
{ "id": "email_xyz", "from": "[email protected]",
  "to": "[email protected]",
  "subject": "Your Acme code", "receivedAt": "2026-11-05T10:00:04.120Z",
  "body": "Your verification code is 847291...",
  "links": ["https://acme.example/verify?token=..."],
  "attachments": [ { "filename": "welcome.pdf", "contentType": "application/pdf", "size": 48213 } ] }

How since works

since is an ISO 8601 timestamp. A wait matches only mail whose receivedAt is strictly after it. That gives two rules:

  • First email: wait from the since that create_inbox returned. Mail from before the address existed can never match.
  • Next email: wait from the receivedAt of the email you already have, for example after the agent clicks "Resend code".

Without since, a wait looks back 60 seconds, so an email that arrived just before the call still counts.

Timeouts

A wait that ends without mail is a normal result, not an error:

json
{ "status": "timeout",
  "since": "2026-11-05T10:00:00.000Z",
  "hint": "No email yet. Call wait_for_email again with the same since." }

Calling again with the same since loses nothing: an email that landed between the calls is returned by the next one.

Errors

Problems come back as tool results with isError: true and a one-line fix the model can act on or relay, never as protocol errors. For example:

Set RECEIVER_API_KEY to a project API key (recv_live_...). Create one in your project's settings at receiver.email.

Next Steps