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.
| Variable | Description |
|---|---|
RECEIVER_API_KEY | Required. The project the tools work in comes from the key. |
RECEIVER_API_URL | Optional. Defaults to https://api.receiver.email/api/v1. |
Install
Claude Code
claude mcp add receiver \
-e RECEIVER_API_KEY=recv_live_your_key \
-- npx -y @receiverdotemail/mcpAdd --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:
{
"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:
{
"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.
| Input | Type | Description |
|---|---|---|
prefix | string, optional | Start 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. |
{ "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.
| Input | Type | Description |
|---|---|---|
address | string | The address to wait on. |
since | ISO 8601, optional | Only mail received strictly after this time. Use the since from create_inbox. Default: the last 60 seconds. |
timeoutSeconds | number, optional | How long to wait. Default 60, max 300. |
extract | "otp" | "links" | "none" | Also return the verification code, or the links. Default "none". |
{ "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
| Input | Type | Description |
|---|---|---|
address | string, optional | Only mail to this address. Default: the whole project. |
limit | number, optional | Default 10, max 50. |
{ "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
| Input | Type | Description |
|---|---|---|
id | string | An email id from wait_for_email or list_emails. |
format | "text" | "html" | Which body to return. Default "text". |
{ "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
sincethatcreate_inboxreturned. Mail from before the address existed can never match. - Next email: wait from the
receivedAtof 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:
{ "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
- Give your agent an inbox: the end-to-end guide
- CLI: the same operations from a shell
- REST API Reference: what the tools call