There's a real difference between an API an agent can call and an API an agent knows how to call. A REST endpoint needs the model to hold the base URL, the auth header shape, the JSON body and the response schema in context, and to get all four right in one shot. A tool definition hands it those for free, from the protocol.
That's the whole argument for MCP here. An inbox is a small enough surface that the tool list is the documentation.
Wiring it up
apumail ships an MCP descriptor at /.well-known/mcp.json. For a client
that reads descriptors, pointing it at the origin is enough:
https://api.apumail.com/.well-known/mcp.json
No install step, no package to pull, no key to provision first — the inbox tools
that need auth take the inbox token that create_inbox hands back.
The 9 tools
They fall into three groups, and the grouping is the mental model:
Get an address
create_inbox— provisions a random-slug inbox, returns the address and its token. No auth. This is the entry point.get_inbox— inbox metadata and TTL state.
Receive
list_mails— everything currently in the inbox.read_mail— one message, full body, sanitized.wait_for_mail— the important one. Blocks until a mail lands. This is what keeps the agent from burning a model round-trip per poll.extract_latest_otp— the code from the newest message, already pulled out server-side.
Send
send_mail— reply from the same address. Thefromis forced to the authenticated inbox, so a leaked token can't spoof anyone.
Plus wait_for_sms and extract_latest_sms_otp on the paid
tier, which do exactly what their email counterparts do — same wait/extract shape, phone
numbers instead of addresses.
What the flow looks like as tools
The signup dance that was three curl calls in the OTP post collapses to this:
create_inbox→ agent getsvivid-llama-4a2c@apumail.com- agent types that address into the form it's working on
wait_for_mail→ blocks, returns when the confirm landsextract_latest_otp→"482910"
Nothing in there is apumail-specific reasoning. The model doesn't need to know what
apumail is — it needs to know there's a tool called wait_for_mail,
which the protocol already told it.
When to skip MCP
Honestly: if you're writing a test suite, use the REST API. MCP earns its keep when
the caller is a model deciding what to do next. When the caller is your CI pipeline
running a known script, the endpoints are simpler and there's no protocol in the way.
Both hit the same backend, so mixing them is fine — provision over REST in a fixture,
hand the address to the agent, let it wait_for_mail over MCP.
The descriptor is the docs
If you want to read the surface before wiring anything, three URLs answer everything:
- /.well-known/mcp.json — the MCP descriptor
- /openapi.json — OpenAPI 3.1 for the REST side
- /llms.txt — the same thing in Markdown, written for a model to read top to bottom