Agents
MCP server
Give Claude, Cursor and any MCP client real inboxes — via OAuth 2.1 or an API key.
Every Squadmail instance serves a Model Context Protocol server at /mcp (Streamable HTTP). Agents can create inboxes, wait for mail, pull verification codes, label and send.
Connect
Claude Code
claude mcp add --transport http squadmail https://app.squadmail.dev/mcp
--header "Authorization: Bearer sqm_YOUR_KEY" claude.ai and Claude Desktop
Settings → Connectors → Add custom connector and enter https://app.squadmail.dev/mcp. You’ll be redirected to Squadmail to sign in, pick a workspace and approve scopes — no key required (OAuth 2.1 with dynamic client registration).
Cursor, Windsurf and other clients
{
"mcpServers": {
"squadmail": {
"url": "https://app.squadmail.dev/mcp",
"headers": { "Authorization": "Bearer sqm_YOUR_KEY" }
}
}
} Replace app.squadmail.dev with your own instance URL when self-hosting. The dashboard’s Agents & API page generates these snippets for you and shows a live “connected” indicator once your agent makes its first call.
Authentication
| Method | Best for | How |
|---|---|---|
| API key | Headless agents, CI, scripts | Authorization: Bearer sqm_… |
| OAuth 2.1 | claude.ai / Desktop connectors, user-facing apps | Discovery via /.well-known/oauth-protected-resource/mcp |
Both map to the same scopes: read, write, send (and admin for keys). A tool call without the required scope fails with insufficient_scope.
The typical flow
create_inboxwithttl_minutesfor a disposable address- use the address on the target website
get_verification— returns the OTP and/or magic link, waiting up to 120 s for the mail
❯ Sign up for acme.io and confirm the email.
⚙ create_inbox { ttl_minutes: 30, agent_name: "signup-bot" }
→ swift-otter-4821@acme-agents.com
⚙ get_verification { inbox: "swift-otter-4821@acme-agents.com" }
→ { code: "482913", link: "https://acme.io/verify?t=…" } Prompt
The server exposes a signup-flow prompt that walks the model through exactly this sequence.
Tool reference
Generated from the server’s own schemas.
create_inbox Create a new email inbox. Omit local_part for a random readable address. Set ttl_minutes for a disposable inbox that expires automatically.
local_part string | Local part before the @. Omit for a random, readable name like swift-otter-4821. |
domain string | Domain to use. Defaults to the first available domain. |
name string | Display name for the inbox. |
ttl_minutes integer | null | Minutes until the inbox expires and stops accepting mail. null = permanent (if allowed). |
agent_name string | Name of the agent using this inbox; shown in the dashboard. |
tags string[] | |
max_emails integer | null | |
overflow "drop_oldest" | "reject" | |
allow_senders string[] | Only accept mail from these addresses/domains. |
block_senders string[] | Reject mail from these addresses/domains. |
forward_to string (email) | null | Forward a copy of every incoming email to this address (counts as a sent email). |
list_inboxes read-only List inboxes of the organization (newest activity first).
q string | Filter by address, name or agent name. |
tag string | |
include_expired boolean | |
limit integer | Max: 200 |
get_inbox read-only Get details for one inbox, including expiry and counts.
inbox required string | Inbox id (inb_…) or full email address. |
extend_inbox Extend a disposable inbox by N minutes from now, or pass permanent=true to remove the expiry.
inbox required string | Inbox id (inb_…) or full email address. |
minutes integer | Max: 9007199254740991 |
permanent boolean |
delete_inbox destructiveDelete an inbox and all of its emails permanently.
inbox required string | Inbox id (inb_…) or full email address. |
list_emails read-only List or search emails, optionally limited to one inbox, a label, or unread mail.
inbox string | Inbox id or address. Omit to search all inboxes. |
q string | |
label string | Label key, e.g. "verification" or "spam". |
unread boolean | |
limit integer | Max: 100 |
get_email read-only Read one email: text body, extracted codes/links, labels and attachment list.
email_id required string | |
include_html boolean | |
mark_read boolean |
wait_for_email read-only Block until a new email arrives in the inbox (optionally matching sender/subject), then return it. Returns null on timeout.
inbox required string | Inbox id (inb_…) or full email address. |
timeout_seconds integer | Default 60. Max: 120 |
from string | Sender must contain this text. |
subject string | Case-insensitive regex for the subject. |
since string | ISO timestamp. Include emails received at/after this time (default: now). |
get_verification read-only Return the newest verification code (OTP) and/or magic/verify link from an inbox. Waits for a new email if none is present yet.
inbox required string | Inbox id (inb_…) or full email address. |
timeout_seconds integer | Max: 120 |
from string | |
since string | Only consider emails received after this ISO time. Default: last 10 minutes. |
get_attachment read-only Return an attachment. Text-like files are returned as text, others as base64 (max 2 MB).
email_id required string | |
attachment_id required string |
label_email Set the manual labels of an email (replaces existing labels). Use list_labels for valid keys.
email_id required string | |
labels required string[] |
list_labels read-only List the organization’s labels (spam, verification, custom ones…).
No parameters.
list_domains read-only Domains available for new inboxes.
No parameters.
send_email Send an email from one of your inboxes (requires the "send" scope). Use in_reply_to to reply to an email id. If the organization requires human approval, the email is queued: the result has status "pending" — tell the user and use get_send_status to wait for the decision. Add a short `reason` to help the approver.
to required string (email)[] | |
cc string (email)[] | |
subject required string | |
text required string | |
html string | |
in_reply_to string | Email id this message replies to (sets threading headers). |
reason string | Why this email should be sent. Shown to the human approver when approvals are on. |
inbox required string | Inbox id (inb_…) or full email address. |
get_send_status read-only Check an email requested with send_email. With wait_seconds, blocks until a human approves or rejects it (max 120 s). Status: pending, sent, rejected, failed or expired.
id required string | The id returned by send_email (out_…). |
wait_seconds integer | Max: 120 |