Ask an AI assistant if your email has been in a data breach. You'll get a neat, confident answer. And it's a guess.
It's not really the model's fault. It can't look anything up, so it fills the gap from old training data. But a guess is a bad answer when the question is about your own account.
I run XposedOrNot, a free and open-source breach index. I kept copying API results into chat windows by hand, and it felt silly. So I added an MCP endpoint to the API.
(New to MCP? It's a standard way to give an AI assistant tools it can call. You point it at a server and it works out when to use what.)
Here's what I wanted from it. A lot of breach lookup servers ask for a paid API key or a local install before they do anything. This one asks for nothing.
No key. No signup. Nothing to install.
Just a URL, and it's free.
Set it up (about two minutes)
Using Claude Code? It's one line:
claude mcp add --transport http xposedornot https://api.xposedornot.com/mcp
Cursor users, put this in ~/.cursor/mcp.json:
{
"mcpServers": {
"xposedornot": { "url": "https://api.xposedornot.com/mcp" }
}
}
And for VS Code, it goes in .vscode/mcp.json:
{
"servers": {
"xposedornot": { "type": "http", "url": "https://api.xposedornot.com/mcp" }
}
}
Now ask a normal question. Something like "has my email been in any breaches, and what leaked?"
You don't have to name a tool. The assistant reads the tool list and picks one.
Want to see what the assistant sees? Use curl
I like this part the most. There's no magic in MCP. It's JSON over HTTP, one request per POST, so you can call the server yourself:
curl -s -X POST https://api.xposedornot.com/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| jq -r '.result.tools[].name'
check_email_breaches
get_breach_analytics
list_breaches
domain_breach_summary
get_breach_metrics
get_recent_breaches
You get six tools back. Here's what each one is for:
| You ask | Tool | You get |
|---|---|---|
| Has this email been breached? | check_email_breaches |
Breach names |
| How bad is it? | get_breach_analytics |
Dates, data types, a risk score |
| Which breaches hit this company? | list_breaches |
Catalog entries by domain or breach ID |
| How exposed is my domain? | domain_breach_summary |
Counts only |
| How big is the index? | get_breach_metrics |
Totals per year and industry |
| What's new? | get_recent_breaches |
Latest additions |
You can call a tool by hand too:
curl -s -X POST https://api.xposedornot.com/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"domain_breach_summary","arguments":{"domain":"example.com"}}}' \
| jq -r '.result.content[0].text'
{"sendDomains": {"breaches_details": [{"domain": "example.com", "breach_pastes": 50, "breach_emails": 10000, "breach_total": 10474, "breach_count": 172, "breach_last_seen": "01-Aug-2026"}]}, "SearchStatus": "Success"}
See that? Only counts. It won't list the email addresses behind a domain, and that's on purpose.
Four things I learned building it
Keep it stateless. No sessions and no SSE stream. Each request stands on its own (a GET just gets a 405).
Our early docs told people to add "type": "sse", and their connections broke because of it. That one's on me, so if you still have that line in your config, take it out.
Tell the client your tools are read-only. All six carry readOnlyHint: true and idempotentHint: true.
Why does that matter? The client can ask you for permission once, not on every single call. Nobody likes a tool that nags.
Write error messages for the model. If the assistant sends x as the email, it doesn't get a stack trace. It gets this:
'x' is not a valid email address. Provide a full address such as user@example.com.
That's a sentence the model can read. So it can fix the call and try again.
Leave some tools out. There's no password tool here. Nothing returns a password, a hash, or a person's address from a domain lookup. We started with three tools in October 2025 and we're at six now, but that one stays out.
Free has a limit (and what to do past it)
Free doesn't mean endless. The limits are per IP: 25 email checks an hour and 100 a day. Give it fifty addresses and it'll stop at 25.
That's fine for checking your own accounts, one address at a time. But I'll be honest, people hit it fast.
Need more than that? Maybe you're putting breach checks into your own product, or checking a lot of users.
That's what xonPlus is for. Same breach data, but with an API key and much higher limits (up to 25,000 requests a minute).
And one ask from me. Please only check emails and domains that are yours to check. This is for looking at your own exposure, not someone else's.
It's all open
The code is MIT licensed. You'll find the MCP handler in main.py in the XposedOrNot-API repo. It's in the official MCP registry too, as com.xposedornot/xposedornot, if your client installs from there.
The MCP page lists every tool, and our blog post has the Claude Desktop steps as well.
Have you built an MCP server? I'm curious about one thing.
Could you keep it stateless, or did you end up needing sessions? Tell me what pushed you there.
Top comments (0)