An AI agent that handles signups, outreach, or CRM hygiene keeps hitting the same wall: it has no idea whether an email address is real. It will cheerfully email gmial.com, accept a mailinator.com throwaway as a new user, or import a dead domain into your database. The agent is not wrong to try; it just has no sense for deliverability.
MCP (the Model Context Protocol) is the clean way to close that gap. Instead of hardcoding an HTTP client into every agent, you point the agent at a server and it gets the tools. This post connects Verifly over MCP so any MCP-capable client (Claude Desktop, Cursor, your own agent runtime) can verify and clean email addresses inside its loop.
The use case
You are building an agent that onboards users or works a lead list. You want it to:
- reject fake or disposable signups before they land in your database, and
- clean a list before a campaign so you are not emailing dead addresses.
Both are decisions the agent should make mid-task, which means verification has to be a tool it can call, not a script you run afterward.
Two ways to connect
Verifly runs a hosted MCP server at https://verifly.email/mcp (Streamable HTTP, Bearer auth). There is also an npm package that runs the same server locally over stdio. Use whichever your client supports.
Get a key first
Verifly is built for agents, so onboarding is a single call, no dashboard:
curl -s -X POST https://verifly.email/api/v1/autonomous/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"a-strong-password"}'
You get back an api_key.key starting with vf_ and 100 free credits.
Option A: hosted server (Claude Desktop / Cursor)
Add it to your MCP config. For Claude Desktop, claude_desktop_config.json:
{
"mcpServers": {
"verifly": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://verifly.email/mcp"],
"env": { "VERIFLY_API_KEY": "vf_your_key_here" }
}
}
}
Option B: local stdio server
npx verifly-mcp-server
{
"mcpServers": {
"verifly": {
"command": "npx",
"args": ["-y", "verifly-mcp-server"],
"env": { "VERIFLY_API_KEY": "vf_your_key_here" }
}
}
}
Restart the client and the Verifly tools appear.
What the agent actually gets
After connecting, a tools/list against the server returns a real toolset. These are the verification-focused ones:
-
verify_email— verify one address, returns the verdict, reason, flags, and a send/reject recommendation. -
verify_batch— verify a list synchronously (good up to a few hundred). -
clean_email_list— dedupe, drop invalid syntax, optionally strip disposable and role accounts. -
extract_emails— pull addresses out of free-form text (signatures, pasted notes). -
check_domain_health— MX / SPF / DMARC and an overall health score for a domain. -
submit_bulk/get_job_status/get_job_results— async jobs for large lists. -
get_credits/get_account/get_usage— balance and usage, no credits charged.
The agent picks the right one from the descriptions. "Clean this list" pulls clean_email_list; "is this signup real?" pulls verify_email.
What a verdict looks like
When the agent calls verify_email on a typo, the live server returns this (shown via the underlying REST call the tool wraps):
{
"email": "jane.doe@gmial.com",
"result": "undeliverable",
"reason": "Invalid email: bad_domain",
"confidence": 90,
"recommendation": "do_not_send",
"did_you_mean": "jane.doe@gmail.com",
"details": { "domain_exists": true, "mx_records": true, "smtp_valid": false,
"is_disposable": false, "is_catch_all": false }
}
A disposable address is caught outright:
{
"email": "test@mailinator.com",
"result": "undeliverable",
"reason": "Disposable/temporary email address",
"recommendation": "do_not_send",
"details": { "is_disposable": true }
}
And a real mailbox passes:
{
"email": "james@sibscientific.com",
"result": "deliverable",
"reason": "Email exists and accepts mail",
"confidence": 95,
"recommendation": "safe_to_send"
}
Two fields make this agent-friendly. recommendation is a flat verb (do_not_send / safe_to_send) the model can branch on with no parsing, and did_you_mean lets the agent offer a correction instead of just rejecting.
Wiring it into the agent loop
The pattern is the same regardless of framework. In your system prompt, tell the agent the policy and let the tool descriptions do the rest:
Before accepting a new signup, call
verify_email. Reject anything withrecommendation: do_not_send. Ifdid_you_meanis set, ask the user to confirm the corrected address. Before sending a campaign, run the list throughclean_email_listand only send to what survives.
Now the agent has a deliverability sense built into its decisions: fake signups bounce off at the door, typos get corrected, and lists get cleaned before send, all without you bolting on a separate validation step.
Notes
- Verdicts are
deliverable,undeliverable,risky, orunknown.riskyusually means a catch-all domain (confidence around 40) where no provider can confirm the individual mailbox; treat it as "send with caution." - Read-only tools like
get_creditsandget_accountcost nothing, so an agent can check its own balance before a big batch. - The free tier is 100 verifications, enough to wire the whole thing up end to end.
Point your agent at https://verifly.email/mcp, give it a key, and it can verify email the same way it calls any other tool. Full API and tool docs at verifly.email.
Top comments (0)