Back to Browse

Radmail MCP Server

Developer ToolsUse Caution4.8MCP RegistryLocalRemote
Free

Server data from the Official MCP Registry

Email OS for agents - real-inbox search, triage, commitments, and a verifiable BEC hard-stop.

About

Email OS for agents - real-inbox search, triage, commitments, and a verifiable BEC hard-stop.

Remote endpoints: streamable-http: https://radmail.ai/api/mcp/sandbox

Security Report

4.8
Use Caution4.8High Risk

RadMail MCP is a well-designed email triage server with strong security-by-construction principles, particularly the hardcoded refusal of sensitive operations (money, banking changes, first-contact messages). Authentication is properly scoped to read-only connected mode, and credentials are handled via environment variables. Minor code quality concerns around error handling and input validation exist, but permissions align well with the stated purpose of email triage and inbox management. Supply chain analysis found 3 known vulnerabilities in dependencies (0 critical, 3 high severity). Package verification found 1 issue.

3 files analyzed · 9 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

env_vars

Check that this permission is expected for this type of plugin.

HTTP Network Access

Connects to external APIs or services over the internet.

process_spawn

Check that this permission is expected for this type of plugin.

How to Install & Connect

Available as Local & Remote

This plugin can run on your machine or connect to a hosted endpoint. during install.

Documentation

View on GitHub

From the project's GitHub README.

RadMail MCP

An email operating system for agents — with a refusal you can trust.

Every inbox got an AI in 2026. None can be trusted to hit send. RadMail is the one that can — because the consequential actions are refused in code, model-independent: money, changed-banking details, first-contact senders, decisions, and prompt-injection are human-only, forever. No prompt can talk RadMail into auto-sending them.

This is the Model Context Protocol (MCP) server, so any AI agent can use the inbox.

If a fleet of MCP agents runs your execution layer while you sit in the decision seat, the inbox is the seat that needs a hard-stop first. It's where a socially-engineered wire or banking change is irreversible — and where an autonomous process that can hit send can be talked into the loss. RadMail lets agents do the inbox's work (triage, the Right Now lane, commitment tracking, drafting) while money, changed banking, first contact, decisions, and prompt-injection stay human-only by construction, not by a policy an agent could be argued out of. That's what makes the company inbox delegable at all.

Why it withholds the draft, not just the send

Ask this category how it keeps a person in the loop and the published answer is a draft: the agent composes, a human approves, nothing auto-sends. For ordinary mail that is the right design, and it is exactly what RadMail does — draft_reply returns text a person reviews and sends, and the hosted tier lists no send tool at all.

For five classes RadMail does something stricter, and the reason is the whole product: money, changed banking, first contact, a decision, and prompt-injection get no draft at all. On a wire-change thread a draft is not a safeguard — it is the last mile of the attack. Business email compromise does not fail at the send button; it succeeds at the approval button, by putting a plausible, well-written reply in front of a busy person who only has to say yes. Handing that person a pre-written answer makes approving easier than reading. So RadMail withholds the draft and hands over the message and the signals instead, and the person writes the reply.

Both halves are verifiable by execution, with no account — run these two commands and compare:

# Ordinary mail: a draft comes back.
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"draft_reply","arguments":{"from":"sam@client.example","subject":"Re: the deck","body":"Can you send me the updated deck by Thursday?","knownSender":true}}}' | npx -y radmail-mcp

# A banking change: no draft comes back.
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"draft_reply","arguments":{"from":"cfo@vendor.example","subject":"Updated wire instructions","body":"Our bank details changed. Remit the $48,200 to the new account by Friday.","knownSender":true}}}' | npx -y radmail-mcp

Both commands were run verbatim against the published package on 2026-10-14. The first returns a draft plus "mcpEnforcement": "No hard-stop. Still a DRAFT — the MCP surface never sends mail." The second returns "draft": null, "hardStop": "changed-banking", and "mcpEnforcement": "HARD-STOP (changed-banking). No draft offered — human-only forever (BEC defense)." Note what the second one still gives you: the extracted commitment and the reason, taint-tagged — the withheld thing is the proposed reply, not the information.

