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

MethodBest forHow
API keyHeadless agents, CI, scriptsAuthorization: Bearer sqm_…
OAuth 2.1claude.ai / Desktop connectors, user-facing appsDiscovery 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

  1. create_inbox with ttl_minutes for a disposable address
  2. use the address on the target website
  3. 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 destructive

Delete 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
Edit this page on GitHub