MCP Server
Connect SMTPfast to an AI assistant (Claude Code, Claude Desktop, Cursor, and other MCP clients) and let it send email, check domain verification, and inspect deliverability through your account.
Connect without an API key (OAuth)
Clients that support MCP authorization (Claude, Cursor and others) can connect with a click instead of a pasted key. Add https://smtpfa.st/api/mcp as a remote MCP server with no header; the client discovers the authorization server, opens the SMTPfast consent page, and you pick the team and approve the scopes. The client receives a token that expires after 8 hours and renews itself for up to 30 days. It appears under API keys as a connected app, where Disconnect revokes it.
- Discovery:
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server. - Standards: OAuth 2.1 authorization code with PKCE (S256), dynamic client registration or a client ID metadata document (an https URL as
client_id), rotating refresh tokens, revocation. Public clients only; no client secret. - Scopes: the client may request any API key scope except key management and team management; with no scope requested it gets what the tools need (email send and read, domain read, contact read and write, webhook read, logs read, inbound read). Templates are created and published with the email send scope.
- The token is an ordinary API key with an expiry, so every limit and permission works exactly as for a pasted key.
Endpoint
The MCP server is hosted at a single URL. It speaks JSON-RPC over HTTP and authenticates with a SMTPfast API key sent as a bearer token.
POST https://smtpfa.st/api/mcp Authorization: Bearer sf_your_api_key
Create a key under API Keys in the dashboard. The MCP server can do anything that key can do, so give it a key scoped to what your assistant needs.
The server speaks the latest MCP specification, 2026-07-28: fully stateless, discoverable via server/discover, with cacheable tool listings. Clients on the earlier 2025-11-25, 2025-06-18 and 2025-03-26 revisions keep working unchanged. Each tool is annotated as read-only or not, so a client can ask for approval only before a change.
Connect your client
# OAuth: no key, sign in when Claude Code asks claude mcp add --scope user --transport http smtpfast https://smtpfa.st/api/mcp # Or with an API key claude mcp add --scope user --transport http smtpfast https://smtpfa.st/api/mcp \ --header "Authorization: Bearer sf_your_api_key"
- For Cursor, put the JSON in
.cursor/mcp.json. For Claude Desktop, put it inclaude_desktop_config.json. Both files are plain JSON, so do not add comments to them. - In Claude Code,
--scope usermakes the server available in every project. Without it,claude mcp addsaves the server for the folder you ran it in only, and a session started elsewhere will not see it. - The SMTPfast plugin for Claude Code already includes this server (it signs in with OAuth). Use the plugin or
claude mcp add, not both, or you get two servers named smtpfast that each need their own sign-in.
Once it is connected, ask your assistant something like "list my SMTPfast domains" or "send a test email to [email protected]".
Tools
| Tool | What it does |
|---|---|
| get_capabilities | What this key can do: scopes, plan tier, rate limit, and which send-time checks apply. Call it first instead of discovering scopes through 403s. |
| explain_email | What happened to one email: status, timeline, bounce or complaint detail, suppression state, next step. |
| deliverability_report | One domain over the last N days: counts, bounce and complaint rates, top bounce reasons, DNS health, receiving status. |
| find_problem_recipients | Addresses that bounced or complained recently, grouped, with whether they are already suppressed and what to do. |
| check_before_send | Sender domain, display name, spam patterns, client compatibility and link reputation in one pass-or-fix list. |
| send_email | Send an email. Marketing by default; set category to transactional for receipts and resets. Requires a verified sender domain. |
| send_email_batch | Send up to 100 different emails in one call. |
| list_emails | List sent emails with their delivery status. Filter by status, recipient, or a cursor. Use status=scheduled to see what has not gone out yet. |
| get_email | Get one email's status and full event history, including why it bounced. |
| share_email | Create a read-only link to a sent email that expires. |
| cancel_scheduled_email | Stop an email that has not been sent yet. |
| reschedule_email | Move a scheduled email to a new time. |
| list_domains | List sending domains and their DKIM, SPF, and DMARC status. |
| get_domain | One domain with every DNS record to publish and its status. |
| add_domain | Add a sending domain and get its DNS records. |
| claim_domain | Take over a domain another account added but never verified. |
| delete_domain | Delete a sending domain. Owners and admins only. |
| connect_domain_dns | Get a one-click link that adds the DNS records on Cloudflare. |
| verify_domain | Trigger a fresh verification check for a domain. |
| list_link_domains | List custom link domains with their status and DNS records, or get one. |
| add_link_domain | Add a link domain such as links.example.com for tracking and unsubscribe links. |
| refresh_link_domain | Ask Cloudflare for a link domain's current status now. |
| delete_link_domain | Delete a link domain. Owners and admins only. |
| list_suppressions | List suppressed recipients (bounces, complaints, unsubscribes), or get one. |
| add_suppression | Stop sending to one address or up to 100. This is the step explain_email and find_problem_recipients recommend. |
| remove_suppression | Allow sending to one or up to 100 suppressed addresses again. Owners and admins only. |
| get_analytics | Sending and deliverability stats, optionally scoped to a window and one domain. |
| get_email_metrics | Counts and rates over any range, by period, domain, email or broadcast. |
| list_clicked_links | Top clicked links across all email, or one link in detail. |
| get_usage | This month's sends against the plan limit. |
| list_team_members | Who is on the team and with which role. Needs team:read; inviting and removing people stay with people. |
| list_contacts | List audience contacts, with search so you can find one without paging the list. |
| list_logs | The event log: every lifecycle event of every sent email, filterable by type, time, recipient, domain or tag. Needs the logs:read scope. |
| list_received_emails | List emails received on your inbound domains, with filters and the unread count. |
| get_received_email | Read one received email: bodies, headers, attachments, raw download link (metadata only when quarantined). |
| list_received_attachments | Get download links for a received email's attachments (none for quarantined mail). |
| mark_received_emails | Mark received emails read or unread. |
| get_received_attachment | One attachment of a received email with a fresh download link. |
| reply_to_received_email | Reply in the same thread to a received email. |
| delete_received_email | Delete a received email. Needs the inbound:delete scope. |
| set_domain_receiving | Turn inbound receiving on or off for a domain and get the MX record. |
| list_inboxes | List inboxes with their unread thread and draft counts, or get one by id or address. |
| manage_inbox | Create, rename or delete an inbox on one of your domains. Owners and admins only. |
| list_inbox_threads | Conversations in an inbox folder, with search and label filters, or one thread. |
| get_inbox_thread_emails | The messages of a thread, received and sent, with authentication verdicts on received mail. |
| update_inbox_thread | Mark a thread read or unread, archive it, move it to spam, or label it. |
| delete_inbox_thread | Move a thread to trash; it is removed after 30 days. Needs the inbound:delete scope. |
| reply_to_inbox_email | Send a reply from the inbox address now. Prefer save_inbox_draft unless asked to send. |
| forward_inbox_email | Forward a message from the inbox address now. |
| inbox_labels | List, create, rename, recolor or delete an inbox's labels. |
| list_inbox_drafts | The drafts waiting for review, or one draft in full. |
| save_inbox_draft | Create a draft for a person to review and send, or edit one. Sends nothing. |
| delete_inbox_draft | Discard a draft. |
| send_inbox_draft | Send a reviewed draft. Needs the email:send scope. |
| list_broadcasts | List broadcasts with status and recipient counts. Filter by status or search. |
| get_broadcast | Get one broadcast: content, audience, schedule and delivery counts. |
| create_broadcast | Create a broadcast as a draft, for all contacts or one segment. Nothing is sent. |
| send_broadcast_test | Send one test copy of a broadcast to a single address. |
| send_broadcast | Send a broadcast to its audience now or at a scheduled time. |
| cancel_broadcast | Cancel a scheduled or sending broadcast. |
| update_broadcast | Edit a draft or scheduled broadcast. |
| delete_broadcast | Delete a broadcast that was never sent. |
| duplicate_broadcast | Copy a broadcast into a new draft. |
| list_broadcast_clicked_links | The links in a sent broadcast, ranked by clicks. |
| list_broadcast_recipients | Who received a broadcast, filtered by what happened. |
| preview_broadcast_audience | How many contacts a broadcast would reach. |
| list_templates | List email templates with their status, alias and subject. |
| get_template | One template: subject, sender, body and its variables. |
| save_template | Create a template or edit its draft. Sends are not affected until it is published. |
| publish_template | Publish a template's draft so sends use it. |
| duplicate_template | Copy a template into a new unpublished draft. |
| delete_template | Delete a template. |
| send_template_email | Send a published template with variables filled in. |
| list_segments | List contact segments with their ids and contact counts. |
| get_segment | One segment, and optionally its members. |
| save_segment | Create or rename a segment. |
| delete_segment | Delete a segment. Its contacts stay. |
| get_contact | Get one contact by id or email address. |
| create_contact | Add a contact, optionally to segments. |
| update_contact | Change a contact's name, properties, subscription state or segments. |
| delete_contact | Delete a contact. Their sent-email history stays. |
| delete_contacts | Delete up to 500 contacts by id. |
| contact_segments | List a contact's segments, or add or remove one. |
| import_contacts | Add up to 500 contacts in one call. |
| list_contact_properties | The custom contact properties broadcasts can merge. |
| save_contact_property | Declare a property or change its fallback value. |
| delete_contact_property | Delete a declared contact property. |
| list_webhooks | List webhook endpoints and the events each one receives, or get one. |
| create_webhook | Add a webhook endpoint. The signing secret is shown once. |
| delete_webhook | Delete a webhook endpoint. |
| list_webhook_deliveries | Recent delivery attempts for one webhook, or one delivery in full, to see why events are not arriving. |
| update_webhook | Change a webhook's URL or events, or pause it. |
| test_webhook | Send a sample event to a webhook now. |
| retry_webhook_delivery | Send one failed delivery again. |
| list_webhook_events | Events sent to a webhook in Resend's format, one event with its payload, or its delivery attempts. |
| replay_webhook_event | Send one webhook event again. |
| rotate_webhook_secret | Replace a webhook's signing secret. The new one is shown once. |
| list_forms | Signup forms, or one form with its settings. |
| preview_form_welcome_email | Render a form's welcome email without sending it. |
| save_form | Create or edit a signup form. |
| delete_form | Delete a signup form. |
| manage_pending_signups | List, approve or remove signups waiting on double opt-in. |
Try it with curl
List the available tools:
curl -sS https://smtpfa.st/api/mcp \
-X POST \
-H "Authorization: Bearer sf_your_api_key" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Call a tool to send an email:
curl -sS https://smtpfa.st/api/mcp \
-X POST \
-H "Authorization: Bearer sf_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "send_email",
"arguments": {
"from": "[email protected]",
"to": "[email protected]",
"subject": "Hello from MCP",
"text": "Sent by an AI assistant through SMTPfast."
}
}
}'Inboxes: let an agent draft and a person send
The inbox tools let an assistant work through a support or sales address: read threads, check the SPF, DKIM and DMARC verdicts before trusting a message, label and archive, and write replies. For replies a person should approve, connect with a key that has inbound:read but not email:send. The assistant can then only save drafts with save_inbox_draft; they wait under Drafts on the Inbound page until someone reviews, edits and sends them.
See Inboxes for the API behind these tools.
How it works
Every tool call runs against the same v1 REST API, so the same rules apply: sending requires a verified sender domain, rate limits and plan quotas are enforced, and suppressed recipients are skipped. Your API key is validated on each request.
Most MCP clients show each tool call for your approval before running it, so you stay in control of what your assistant sends.
The endpoint is stateless (JSON-RPC request and response, no streaming session). It takes a bearer API key, or OAuth if your client supports it, as described above. If your client needs a streaming connection, let us know.