The five classes are published as draftRefusalClasses in the contract, and the refusal is a one-way ratchet: it may be tightened, never loosened.

The cost, stated plainly. This is a worse experience on precisely the mail you most want handled for you. If a wire-change notice lands at 2am and you wanted a reply waiting, RadMail will have nothing for you to approve — by design. That trade is the product. If what you need is a reply ready to approve on every thread including the ones that move money, a draft-and-approve server is the right tool and this is the wrong one.

Start in one call

Call triage_inbox and omit the token — RadMail auto-provisions a free sandbox tenant and returns a working triage in one round-trip. Reuse the returned token. (On the zero-auth hosted sandbox, triage_inbox takes no args — it triages a built-in demo inbox so your very first call returns the full wedge.)

This server runs the sandbox engine (heuristic, in-memory, free, no credentials). It is real and runnable — not the production "99%" engine.

Tools

ToolWhat it does
triage_inboxOne round-trip over a batch: the Right Now lane + every open commitment + every hard-stop. The whole wedge in one call.
list_right_nowThe can't-miss lane only — most-recent × most-important, each with why-surfaced. Pass messages for the sandbox (with hard-stop flags), or omit them with RADMAIL_API_KEY set for your real Right Now lane (read-only).
why_surfacedExplain in plain English why a message surfaced — the signals behind its importance × urgency. Transparency, not a black box.
draft_replyDraft the reply that discharges a commitment — never for a hard-stopped one (money / banking / first-contact stay human-only).
list_commitmentsOpen promises with their due window. Pass messages for sandbox extraction, or omit them with RADMAIL_API_KEY set for your real tracked commitments (read-only).
searchFind the one message you mean by sender / subject / content — most-relevant + newest first (no filesystem grep). Pass messages for the sandbox, or omit them with RADMAIL_API_KEY set to search your real inbox (read-only).
read_emailConnected mode only: fetch one full email (headers + textBody + attachment names) from your real inbox by RadMail's id; returns rfcMessageId, the RFC 5322 Message-ID a reply threads on. Read-only; body content arrives taint-tagged.
read_threadConnected mode only: one conversation by threadId — the thread and its received emails oldest first, each with id, rfcMessageId and inReplyTo. Metadata only; coverage says what is left out. Read-only.
list_emailsConnected mode only: your real inbox newest first, metadata only, with since and a nextCursor for polling. Fails closed on a RadMail deployment too old to honour since / cursor. Read-only.
list_prepared_draftsConnected mode only: RadMail's own AI-prepared reply drafts (optionally for one emailId). Read-only — RadMail never sends a prepared draft on its own.
list_watched_threadsConnected mode only: the threads you watch, with who spoke last (me_last / them_last / unknown) and a stalled flag. Read-only.
get_attachmentConnected mode only: save one file attached to a real email to RADMAIL_ATTACHMENT_DIR and return its path. Read-only; the server decides whether the file may be served (key scope, mailbox, sender allowlist, size cap).
check_send_domainZero-auth, works on any domain: read-only SPF / DKIM / DMARC health read (verdicts + raw records + plain-language advice). Probes the common DKIM selectors (default, google, resend, sendgrid, mail, k1, s1, s2). Read-only DNS — no key, no send capability.
check_before_sendConnected mode only: ask RadMail whether an email your agent will send through its own provider should go — pass / review / human_only, with reasons — without sending it. Nothing is sent or stored. human_only means a person sends it from their own mail, or discards it; review means show the owner first; pass means no known risk pattern matched, not a clearance. Any answer without a verdict (the check switched off, a refused key, a timeout) comes back checked: false, verdict: null — unchecked, never pass. Needs a key that is not limited to one mailbox. See Checking a message your agent sends itself.
triageScore a single message (the per-message form of triage_inbox).
provision_sandboxExplicitly mint a free sandbox tenant.
report_need / request_capabilityTell RadMail what was awkward / what you wish existed — the surface adapts.
radmail_learning_insightsWhat RadMail has learned about how you work.

