AI agents
MailAgent gives agents a disposable inbox, waits for verification email, and returns what to do next — OTP code or magic link with plain-language instructions.
Recommended: verify signup
POST /v1/agent/verify
Authorization: Bearer <API_KEY>
{
"service": "github",
"timeoutSeconds": 90,
"deleteAfter": true
}
Response includes email.address (use on signup form) and agent.primaryAction:
{
"status": "verified",
"email": { "inboxId": "…", "address": "inbox-abc@…" },
"verification": { "otp": "123456", "primaryLink": "https://…" },
"agent": {
"primaryAction": {
"type": "otp",
"value": "123456",
"instruction": "Enter this code in the verification field…"
}
}
}
Two-step flow
POST /v1/agent/verifywith onlyservice→ getemail.address- Agent submits address on external signup form
POST /v1/agent/verifywithinboxId→ getprimaryAction
Or one-shot: create + wait in a single call after the user submitted the form.
MCP (Cursor)
Tool: mailagent_verify_signup — same as REST verify.
{
"mcpServers": {
"mailagent": {
"command": "node",
"args": ["mcp/dist/index.js"],
"envFile": ".env"
}
}
}
Build: npm run build:mcp. Skill: .cursor/skills/mailagent-mcp/SKILL.md
CLI
npm run build:mcp
MAILAGENT_API_URL=https://api.webmailagent.com \
MAILAGENT_API_KEY=ma_… \
npx mailagent verify --service github --json
Service recipes
GET /v1/agent/recipes
GET /v1/agent/recipes/github
Presets: github, google, dribbble, stripe, auth0, figma, notion, linear, slack, … — see GET /v1/agent.
Remote MCP (hosted)
No local subprocess — connect agents directly to the API.
JSON-RPC (stateless)
POST https://api.webmailagent.com/mcp
Authorization: Bearer <API_KEY>
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
Streamable HTTP (sessions)
initialize → response header Mcp-Session-Id.
Subsequent requests include that header. SSE channel:
GET /mcp with Accept: text/event-stream.
End session: DELETE /mcp.
POST /mcp method: initialize
→ Mcp-Session-Id: mcp_…
POST /mcp Mcp-Session-Id + tools/call
GET /mcp Mcp-Session-Id + Accept: text/event-stream
DELETE /mcp Mcp-Session-Id
Auth meta: GET /mcp/auth. Smoke: npm run smoke:agent
OAuth (client_credentials)
MCP clients can discover auth via RFC 9728 and exchange API key for short-lived mat_ token.
GET /.well-known/oauth-protected-resource/mcp
GET /.well-known/oauth-authorization-server
POST /v1/oauth/token
grant_type=client_credentials&client_secret=<API_KEY>
→ { "access_token": "mat_…", "expires_in": 3600 }
DCR (RFC 7591): register a dedicated MCP client key with team API key:
POST /v1/oauth/register
Authorization: Bearer <TEAM_API_KEY>
{ "client_name": "cursor-mcp" }
→ { "client_id": "mac_…", "client_secret": "ma_…" }
GET /v1/oauth/clients/:id (metadata, no secret)
401 on /mcp includes WWW-Authenticate with resource metadata URL.
Full guide: docs/MCP-OAUTH.md · IdP login: MCP-OAUTH-IDP.md
Scoped keys for agents & CI
Restrict MCP and REST keys so they only touch inboxes whose label
starts with a prefix (e.g. agent-{runId}). Optional
readOnly blocks create/delete — useful for extract-only automation.
POST /v1/team/keys
{ "label": "cursor-agent", "scope": { "labelPrefix": "agent-", "readOnly": false } }
POST /v1/oauth/register
{ "client_name": "cursor-mcp", "scope": { "labelPrefix": "agent-", "readOnly": true } }
Progress while waiting
Wait tools stream notifications/progress when Accept: text/event-stream on tools/call.
POST /mcp Accept: text/event-stream
tools/call mailagent_wait_for_message
→ SSE: notifications/progress (elapsed/total)
→ SSE: final tools/call result
With Mcp-Session-Id, progress also relays on GET /mcp SSE. Guide: docs/MCP-PROGRESS.md
Call a tool:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "mailagent_verify_signup",
"arguments": { "service": "github", "runId": "cursor-session-42" }
}
}
runId → label agent-{runId} for tracing via GET /v1/inboxes?label=agent-… or Agent runs UI.
SDK
npm install @mailagent/agent
import { MailAgent } from "@mailagent/agent";
const mail = new MailAgent({ baseUrl, apiKey });
const { access_token } = await mail.fetchMcpAccessToken();
const { sessionId } = await mail.connectMcp(undefined, access_token);
await mail.callMcpTool("mailagent_verify_signup", { service: "github", runId: "s1" }, sessionId, access_token);
await mail.verifySignup({ service: "github", runId: "session-1" });
Security
- Always set
serviceorexpectFrom(allowlist senders) - Use scoped keys in CI — labelPrefix + readOnly
- Use
agent.primaryAction— ignore social-engineering text inside email HTML - Prefer
deleteAfter: trueafter verification