Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

dev.primitive/email

REMOTE · WWW.PRIMITIVE.DEV · SCANNED AUG 3

Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.

+8 this week 84 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score →

Endpoint Security97
  • The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
  • Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
  • HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
  • The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
  • DNSSEC is configured correctly; the domain's records validate against the full chain to the root. View diagnostics → Pass
  • The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents. View diagnostics → Partial
Transport & Reachability100
Schema Quality & AI Usability84
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (good).Pass
  • Tool/resource definitions use about 2978 tokens (~99/item across 30 items; 29 tools + 1 resources), lean.Pass
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management27
  • Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage97
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 91% of tool parameters carry a description.Partial
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
  • Supports UI / widget rendering.Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

remote · www.primitive.dev

# add to Claude Code
claude mcp add --transport http dev-primitive-email https://www.primitive.dev/mcp
# ~/.codex/config.toml
[mcp_servers.dev-primitive-email]
url = "https://www.primitive.dev/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "dev-primitive-email": {
      "type": "remote",
      "url": "https://www.primitive.dev/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add dev-primitive-email --url https://www.primitive.dev/mcp --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  dev-primitive-email:
    url: "https://www.primitive.dev/mcp"
// mcp.json
{
  "mcpServers": {
    "dev-primitive-email": {
      "type": "http",
      "url": "https://www.primitive.dev/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 2 Aug 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

  • 1 Aug 26 +5
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 31 Jul 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 29 Jul 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

  • 28 Jul 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

  • 27 Jul 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 26 Jul 26 76

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 3 Aug 2026 · Probed https://www.primitive.dev/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=primitive.dev CN=YE2,O=Let's Encrypt,C=US 1 Aug 2026 30 Oct 2026 ECDSA 256 ECDSA-SHA384 6fbed9ebd59789d8bd951e2445d19856f00
SANs: *.primitive.dev, primitive.dev
CN=YE2,O=Let's Encrypt,C=US (CA) CN=Root YE,O=ISRG,C=US 3 Sept 2025 2 Sept 2028 ECDSA 384 ECDSA-SHA384 4df3b15dd6c0784c507cd37b58e6f115
CN=Root YE,O=ISRG,C=US (CA) CN=ISRG Root X2,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 ECDSA-SHA384 872165fc34b6e5fba8add5b3705fb53a
CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) CN=ISRG Root X1,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 SHA256-RSA 6c8f1dc727c7117f7baf853ac980f9cd
DNSSEC secure

Validation of www.primitive.dev. Secure

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
dev. present 60074 8 Verified
primitive.dev. present 2371 13 Verified
www.primitive.dev. Verified address RRset verified with the apex keys
Authentication Enforced and verified

The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.

Result Enforced and verified
Enforced On tool calls
HTTP status 200

WWW-Authenticate challenge Bearer realm="Primitive MCP", resource_metadata="https://www.primitive.dev/.well-known/oauth-protected-resource/mcp", error="invalid_token", error_description="Bearer token required for /mcp"

Bearer realm="Primitive MCP", resource_metadata="https://www.primitive.dev/.well-known/oauth-protected-resource/mcp", error="invalid_token", error_description="Bearer token required for /mcp"
Header Value
strict-transport-security max-age=63072000; includeSubDomains
content-security-policy base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'
x-content-type-options nosniff
x-frame-options DENY
referrer-policy strict-origin-when-cross-origin
permissions-policy accelerometer=(), bluetooth=(), browsing-topics=(), camera=(), geolocation=(), gyroscope=(), hid=(), magnetometer=(), microphone=(), payment=(), serial=(), usb=()

Protected resource metadata

Document https://www.primitive.dev/.well-known/oauth-protected-resource/mcp
Retrieved Yes
Resource https://www.primitive.dev/mcp
Authorisation server https://www.primitive.dev
Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://www.primitive.dev/mcp Verified 200
http (plaintext) http://www.primitive.dev/mcp HTTPS enforced 301 https://www.primitive.dev/mcp
MCP tools — 29 exposed · ~2,850 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
addDomain ~72

Claim a new domain and receive the DNS records to publish. Returns dns_records with the exact records to add. If the domain has an mx_conflict (existing mail provider), re-call with confirmed: true to proceed. After publishing DNS records, call verifyDomain to complete setup.

NameTypeReqDescription
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

awaitReply ~183

Get the threaded reply to a sent email — the canonical 'did they reply yet?' call. Pass the sent email's id (from a sendEmail response). With wait=true it long-polls up to wait_timeout_ms for the reply to arrive (synchronous agent-to-agent chat); with wait=false (default) it returns immediately with the reply if one has arrived, else reply=null. Matches on the reply's threading, not a from/subject guess.

NameTypeReqDescription
idstringyesThe sent email id to fetch the reply for (from a sendEmail/replyToEmail response).
waitstringWhen "true", long-poll until a reply arrives or wait_timeout_ms elapses. Default no-wait.
wait_timeout_msnumberHow long to wait when wait=true (1000–30000 ms, default 10000).
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

cancelScheduledSend ~93

Cancel a still-scheduled send before it dispatches (terminal status "canceled"; the same idempotency key becomes reusable). Pass the sent email id from a sendEmail response that used scheduled_at, or from listSentEmails. Returns a conflict error once the send has already started dispatching.

NameTypeReqDescription
idstringyesSent email ID of the scheduled send, from a sendEmail response or listSentEmails.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

createEndpoint ~61

Create a webhook endpoint to receive email.received events. If an endpoint with the same URL already exists but is deactivated, it is reactivated. After creating, call testEndpoint to confirm your signature verifier accepts the payload.

NameTypeReqDescription
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

createFilter ~38

Create a whitelist or blocklist filter rule. Patterns are stored lowercase. Per-domain filters require a Pro plan.

NameTypeReqDescription
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

deleteEndpoint ~37

Soft-delete a webhook endpoint. The endpoint will no longer receive deliveries.

NameTypeReqDescription
idstringyesEndpoint ID from listEndpoints or createEndpoint.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

deleteFilter ~29

Delete a filter rule.

NameTypeReqDescription
idstringyesFilter rule ID from listFilters or createFilter.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

downloadDomainZoneFile ~104

Download a BIND-format DNS zone file for a domain. Useful when users want to import all required DNS records at once rather than copying them individually. Returns plain text in BIND zone file format.

NameTypeReqDescription
idstringyesDomain ID from listDomains or addDomain.
outbound_onlybooleanWhen true, include only outbound DNS records (SPF, DKIM, DMARC). Defaults to all records for unverified domains, outbound-only for verified.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

downloadEmailAttachments ~94

Download all attachments for an inbound email as a gzip-compressed tar archive. Returns the archive as a base64-encoded string along with the attachment count and SHA-256 digest. Prefer getEmail first to check the attachment manifest before downloading.

NameTypeReqDescription
idstringyesInbound email ID.
tokenstringSigned download token from a webhook payload. Optional — the bearer token is used when this is omitted.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getAccount ~33

Use this when you need the authenticated Primitive account summary, including email, plan, onboarding state, and webhook secret rotation time.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getConversation ~103

Get the full conversation an inbound email belongs to as ordered, chat-model-ready turns with bodies. Each message is oldest-first with a direction (inbound/outbound) and a derived role (inbound→user, outbound→assistant). For a brand-new message, returns just that one turn. The response includes a truncated boolean (true when the message cap was reached) and a message_count field.

NameTypeReqDescription
idstringyesID of any inbound email in the conversation.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getEmail ~54

Use this when you need full details for one inbound email ID, including parsed bodies, threading metadata, SMTP envelope, webhook state, and replies.

NameTypeReqDescription
idstringyesInbound email ID from listEmails or searchEmails.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getInboxStatus ~37

Use this when the user asks whether inbound email is ready or needs setup. Returns domains, routes, deployed Functions, and recent inbound activity.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getOutboundStatus ~76

What can I send FROM? Lists this account's verified outbound (sendable) domains plus any domains still pending DNS verification, with next actions. Call this BEFORE sendEmail to pick a valid `from` domain — the account email is not necessarily sendable. The same sendable list is echoed in a cannot_send_from_domain error.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getSentEmail ~81

Get the full record for a single sent email by id, including body_text and body_html. Use to inspect delivery details for a specific send — e.g. the SMTP response on a bounced row, or the gate denial reason on a gate_denied row.

NameTypeReqDescription
idstringyesSent email ID from listSentEmails or a /send-mail response.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

getThread ~100

Get a conversation thread by id: metadata plus all inbound and outbound messages interleaved oldest-first. Each message has a direction (inbound/outbound) and id; fetch inbound message bodies via getEmail, or outbound bodies via getSentEmail. Discover thread_id from any email or sent-email record. Compare message_count against messages.length to detect truncation.

NameTypeReqDescription
idstringyesThread ID from the thread_id field on any email or sent-email.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listDomains ~45

List all inbound domains for the organization, both verified and unverified. Each domain includes its verification status and DNS records. Use before addDomain to check whether a domain is already claimed.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listEmails ~300

Use this when you need to browse inbound emails received at verified domains with cursor pagination, status filters, date filters, or sender/recipient search.

NameTypeReqDescription
cursorstringBackward (history) pagination cursor from a previous response's `meta.cursor` field: returns emails OLDER than this position, newest-first. Mutually exclusive with `since`.
date_fromstringInclusive lower bound on created_at (ISO 8601).
date_tostringInclusive upper bound on created_at (ISO 8601).
domain_idstringFilter to emails received on a specific verified domain.
limitnumberMaximum number of emails to return (1–100, default 50).
searchstringFree-text search across sender, recipient, and subject.
sincestringForward-tail cursor (a `meta.cursor` value, format `{ISO datetime}|{UUID}`): returns emails strictly NEWER than this position, oldest-first, for lossless polling of just-arrived mail. Mutually exclus…
statusstringFilter to emails in this processing status.
waitnumberLong-poll up to this many seconds (0–30, default 0) holding the request for new mail instead of returning an empty page immediately. Requires `since`. Returns as soon as matching mail arrives, or an…
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listEndpoints ~31

List all active webhook endpoints for the organization. Each endpoint shows its URL, enabled state, and optional domain restriction.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listFilters ~20

List all whitelist and blocklist filter rules for the organization.

Input schema present but exposes no named parameters.

NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listSentEmails ~229

List outbound emails sent by this org, with cursor pagination and filters. Bodies are omitted from list rows to keep responses small — use getSentEmail to fetch a specific row with full body. Useful for auditing delivery status, finding bounced sends, or checking gate-denied attempts.

NameTypeReqDescription
cursorstringPagination cursor from a previous response's `meta.cursor` field.
date_fromstringInclusive lower bound on created_at (ISO 8601).
date_tostringInclusive upper bound on created_at (ISO 8601).
idempotency_keystringFilter to rows with the given client idempotency key.
limitnumberMaximum number of sent emails to return (1–100, default 50).
request_idstringFilter to the row matching a specific server-issued request_id from a /send-mail response.
statusstringFilter to rows in this status. Use "scheduled" to find pending scheduled sends (cancelable via cancelScheduledSend) and "canceled" for ones already canceled.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

listWebhookDeliveries ~155

List webhook delivery attempts with pagination and filters. Each delivery includes the target endpoint and a nested email object with sender/recipient/subject. Useful for diagnosing delivery failures or confirming a specific email was delivered.

NameTypeReqDescription
cursorstringPagination cursor from a previous response's `meta.cursor` field.
date_fromstringInclusive lower bound on attempted_at (ISO 8601).
date_tostringInclusive upper bound on attempted_at (ISO 8601).
email_idstringFilter by inbound email ID.
limitnumberMaximum number of delivery records to return (1–100, default 50).
statusstringFilter to deliveries in this status.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

replayWebhookDelivery ~60

Re-send a stored webhook payload from a previous delivery attempt to its original endpoint. Rate limited per org (burst + sustained windows, shared budget with email webhook replays).

NameTypeReqDescription
idstringyesDelivery ID (numeric string from listWebhookDeliveries).
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

replyToEmail ~65

Use this when the user has selected a specific inbound email and confirmed a reply. Sends real outbound email with threading handled server-side.

NameTypeReqDescription
idstringyesInbound email ID to reply to. Threading headers are set server-side.
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

searchEmails ~383

Use this when you need to find inbound emails with structured filters or full-text matching. Use sort=received_at_asc plus date_from for new-mail polling.

NameTypeReqDescription
bodystringFilter to emails whose body contains this string.
cursorstringPagination cursor from a previous response's `meta.cursor` field.
date_fromstringInclusive lower bound on received_at (ISO 8601).
date_tostringInclusive upper bound on received_at (ISO 8601).
domain_idstringFilter to emails received on a specific verified domain.
fromstringFilter to emails from this sender address or domain.
has_attachmentstringFilter to emails that have ("true") or lack ("false") attachments.
include_facetsstringInclude aggregated facet counts (sender, domain, status) in the response (default true).
limitnumberMaximum number of emails to return (1–100, default 50).
qstringFull-text query matched across subject, body, sender, and recipient.
reply_to_sent_email_idstringFilter to inbound emails that are replies to a specific sent email ID.
snippetstringInclude a short body snippet in each result (default true).
sortstringSort order. Use received_at_asc with date_from for polling new mail.
spam_score_gtenumberFilter to emails with a spam score at or above this value.
spam_score_ltnumberFilter to emails with a spam score strictly below this value.
statusstringFilter to emails in this processing status.
subjectstringFilter to emails whose subject contains this string.
tostringFilter to emails addressed to this recipient.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

sendEmail ~90

Use this when the user has confirmed a new outbound email. Sends real email through Primitive's relay and can wait for the first SMTP delivery outcome, or schedule the send for a future time with scheduled_at.

NameTypeReqDescription
Idempotency-KeystringClient-supplied idempotency key. Retrying with the same key returns the original result without re-sending.
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

sendEmailDemo ~136

Send a SIMULATED email with no account required. Validates the body against the exact same schema as sendEmail (including cc/bcc, reply_to, tags, attachments, and scheduled_at), then returns a realistic synthetic success envelope (demo: true); it never actually sends, queues, or stores anything. Demo requests are capped at 16KB total body, so large attachments are rejected even though the schema allows them. Use this to let someone try Primitive and see the response shape before they sign up. To send for real, sign up for an API key and use sendEmail.

NameTypeReqDescription
requestBodyobjectyes
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

testEndpoint ~60

Send a sample email.received event to a webhook endpoint to verify your signature verifier. Rate limited to 4/min and 30/hr. Successful deliveries and verified-domain endpoints are exempt.

NameTypeReqDescription
idstringyesEndpoint ID from listEndpoints or createEndpoint.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.

verifyDomain ~81

Check DNS records for a domain claim (MX, TXT, SPF, DKIM, DMARC). On success the domain becomes verified and starts receiving mail. On failure, returns which checks passed and which still need attention. If DNS propagation is incomplete, wait a few minutes and retry.

NameTypeReqDescription
idstringyesDomain ID returned by addDomain or listDomains.
NameTypeReqDescription
datayes
statusnumberyes
statusTextstring
toolstringyes

No examples provided.