MCP · AGENTS

Receive emails in Claude Code without IMAP or Gmail API

Claude Code is good at writing code that signs up for things. Stripe webhooks, GitHub apps, Supabase projects, your own SaaS. The wall it hits, every time, is the verification email. You can ask the agent to “check Gmail and grab the code”, but the standard answer is messy: connect via IMAP, parse a multipart MIME body, regex out the OTP, hope the message arrived before timeout.

The Model Context Protocol fixes the dead-end with one tool call. This post walks through wiring MailSink’s MCP server into Claude Code (and Claude Desktop, and Cursor - same recipe) so the agent reaches signup completion without ever touching IMAP or Gmail OAuth.

What changes when the agent has its own inbox

Without an MCP email server, agent verification looks like this:

agent → fills signup form → submits → waits → ???
human → opens Gmail → finds OTP → pastes back to agent

The human is in the loop. The agent task isn’t autonomous.

With @mailsink/mcp configured, the same flow becomes:

agent → create_inbox → fills signup form (uses returned address)
      → wait_for_email → reads OTP → submits verification

Two extra tool calls, no human. The whole signup completes inside one Claude Code conversation.

Setup: 4 minutes

1. Get a free MailSink API key

Either route works:

Copy the msk_… key. You’ll paste it into the MCP config below.

2. Add the MCP server to Claude Code

Claude Code reads MCP servers from ~/.claude.json under each project’s mcpServers block. Add this entry:

{
  "mcpServers": {
    "mailsink": {
      "command": "npx",
      "args": ["-y", "@mailsink/mcp"],
      "env": {
        "MAILSINK_API_KEY": "msk_your_key_here"
      }
    }
  }
}

That’s it. Restart Claude Code, open a session, and the mailsink:* tools become available.

For Cursor, the file is .cursor/mcp.json in your project. Same JSON shape.

For Claude Desktop, the file is claude_desktop_config.json (path depends on OS - check Settings → Developer → Edit Config). Same JSON shape.

3. Verify the agent sees the tools

In Claude Code, ask:

List the tools you have available from the mailsink MCP server.

The agent should respond with eight tools: create_inbox, list_inboxes, list_messages, wait_for_email, get_verification_code, get_verification_link, get_message, delete_inbox.

If you see “no tools” or “mcp server failed to start”, check the Claude Code MCP log (in Claude Code: /mcp shows status; toggle DEBUG via --mcp-debug flag for full output).

A real signup flow, end to end

Here’s an actual prompt I run to verify the wiring:

Sign me up for a Vercel free account using a MailSink test inbox. Use the mailsink MCP server to provision the inbox, fill the signup form with the address it gives you, then poll for the verification code and complete the signup. Walk me through what you’re doing.

What the agent does (verbatim from a real session):

  1. Calls mailsink:create_inbox({ local_part: "vercel-test" }). Gets back [email protected] and the inbox id.
  2. Opens vercel.com/signup, types the address into the email field, submits.
  3. Calls mailsink:wait_for_email({ inbox_id: "inb_xxx", timeout: 60 }). Long-polls for up to 60 seconds.
  4. Email arrives. Agent calls mailsink:get_verification_code({ inbox_id }). Returns 847291 (or whatever Vercel sent).
  5. Pastes the code into Vercel’s confirmation page. Account created.
  6. Calls mailsink:delete_inbox({ inbox_id }) to clean up.

Total agent time: ~25 seconds. No human input after the initial prompt.

Why this beats the IMAP route

I tried the IMAP path first. Here’s what kills it for agent workflows:

Auth is heavy. Gmail IMAP via app-specific password works but locks you to one account. OAuth is 4-step. Both require the agent to handle credentials it shouldn’t see.

Folder structure varies. New mail in INBOX, but spam in [Gmail]/Spam, promotional in Updates, etc. The agent has to know your filtering setup. Brittle.

MIME parsing is its own bug surface. Verification emails come in multipart/alternative with HTML and plaintext branches. The plaintext branch sometimes truncates the OTP. The HTML branch has the OTP wrapped in inline styles and <wbr> tags. Regex against either is fragile.

Polling cost. IMAP IDLE keeps a connection open but doesn’t survive cold-start serverless. Polling every 5s burns API quota.

Concurrency is messy. If two parallel agent tasks share the same Gmail account, they fight over which message belongs to which task.

MailSink sidesteps all five. The agent gets a fresh inbox per task. Auth is a single Bearer token. Extraction is server-side. Long-poll is built into the API. Concurrency is one-inbox-per-task by design.

Cost vs Gmail API

For a side-by-side at agent-relevant volume:

PathCost / 1000 verifications
Gmail API (free tier)$0, but 1 quota unit per request and 250 units/sec rate cap
Gmail API (Workspace)$6/user/mo + dev time wiring OAuth
MailSink Free$0 (50/month)
MailSink Pro$15/mo (2,000/month)
MailSink Team$49/mo (20,000/month)

If you’re on the free Gmail tier and the agent runs more than ~250 verifications per second, you’ll hit quota limits and have to negotiate up. MailSink Pro covers most agent + CI workloads in a flat $15.

What MailSink doesn’t do

To be straight: this is receive-only and short-TTL by default.

For the verification-code-from-an-agent use case, those constraints are exactly the right shape. Anything more would be over-engineered.

Common follow-up questions

Can the agent see the full email body, not just the OTP?

Yes. get_message({ message_id }) returns the full text + HTML. Use it when the OTP is embedded in a magic link or you need to assert subject/sender.

Does this work in Claude Code’s autonomous mode (--print / non-interactive)?

Yes. MCP servers initialize regardless of interaction mode. The agent uses tools the same way.

What happens to the inbox if the agent crashes mid-task?

Inboxes auto-expire on TTL. Free tier = 1 hour. The cron worker GCs them server-side; nothing leaks.

Can two Claude Code sessions share an inbox?

They can, but don’t. Each task should create_inbox once, finish, delete_inbox. That keeps the per-task isolation that makes parallel agent runs work.

Can I use this with Anthropic SDK directly (not Claude Code)?

Yes. @mailsink/mcp is a standard MCP server. Wire it into any MCP-aware client: Anthropic SDK with computer-use, Anthropic Managed Agents, n8n, LangChain, Cursor, Continue.dev. The setup file shape changes; the tools are identical.

Try it

Pick a flow you’ve been wanting to automate but kept stalling at the email step. Wire MailSink in via the JSON above. Ask Claude Code to run it. The verification step that used to need you in the loop now just works.

If something’s broken or the docs miss something, ping [email protected]. I read it.

Next