mcp server
send-guard
Check an email list before your agent sends to it. Free local checks, mailbox verification via Analyzemail. CLI, MCP server, library. Zero dependencies.
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- Node.js 20 or newer
{
"mcpServers": {
"askeleven-send-guard": {
"command": "npx",
"args": [
"-y",
"@askeleven/send-guard"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 14, 2026send-guard

Check an email list before your agent sends to it, and find out whether it is safe to.
npx @askeleven/send-guard leads.csv
An agent that sends to a bad list does not notice. It gets bounces nobody reads, lands on a spam trap, and the domain's reputation is gone before a person looks at a dashboard. send-guard is the check that runs first: a CLI for pipelines, an MCP server for agents, and a library for everything else. It returns a pass or a fail, the addresses to keep, and the reason for every one it removes.
Zero dependencies. The local checks need no signup and no account, and nothing leaves your machine except DNS lookups for the domains in the list.
What it checks
| Check | Where it runs | Verdict |
|---|---|---|
| Syntax | Local, free | Remove |
| Duplicates, case-insensitive | Local, free | Remove |
| Domain cannot receive mail: no MX, no A record, or a null MX | Local, free | Remove |
| Parked domains, on known parking nameservers | Local, free | Remove |
| Disposable inboxes | Local, free | Remove |
Typos of major providers, with a suggestion (gmial.com, hotmial.com) | Local, free | Remove |
Role accounts (info@, sales@, support@) | Local, free | Review |
| Free providers | Local, free | Informational |
| Mailbox exists, over SMTP | Analyzemail API key | Remove if not |
| Catch-all domains | Analyzemail API key | Review |
| Spam traps | Analyzemail API key | Remove |
| Known litigators | Analyzemail API key | Remove |
| Security gateways hiding mailbox status | Analyzemail API key | Review |
Keep means nothing was found. Review means a person should decide. Remove means sending will bounce, or will arrive somewhere that hurts you.
The list fails when more than 2% of its distinct addresses should be removed
(--max-remove to change it). Duplicates are left out of that share: sending twice is
wasteful, not dangerous.
Why the mailbox check needs a key
Most cloud hosts block outbound port 25 by default, so an agent running on one cannot ask a mail server whether a mailbox exists. Even where it can, probing from an IP with no reputation gets refused or blocklisted. That check needs infrastructure, so it runs on Analyzemail, which we also make.
Set ANALYZEMAIL_API_KEY (get one here)
and send-guard checks every address that passed the local checks. It never spends a
credit on an address it has already ruled out, or on a duplicate. One credit per address,
and a check the mail server does not answer is refunded.
250 mailbox checks a month are free on any Analyzemail account with a confirmed email address. They reset at 00:00 UTC on the 1st, do not roll over, and are spent before any credits you buy. Until an account has bought credits, it is limited to 2 checks a second and 500 a day; send-guard waits out the per-second limit on its own. AskEleven customers get 25,000 a month.
Before spending anything it checks your balance and refuses to start if the list would
cost more than --max-credits (default 1,000), so an agent cannot spend more than you
expect.
What it does not do
Without a key, it cannot tell you a mailbox exists. A list can pass every local check and still bounce 20% when the people on it left their jobs. The report says so when mailboxes were not checked, rather than letting a pass imply more than it means.
It does not send anything, or fix anything. A probable typo comes with a suggestion,
not a correction. Whether bob@gmial.com meant bob@gmail.com is for a person to
confirm.
It does not treat a DNS failure as a dead domain. If the resolver does not answer, those addresses are marked review, not remove.
Example
$ npx @askeleven/send-guard leads.csv --out clean.csv
FAIL 50% of the list should be removed (limit 2%)
4 checked
1 keep
1 review
2 remove
REMOVE
Disposable inbox (1)
al@sharklasers.com
Probable typo (1)
bob@hotmial.com did you mean bob@hotmail.com?
REVIEW
Shared inbox (role account) (1)
sales@acme.com
Mailboxes were not checked. 2 addresses passed the local checks, which
catch addresses that can never work but cannot tell whether a mailbox
exists. Set ANALYZEMAIL_API_KEY to check them (one credit each; key at
https://analyzemail.com/account/settings/api).
Wrote the addresses to keep to clean.csv
clean.csv keeps the header and every other column, so it drops straight back into
whatever the list came from.
Options
--column <name|n> Email column in a CSV. Found automatically otherwise.
--max-remove <pct> Fail when more than this share should be removed. Default 2.
--max-credits <n> Refuse to spend more than this on mailbox checks. Default 1000.
--out <file> Write the addresses to keep, in the input's format.
--include-review Also write addresses marked review to --out.
--no-mailbox Local checks only, even with an API key set.
--no-dns Skip DNS lookups. Syntax and list checks only.
--dns <ip> Resolver to query. Repeatable.
--json Machine-readable output.
--all List every flagged address, not the first ten per reason.
--no-colour Plain text.
Input is a CSV (comma, semicolon or tab), a plain list with one address per line, addresses on the command line, or standard input.
Exit code 0 means safe to send, 1 means not safe as it stands, 2 means it could not
run. So it gates a pipeline:
npx @askeleven/send-guard list.csv --out clean.csv && ./send-campaign clean.csv
For agents: MCP server
npx @askeleven/send-guard mcp
It serves two tools over stdio: check_emails (up to 5,000 addresses inline) and
check_file (a CSV or text file on disk, optionally writing the clean list to
out_path). Both return passed, the addresses to keep, and the remove and review
lists, each with a reason code and a plain-English explanation.
Claude Code
claude mcp add send-guard -e ANALYZEMAIL_API_KEY=am_live_... -- npx -y @askeleven/send-guard mcp
Claude Desktop, Cursor, and other clients that take a JSON config:
{
"mcpServers": {
"send-guard": {
"command": "npx",
"args": ["-y", "@askeleven/send-guard", "mcp"],
"env": { "ANALYZEMAIL_API_KEY": "am_live_..." }
}
}
}
Leave out the env block for local checks only.
The server tells the model how to use the result: do not send to a list that failed,
send to keep, show review to a person rather than deciding, and never substitute a
typo suggestion without asking.
As a library
import { checkList, createClient } from '@askeleven/send-guard'
const report = await checkList(addresses, {
client: createClient({ apiKey: process.env.ANALYZEMAIL_API_KEY }), // optional
})
if (!report.summary.passed) {
const keep = report.addresses.filter((a) => a.verdict === 'keep').map((a) => a.email)
// send to keep, or stop and ask
}
Every reason has a stable code (syntax, disposable, mailbox_undeliverable, and so
on) to match on, and a detail to show a person. createFixtureResolver() is exported
so you can test without touching the network.
Privacy
With no API key, the only thing that leaves your machine is a DNS query for each distinct domain in the list. Addresses are not sent anywhere.
With a key, each address that passed the local checks is sent to Analyzemail to be
verified, under its privacy policy. --no-mailbox (or
check_mailboxes: false over MCP) turns that off for one run.
Requirements
Node 20 or newer. No dependencies.
Why we built it
AskEleven runs AI employees that send email on behalf of small businesses. The first time an agent is handed a spreadsheet and asked to "follow up with everyone", it will, including the 400 addresses that bounced two years ago. Nothing about the agent is broken. Nobody told it to check.
This is that check, made free wherever it can be. The disposable, role and parking lists are the ones Analyzemail uses server-side, so a local verdict and an API verdict agree.
Contributing
Issues and pull requests welcome, especially:
- Disposable domains we are missing, with a link showing the service hands out inboxes.
- Wrong verdicts. If an address is removed that should not be, open an issue with the domain (not the full address) and we will fix it.
- MCP clients where the server does not work as documented.
Run the tests with npm test. They use fixture DNS and a fake API client, so they are
offline and fast.
License
MIT. See LICENSE.
Removing a litigator or a spam trap from a list is risk reduction, not compliance. Consent is still yours to get.