MCP email tools explained
A plain explanation of MCP email tools: what a tool is in the protocol, the seven an email server needs, and why waiting and asserting belong on the server side.
On this page
An MCP email tool is a single named function that an AI coding agent can call to do exactly one thing with email: create an inbox, wait for a message, read it, assert on it, or delete it. MCP email tools are not a mail client and not an SMTP library. They are a small typed vocabulary a model can invoke mid task, so the agent building your signup flow receives the real verification email instead of guessing what it would have said.
What “tool” means in this protocol
The Model Context Protocol is a JSON-RPC 2.0 layer between an AI application (the host, for example Claude Code or Cursor) and a server that offers it context. Servers can expose three kinds of primitive, and tools are the executable one: functions the model may invoke to act on the outside world.
Each tool is three things. A name the model calls it by, a description the model reads to
decide whether it is the right one, and an inputSchema, a JSON Schema describing the
arguments. The client fetches the list with a tools/list request and runs one with
tools/call. If you want the wire level detail, how the Model Context Protocol works under
the hood walks through the same messages.
One rule matters more than it looks. When a tool fails for a business reason, the spec says to
return a normal result with isError: true and a text explanation, not a JSON-RPC error. The
model reads that text and can correct itself. Protocol errors stay reserved for unknown tools
and malformed arguments.
The seven tools an email server actually needs
InboxDome’s MCP server exposes seven, and the count is not arbitrary. Each one exists because an agent testing a signup flow gets stuck without it.
create_inboxreturns an inbox id and a real address. Optionaldomainpins the receiving domain, optionalttlSecondssets the lifetime, default 3600.wait_for_emaillong polls one inbox until something arrives.list_messageslists what an inbox holds, newest first.get_messagereturns one message in full: text and HTML body, detected OTP, extracted links, and SPF, DKIM and DMARC results.run_assertionswaits and then verifies, returning pass or fail per assertion.delete_inboxdestroys the inbox and its mail immediately.list_domainstells the agent which receiving domains it may choose from.
Notice what is missing. There is no send_email, because InboxDome addresses are receive
only. Your application does the sending, which is the thing you wanted to test anyway.
Discovery is what makes them usable
An agent does not read your documentation. It reads the tool list. MCP email tools are picked
by the model, not by you, so the descriptions carry real weight: wait_for_email says it
long polls until an email, or an
email containing an OTP or verification code, arrives. That sentence is what makes a model
pick it over calling list_messages in a loop.
The InboxDome server also answers initialize and tools/list without any credentials, so a
client, a registry crawler, or a curious agent can inspect the surface first. Only the first
tools/call needs a key, and a keyless call gets back an explanation of how to obtain one.
Waiting is the hard part, so the server does it
Email is asynchronous, and that is where naive agent tooling falls apart. Given only a list messages tool, a model will poll, sleep, poll again, and spend its context window on empty arrays.
wait_for_email takes an inboxId, an optional since timestamp, a timeoutSeconds between
1 and 50 (default 30), and waitFor set to either message or otp. With waitFor set to
otp, the server holds the connection open until a message containing a verification code
lands, and returns the code already extracted. One call, one result, no sleep loop and no
regex improvised by a language model at 2am. The same idea applied to a whole flow is covered
in testing OTP verification end to end.
The 50 second ceiling is a practical limit on a single HTTP request, not a design opinion. An
agent waiting on a slow queue just calls again with since set to the previous timestamp.
Assertions belong in the tool, not in the model
The weakest link in agent driven testing is letting the model be the judge. If the agent reads an email and concludes that it looks correct, you have a vibe, not a test.
run_assertions moves that judgement to the server. It accepts an array of typed assertions:
{type:"otpPresent"}, {type:"containsText", text}, {type:"linkResponds", urlContains}, and
{type:"auth", check:"spf"|"dkim"|"dmarc", expect}. It waits for the message, then returns a
structured pass or fail for each one. The agent reports a result it did not author, and the
same assertions lift straight into CI through the Email Testing API reference without
being rewritten.
Where the limits are
MCP email tools inherit the limits of the service behind them. Three are worth knowing before you wire this into anything.
Retention is short on purpose. A consumer InboxDome inbox lasts 24 hours by default and can be extended to at most 7 days, then it is destroyed. These are throwaway inboxes for a test run, not an archive.
Keep a human in the loop. The specification is explicit that clients should be able to deny a tool invocation and should show tool inputs before sending them. That is sound advice for anything that touches a network, and it applies here.
Point it only at applications you own or are authorized to test. Picking between servers is its own question, and choosing an email MCP server covers the tradeoffs.
Connecting one
The InboxDome server speaks Streamable HTTP at https://inboxdome.com/mcp, so there is nothing
to install locally:
claude mcp add --transport http inboxdome https://inboxdome.com/mcp \
--header "Authorization: Bearer idk_live_..."
Any MCP client that takes JSON config works the same way, with type set to http and the
bearer token in headers. The full setup, including where to get your key, is in the MCP server guide.
Once connected, a signup test reads as four tool calls: create an inbox, fill the form with the address, wait for the OTP, assert on the welcome mail. That is the whole point of MCP email tools. The agent stops simulating email and starts receiving it.
Disclosure: InboxDome publishes this blog and makes the products it mentions. We describe what they do rather than promise results.
Key takeaways
- An MCP email tool is one named function with a JSON Schema, not a mail client. The agent discovers it with tools/list and runs it with tools/call.
- Seven tools cover the whole job: create an inbox, wait, list, read, assert, delete, and list the available domains.
- Waiting belongs on the server. A long poll of up to 50 seconds beats an agent that sleeps in a loop and burns context on nothing.
- Assertions belong on the server too, so a pass or fail is a returned value rather than a model reading an email and deciding it looks fine.
- InboxDome inboxes are receive only, so no MCP email tool can send mail from them. That limit is deliberate.
Sources
- MCP specification, Tools — Defines tools/list, tools/call, inputSchema and the isError result flag.
- MCP architecture overview — Hosts, clients, servers, and the stdio and Streamable HTTP transports.
- JSON-RPC 2.0 Specification — The request, notification and batch semantics MCP is built on.
Links last checked September 4, 2026.
Frequently asked questions
What is an MCP email tool?
It is a single named function that an MCP server exposes to an AI agent, described by a JSON Schema, that performs one email operation: create an inbox, wait for a message, read it, assert on it, or delete it.
Do I need an API key to see the tools?
No. The InboxDome MCP server answers initialize and tools/list without a key, so you or your agent can inspect it first. The first actual tool call explains where the free key comes from: a DevDome account.
Can an agent send email through these tools?
Not through InboxDome. Its inboxes are receive only by design, which is why the service cannot be used for spam or spoofing. If your test needs an outbound message, your application sends it and the tools read what arrives.
Why not just give the agent access to a real mailbox?
Because a real mailbox has real mail in it, no isolation between test runs, and no clean way to expire. A disposable inbox per run gives the agent an empty starting state and something safe to throw away.