Two opt-in surfaces add tools on a local server only, never on a hosted one: send_email (see Opt-in: sending) and five inbox actions — archive_email, snooze_email, mark_read, label_email, act_on_emails (see Opt-in: inbox actions). Every connected read tool is annotated readOnlyHint: true — except get_attachment, which writes a file on the local machine and so carries no read-only claim; the annotations are inside the frozen manifest, so flipping one fails the startup check like a description edit would.

"How many tools?" — and the second number that matters more

Public round-ups of email MCP servers commonly quote a tool count as a measure of depth. Tool count measures surface area, not judgment — and for a server trusted with an inbox, the useful number is the second one: of those tools, how many can send?

RadMail publishes both, as dated observations you can reproduce against any MCP server — this one included:

TierToolsSend-capable
Hosted zero-auth sandbox (https://radmail.ai/api/mcp/sandbox)60
This package at 0.6.0, default (also this package's hosted /api/mcp, with or without a bearer)190
… with RADMAIL_SEND_TOOL=1 (local stdio only)201 — send_email, which hands mail to RadMail's outbound gate and cannot release a hold
… with the opt-in inbox actions (local stdio only)240 — the five added tools change inbox state (archive, snooze, read state, labels); none sends, trashes or deletes

Row 1 observed 2026-10-09; rows 2-4 read from this repository's frozen manifests at 0.6.0 (2026-10-26), which is not yet on npm — the published 0.5.0 predates send_email, the inbox actions, check_before_send and the 0.6.0 read tools. Reproduce row 1 with the tools/list command under Verify before you connect. Reproduce row 2 from the frozen manifest — the surface the server refuses to deviate from (src/send-tool-manifest.ts and src/triage-tool-manifest.ts hold the opt-in rows):

node -e 'const s=require("fs").readFileSync("src/tool-manifest.ts","utf8");
const n=[...s.matchAll(/"name": "([a-z_]+)"/g)].map(m=>m[1]);
console.log(n.length, n.join(" "))'

⚠️ One honest caveat, because the naive version of this check gets it wrong: grepping that list for send matches check_send_domain, which is a read-only SPF/DKIM/DMARC lookup over DNS — it reads a domain's published records and sends nothing — and check_before_send, which asks RadMail whether a message should be sent and sends nothing either. Read each tool's description, not just its name. That caveat applies to whatever server you are evaluating, not only to this one.

The ratio is the point, and it is not a verdict on anyone else. A wide, send-capable tool surface is a legitimate design for an agent that is supposed to send, and most of this category is built for exactly that job. It is the wrong design for the one class of email where being argued into sending is the whole attack. RadMail reports 0 send-capable tools on every hosted endpoint — see The safety contract for why that is capability-absent rather than a setting someone could switch.

Which of the three shapes is this? (a fourth one — and the difference is the product)

Published round-ups of this category sort email MCP servers into roughly three shapes:

  1. Transactional / lifecycle sending for an application — deliverability, templates, logs, domain management.
  2. An inbox the agent owns — the agent has its own address and receives, threads and answers mail end to end.
  3. OAuth access to a mailbox a person already owns — read and write that person's real Gmail or Outlook.

RadMail is none of those three cleanly, which is why a round-up built on them has nowhere to put it. The shape is a fourth one: a triage-and-follow-through layer over a mailbox that stays a person's mailbox. The agent gets rank, explanation, commitment tracking and a draft; the person keeps the send.

That is a boundary rather than a feature list, so it is checkable — in about a minute, without an account:

  • The agent does not own the mailbox. The hosted endpoint takes no credential and serves a fixed demo inbox. Shape 2 needs an address of its own; shape 3 needs your OAuth grant. RadMail asks for neither to be evaluated.
  • Connected mode is read-only by default. With RADMAIL_API_KEY set, the connected tools (search, read_email, read_thread, list_emails, list_right_now, list_commitments, list_prepared_drafts, list_watched_threads) read your real mail; none of them writes or sends. check_before_send asks RadMail's send gate about a message your agent will send through its own provider, and sends nothing. An operator can additionally turn on five local-only inbox actions (archive, snooze, read state, labels) — reversible, and none of them deletes or sends.
  • The send verb is absent from every hosted endpoint — 0 send-capable tools, reproducible with the tools/list command under Verify before you connect. Sending exists only as an opt-in local tool, and even then it cannot release a held message.

And the honest cost of being a fourth shape: if what you need is an agent that owns an address and answers mail with no person in the loop, shape 2 is the right choice and RadMail is the wrong tool — it will refuse precisely the things you would be hiring it to do. RadMail is built for the mailbox a business actually runs on, where being argued into sending is the attack.

The safety contract (un-bypassable by design)

These are decided by deterministic code, not model judgment — see the published contract at https://radmail.ai/.well-known/agent-safety.json (there is a second, code-pinned copy in this repo — see Counting the contract below, so a disagreement between them does not read as a lie):

  • money, changed-banking, first-contact, decision/sign-off, prompt-injection → hardStop, human-only forever. RadMail will never hand an agent an auto-sendable reply for these.

  • Enforcement model: capability-absent. "The agent can't do that" is three different claims, and they are not equally strong — so the contract publishes which one this is, as enforcementModel, with all three values defined so the label is interpretable rather than a slogan:

    ValueWhat it means
    capability-absent — RadMailThe tool that would perform the forbidden action does not exist on the server, so it cannot be called. There is nothing to configure and nothing to bypass.
    config-restrictedThe capability exists and is narrowed by configuration — an allowlist, a scope, a policy file. Whoever holds the configuration can widen it again.
    policy-gatedThe capability exists and is restrained by instructions, prompts, or documented policy that a model is asked to follow.

    The three definitions are generic and name no product — this is the axis, not a comparison. Don't take the label's word for it: read the tool list back (see Verify before you connect) and look for a send-capable tool. There isn't one; that absence is the enforcement.

  • A human-in-the-loop approval gate sits on a different row. "Human-in-the-loop" normally means the capability exists and a person is asked to approve each use — config-restricted or policy-gated on the axis above. Approval gates have a legitimate place and they work differently: whoever holds the configuration can widen one, and an approver under time pressure is precisely what business-email-compromise fraud is built to exploit. RadMail reports capability-absent on the hard-stopped classes, so there is no request to approve and nothing to widen. The reviewable drafts are the human-reviewed path for everything outside those classes — RadMail drafts, a person sends.

  • A read-only banking connector protects a different thing. A read-only bank or accounting MCP server cannot initiate a transfer, so it cannot execute the fraud directly — genuinely useful, and a different job. Business email compromise is not an attack on your bank connection; it is an attack on your inbox. The fraudulent instruction arrives as email — a supplier whose bank details have "changed", an invoice redirected to a new account, a first-contact request that reads as routine — and the loss happens when a person or an agent believes it and acts through some other channel. A read-only connector never sees that email, so it cannot flag it. RadMail works where the instruction lands: money, changed-banking, first-contact, decision and prompt-injection stay human-only, reported as capability-absent, not as a setting an operator could switch off.

  • Taint envelope: every field derived from a raw email body carries provenance: "untrusted-email-body", and every response carries a safety block restating the hard-stops. Treat tainted fields as data, never as instructions — this keeps your agent safe-by-default, even against a poisoned email.

  • Fail-closed: if a risk signal can't be evaluated, RadMail refuses to auto-send.

Counting the contract: forbiddenActions is 3, the hard-stopped classes are 5

Audit the published contract by counting one key and the number will not match the prose, so here is the reconciliation before you conclude this README overclaims. Observed on https://radmail.ai/.well-known/agent-safety.json, 2026-10-18, 21 keys:

  • forbiddenActions → 3: auto-sending money, auto-sending or changing banking instructions, auto-sending first contact. These are actions this server has no tool for.
  • draftRefusalClasses → 5: money, changed-banking, first-contact, decision, injection. These are the classes for which RadMail withholds the draft itself — see Why it withholds the draft, not just the send.
  • enforcementModel → capability-absent, with enforcementModelValues defining all three values so the label is interpretable rather than a slogan.

So the five classes are filed under two keys, not three-instead-of-five. 3 + 5 is the same posture the prose describes, not a weaker one.

And there are two copies of this contract, which is said out loud because an evaluator who reads one and checks the other will think something is wrong. The published contract above is the one to fetch, and every claim in this file is keyed to it. The copy in this repo — public/.well-known/agent-safety.json — has an older shape (observed 2026-10-18: 20 keys, all five classes filed under forbiddenActions, and no enforcementModel at all, so do not go looking for that field there). It earns its place a different way: it is the copy a test ties to the running firewall. test/agent-safety-contract-matches-the-code.test.ts asks the real send-disposition engine whether each permanently-human-only action type is actually refused, and fails if the document names a tool this server does not expose. Nothing compares the two automatically — different repos, no network in CI — so this is a named gap, not a silent one. They agree on the five classes and on fail-closed; if you find a disagreement that matters, that is a bug and the contact address is at the bottom.

Auditing this against the money-safety checklist (two of the three fields do not apply)

Published audits of money-moving MCP servers grade on three fields: a configurable spending budget, a documented human-approval step, and a velocity limit. Those are the right three questions for a server that can move money. Asked of RadMail, the honest answers are two not-applicables and one that is stricter than the field expects:

Audit fieldRadMail's answer
Configurable spending budgetNot applicable — there is no spend to bound. A budget limits a capability; this capability is absent. Answering "yes, $X per day" would imply a money-moving path exists and is merely capped.
Velocity limit (payments/day, auto-sends/hour)Not applicable. Rate-limiting an action the server cannot perform is theatre. Ordinary mail has no auto-send to rate-limit either — draft_reply returns text a person sends.
Documented human-approval stepApplies — and the answer is stricter than the field expects. On the five classes there is nothing to approve: no draft is offered and no send verb exists. Approval gates are a legitimate design and they fail in a known way: an approver under time pressure is precisely what business-email-compromise fraud is built to exploit.

Reproduce the two not-applicables rather than believing them. On the frozen manifest — the surface this server refuses to deviate from — grep -ic budget src/tool-manifest.ts, and the same for velocity and spend, each return 0 (observed 2026-10-18). The hosted tools/list returns 6 tools, 0 send-capable (observed 2026-10-18: triage_inbox, list_right_now, why_surfaced, list_commitments, draft_reply, search). An absent field is weak evidence on its own; an absent verb, readable with no account, is the part that matters.

The cost, stated plainly: RadMail cannot pay an invoice and will not acquire the ability to. If your agent's job is to move money, you need a payments server — and that is exactly where a spending budget, a velocity limit and an approval step are the questions to ask, so ask them there. RadMail's job is the inbox the fraudulent instruction arrives in.

Auditing this against the BEC control checklist the security category publishes (three of the five are someone else's job)

Ask the email-security category how to stop business email compromise and the published guidance converges on five controls. Asked of RadMail the honest answers are one stricter than the field expects, one partial, and three flat nos — because RadMail and an email-security gateway solve different halves of the same problem, and conflating them is how a buyer ends up unprotected.

Published BEC controlRadMail's answer
A second authorized reviewer on wires, payroll changes and vendor-bank changes — an approval that urgency or seniority cannot waiveApplies, and is stricter than the field expects. For an agent there is no approval request to waive, because there is no tool: money and changed-banking are capability-absent, and RadMail withholds the draft too, so there is nothing pre-written to say yes to. The reviewer is the only author.
Out-of-band callback verification to a previously known-good numberNot implemented, and RadMail will not acquire it. RadMail places no calls and holds no vendor contact-of-record, so it cannot confirm a changed account through a second channel. What the hard-stop buys is the pause in which a person makes that call — it does not make the call, and reading it as if it did would be the dangerous misreading.
Authentication of the sending infrastructure (SPF / DKIM / DMARC)Partially — and narrower than the name suggests. check_send_domain is a zero-auth, read-only DNS read of SPF / DKIM / DMARC for a domain you name, probing the common selectors. It is not per-message header authentication of received mail, it does not evaluate alignment on a specific message, and it cannot act on the answer.
Impersonation / behavioural-anomaly detection on inbound mailNo. This is not an email-security product. RadMail scores importance × urgency and flags the five hard-stop classes on messages that have already reached the inbox. It does not model sender relationships to decide whether a message is forged, and it should not be bought instead of something that does.
Automated remediation — quarantine, clawback, incident clusteringNo, by the same construction as everything else. The hosted surface is 6 tools, read/triage/draft only; nothing moves, deletes or quarantines mail.

Reproduce the three nos rather than believing them. On the frozen manifest — the surface this server refuses to deviate from — grep -ic quarantine src/tool-manifest.ts and the same for delete and archive each return 0, and grep -ic send returns 2 (re-measured 2026-10-26, when check_before_send was added; it was 1 before): the nouns inside check_send_domain, a read-only DNS lookup, and check_before_send, which asks RadMail's gate about a message and sends nothing. The hosted tools/list returns 6 tools, 0 send-capable (observed 2026-10-23: triage_inbox, list_right_now, why_surfaced, list_commitments, draft_reply, search).

The two halves, stated so nobody buys the wrong one. A BEC gateway defends the mailbox against the attacker's message — filtering, authentication, impersonation modelling, quarantine. RadMail constrains what an agent may do with the mailbox once a message is in it. Those are not competing claims: a gateway that stops almost everything still passes the message it has not seen before, and in 2026 what increasingly stands at the other end of that message is an autonomous process with send rights and no instinct for a changed bank account. If you have no inbound email security, RadMail is not a substitute and you should buy one. If you have one and you are also handing an agent the inbox, the gateway has nothing to say about what the agent does next — that is the row RadMail is on.

Verify before you connect

The safety contract is machine-verifiable — fetch it and check it in one command, no account, no key:

curl -s https://radmail.ai/.well-known/agent-safety.json

Then don't take its word for it — read the tool list back and look for a send-capable tool. This is the check the capability-absent row above points at, and it needs no key either:

curl -s -X POST https://radmail.ai/api/mcp/sandbox \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Read the names back. There is no send, no send_email, no pay, no update_banking — and that absence is the enforcement. (One exception, and only where an operator chose it: a local stdio server started with RADMAIL_SEND_TOOL=1 also lists send_email — see Opt-in: sending below. Likewise a local server with RADMAIL_TRIAGE_TOOLS=1 and a triage key lists the five inbox actions, none of which sends or deletes. The hosted endpoints never list either.) Observed on the hosted sandbox 2026-10-09: 6 tools — triage_inbox, list_right_now, why_surfaced, list_commitments, draft_reply, search. That is a dated observation of the hosted sandbox tier, not a ceiling: the local stdio package exposes the fuller set in the table above. Re-run the command rather than trusting this line.

And the one claim you cannot check from the outside — check it in the source. The strongest sentence in this README is "no tool can release a held send" (below, under Opt-in: sending). A paragraph is not evidence, and that claim is the one a hosted tools/list cannot reach, because the send tool is not on the hosted tier at all. It is asserted by a test in this repo — so run the test instead of believing the paragraph:

git clone https://github.com/radmail-ai/radmail-mcp && cd radmail-mcp && npm install
RADMAIL_TELEMETRY=off node --test --import tsx \
  --test-name-pattern="release a held send" test/send-email.test.ts

Three things are asserted: that every URL the tool fetches, across every outcome, is the send path and never a /confirm route; that neither the client nor the tool names a confirm/release route anywhere in its source; and that the input schema has no field that could name an earlier request to act on. Observed 2026-10-05: 3 pass, 0 fail — a dated observation, like every other count in this file. Re-run it.

🔑 Now make it fail, because a guard you have not seen bite is not a guard. Add one line to src/lib/send.ts —

echo 'export const RELEASE_PATH = "/api/v1/sends/confirm";' >> src/lib/send.ts

— and re-run the command above: the second assertion fails and the suite exits non-zero. Then git checkout src/lib/send.ts to put it back. RadMail publishes the falsification step rather than asking you to assume the check is real.

Reproducing the explanation itself — and the argument name this README never published

why_surfaced is the claim that the ranking is explainable rather than a score with a story attached. It is named three times above and its one argument was never written down, so until now the fastest way to check the claim had to be guessed at. Two commands, no account, no key:

# 1. get an id out of the demo inbox
curl -s -X POST https://radmail.ai/api/mcp/sandbox \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_right_now","arguments":{}}}'

# 2. ask why that one surfaced — the argument is message_id (snake_case)
curl -s -X POST https://radmail.ai/api/mcp/sandbox \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"why_surfaced","arguments":{"message_id":"m_001"}}}'

Observed 2026-10-19 — six named signals and the base number they move, not a sentence:

Why "Re: PO-4471 — confirm revised delivery window" [m_001] scored importance 94 x urgency 94:

  • sender is a known counterparty (base importance 78)
  • you owe an open commitment on this thread
  • arrived in the last few hours
  • explicit same-day deadline language
  • an explicit confirmation is requested
  • a commitment on this thread is due soon

And the part worth measuring instead of asserting: the same input returned the same bytes. Three consecutive calls on 2026-10-19 returned byte-identical 433-byte payloads — sha256 e0eebdcf46ae7aada7abc0ac41e5a48608773026252fd49a511f07f5d8cb549c. That is what "not a black box" is being used to mean here: the signals are the scoring inputs read back, so an explanation can be diffed, pinned in a test, and shown to a person who disagrees with the rank. An explanation written by a model narrating its own guess is a legitimate design and often reads better — but two identical calls to it need not agree, and what does not repeat cannot be diffed. Re-run the commands rather than trusting this paragraph, and scope the claim the way it is scoped here: this is the heuristic sandbox tier, which is the part you can check with no account.

The two tiers take the argument differently, and that is by design, not drift. The hosted sandbox serves a fixed demo inbox, so why_surfaced there takes message_id — ids m_001–m_006, and list_right_now prints them in brackets. The local stdio package has no inbox of its own (you pass it your own messages), so there why_surfaced takes the message object — from and body, optionally knownSender / hasReply / receivedAt / subject — the same shape as triage. Measured on the hosted tier 2026-10-19: the camelCase guess {"messageId":"m_001"} does not fail silently, it answers No demo message with id "". Pass a message_id from triage_inbox (available ids: m_001, m_002, m_003, m_004, m_005, m_006). — which is the list you needed. Published here so the convention is read rather than discovered.

An independent grade of this server — one we did not ask for and do not control

Everything above this line is RadMail checking RadMail. A reader is right to discount it. So here is the same claim measured by someone else, on a page RadMail does not own, cannot edit, and never submitted to:

AxioRank MCP Security Index grade for radmail-mcp

⚠️ Re-read 2026-10-31, and the news is against us: AxioRank is publishing no grade for this server right now, and the live badge above says so. It renders "AxioRank: unrated". The scorecard page returns "grade":null in its own payload, and the four panels that held the numbers below — Grade, Blast radius, Tools, Capabilities — now read unrated, –, –, –. The page also no longer shows the high advisory discussed further down (Credential / secret access → 0 occurrences, where it was present on 2026-10-22), and it shrank from 148,905 B to 123,139 B. Re-verified 2026-11-01 and unchanged: badge still AxioRank: unrated, page 200 / 123,077 B, unrated present, "grade":null.

The table below is therefore the 2026-10-22 reading, kept and dated, not a current one. Two things are worth saying plainly about it. First, this does not look like a downgrade of RadMail: two unrelated slugs on the same badge endpoint — io-github-modelcontextprotocol-servers and ai-mails-agent-email — also return unrated today, so the grades appear withdrawn across the index rather than for this server. We do not know why, we did not ask, and we are not going to guess in public. Second, a withdrawn grade is not a grade of zero and is not evidence in RadMail's favour either — the correct reading of this paragraph today is there is currently no independent grade here, and the only thing you should rely on is the tools/list call above, which you can run yourself with no account.

This section said, before any of this happened, that the badge is served live by them and "moves if their grade moves — including downward. That is the point of citing it." This is what that looks like when it is honoured rather than quietly edited out. Re-derive both states yourself:

curl -s https://axiorank.com/api/badge/mcp/ai-radmail-radmail-mcp.svg | grep -o 'AxioRank: [a-z]*'
curl -s https://axiorank.com/mcp-index/ai-radmail-radmail-mcp | grep -o '\\"grade\\":[a-z]*'

AxioRank's MCP Security Index crawls a server's declared tool surface and grades its blast radius — "the most powerful thing each of its tools can do." Its scorecard for this server, as read on 2026-10-22 (superseded — see the note above):

what AxioRank measuredits value
GradeA — "a minimal exposure"
Blast radius0 / 100
Tools found6
Capabilities flagged0
Execute · Delete · Write · Read0 · 0 · 0 · 6

In its own words: "radmail-mcp declares no high-impact capabilities that AxioRank flags."

And the caveat matters more than the grade, so here it is verbatim rather than paraphrased: "The grade reflects the blast radius of what radmail-mcp declares it can do, read-only, not whether it is secure or trustworthy, and not a judgment of the vendor." And: "A minimal grade means a small blast radius, not an endorsement." That is the correct reading. A zero blast radius says the dangerous verbs are absent from the declared surface — which is exactly the claim the capability-absent row makes and exactly what the tools/list command above lets you re-derive yourself in one call. It does not say the code is well written, and it is not a security audit.

RadMail has no relationship with AxioRank, did not request the listing, and cannot change what it says. The badge above is served live by them, so it moves if their grade moves — including downward. That is the point of citing it.

The high advisory on that page, and the one keyword that causes it

On 2026-10-22 that same scorecard showed an Advisory: high — "Credential / secret access capability." It would have been dishonest to link the grade and skip the red word next to it, so it was named here — and it is kept here now that the advisory has gone along with the grade, because a record that only keeps the flattering half is not a record: AxioRank labels that block "Keyword matches in tool descriptions and schemas… shown for transparency and are not part of the grade" — and the keyword it matched is one this README can name, because it was measured rather than guessed.

curl -s -X POST https://radmail.ai/api/mcp/sandbox \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | grep -o RADMAIL_API_KEY

Counted over that whole payload on 2026-10-22: api_key 1, and token · credential · secret · password 0 each. The single hit is inside the description of search, where it explains the connected-mode upgrade: run the local package with RADMAIL_API_KEY set and the same tool reads your real inbox instead of the demo one. A keyword scanner reading tool prose cannot tell a sentence about a key from a tool that handles one — and this is the former. There is no tool here that reads, writes, stores, or forwards a credential; the same scorecard's own capability count says so on the line above (Read 6, everything else 0).

The honest shape of it: the advisory is a true statement about our text and a false impression about our surface. We are not going to delete the sentence that tells an operator how to connect their real inbox in order to make a keyword scanner happier — we would rather publish the arithmetic and let you run the grep.

Connect

Fastest — zero-auth hosted sandbox (no install, no key, no signup). Point any MCP client at the streamable-HTTP endpoint:

{
  "mcpServers": {
    "radmail": {
      "url": "https://radmail.ai/api/mcp/sandbox",
      "transport": "streamable-http"
    }
  }
}

Local stdio (this package — the fuller surface that triages the messages you pass it):

{
  "mcpServers": {
    "radmail": {
      "command": "npx",
      "args": ["-y", "radmail-mcp"]
    }
  }
}

radmail-mcp is live on npm — the npx line above works as-is. Prefer no install at all? Use the zero-auth hosted sandbox above.

⚠️ Honest note on the published version (true as of 2026-09-30). npm view radmail-mcp dist-tags reports latest: 0.5.0, but the build inside that tarball announces itself as 0.4.0 over MCP — dist/ was packed before a version bump. This repository's main is at 0.5.1 with the root cause fixed (prepublishOnly now rebuilds dist/ before packing); the corrected package is not yet published, because publishing needs an interactive npm login only the maintainer can run. Reproduce it yourself: npm pack radmail-mcp && tar -xzOf radmail-mcp-*.tgz package/dist/src/server-info.js | grep version. No part of the safety contract depends on the version string — but RadMail publishes this check rather than asking you to assume.

Or from source: git clone https://github.com/radmail-ai/radmail-mcp && npm i && npm run build && npm start (stdio). Hosted deploy: Vercel Node serverless function (api/mcp.ts; / rewrites to the MCP handler).

Documentation truncated — see the full README on GitHub.

Reviews

No reviews yet

Be the first to review this server!