echo.email MCP server
The MCP server gives AI agents the echo.email test: create an address,
send one email to the address, wait for the report. The server is free,
with no key and no signup. The registry lists the server as
email.echo/deliverability.
Connect
Server URL, Streamable HTTP transport:
https://mcp.echo.email/mcp
Claude Code:
claude mcp add --transport http echo-email https://mcp.echo.email/mcp
Clients with a JSON configuration:
{
"mcpServers": {
"echo-email": { "type": "http", "url": "https://mcp.echo.email/mcp" }
}
}
Tools
| Tool | Arguments | Result |
|---|---|---|
create_test_address | none | address, token, key,
idle_timeout_s, status_url |
wait_for_report | token,
key, timeout_s (1 to 50, default 45) |
status waiting or received (call again),
or done with report_id,
report_url and a digest |
get_report | report_id |
the digest plus the full report as JSON |
The digest holds the score, SPF, DKIM, DMARC, TLS, IPv6 readiness and
the failing sender requirements. Every result carries the data twice: as
JSON text in content and as structuredContent.
Typical run
- The agent calls
create_test_address. - The agent sends one email to the address, through the application or mail server under test.
- The agent calls
wait_for_reportuntil the status isdone. - For details, the agent calls
get_report.
The address stays alive while wait_for_report runs and
for 10 minutes after the last call. Each address accepts one message,
and reports are deleted after 24 hours.
Protocol
The server follows MCP 2026-07-28 and answers every request statelessly
with a single JSON response. There is no handshake and no session. Each
request carries the protocol version and the client details in
_meta, and the HTTP headers repeat the version, the method
and, for tools/call, the tool name. A tool name outside plain
ASCII goes in Mcp-Name as =?base64?…?=.
POST /mcp HTTP/1.1
Host: mcp.echo.email
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: wait_for_report
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "wait_for_report",
"arguments": {
"token": "lake.mother.column",
"key": "q3k7…",
"timeout_s": 45
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "my-agent",
"version": "1.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
Every result carries resultType and the server details
in _meta:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "{ \"status\": \"done\", … }"
}
],
"structuredContent": {
"status": "done",
"report_id": "…",
"report_url": "https://echo.email/r/…",
"digest": {
"score": "8/9"
}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "echo.email",
"version": "1.1.0"
}
}
}
}
server/discover returns the supported versions, the
capabilities and the instructions. server/discover and
tools/list results add ttlMs (one hour) and
cacheScope, because the tool list only changes on a
release.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": [
"2026-07-28",
"2025-11-25",
"2025-06-18",
"2025-03-26",
"2024-11-05"
],
"capabilities": {
"tools": {
"listChanged": false
}
},
"instructions": "Create a test address, send one email to it, then wait for the report.",
"ttlMs": 3600000,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "echo.email",
"version": "1.1.0"
}
}
}
}
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | -32020 | A required header is missing or differs from the body |
| 400 | -32022 | Unsupported protocol
version. The error data lists supported and
requested |
| 404 | -32601 | Unknown method |
| 200 | -32602 | Unknown tool |
| 403 | An Origin header from another
site | |
| 405 | GET or DELETE on the endpoint | |
| 202 | A notification, accepted with an empty body |
Rate limits and dead addresses come back as tool results with
isError: true and a message the agent acts on. Each IP
address gets 30 new addresses and 120 status or report requests per
minute, and every poll inside wait_for_report counts as one
request.
Older clients
Clients built for earlier MCP versions connect through the
initialize handshake, with versions 2025-11-25, 2025-06-18,
2025-03-26 and 2024-11-05. A request without the version header counts
as 2025-03-26. These clients also get ping. The tools and
the results are the same in both cases.
API
Scripts and CI jobs use the same flow through the echo.email API.