Every AI agent that reads your files, drafts an email, or summarizes a support ticket eventually passes that content to an LLM as part of a prompt or tool call. If the content contains personal data, the model provider now has it too — regardless of what the agent's system prompt says about privacy. anonym.plus runs a local MCP server that sits between your files and your agent: it detects and anonymizes PII on the device, hands the agent a redacted version to work with, and reverses the substitution afterward — entirely without a network call.
The Problem: Agents Leak PII Into Prompts and Tool Calls
An agentic coding or research tool doesn't just answer a question — it reads files, calls functions, and feeds the results back into the model's context window as part of the next turn. If you ask Claude Desktop to "summarize this customer complaint" or Cursor to "refactor this function using the sample data in fixtures.json," whatever PII sits in that file — a customer's name, email, phone number, national ID, address, or a support ticket full of both — gets serialized straight into a prompt or a tool-call payload and sent to whichever model is backing the agent. The agent has no PII awareness of its own; it treats a Social Security number and a variable name identically, as tokens in a string.
This is invisible by default. Nothing in a typical agent session shows you what left your machine as part of a tool call, and most users never think to check. For anyone bound by GDPR (Regulation (EU) 2016/679), HIPAA, or an internal data-handling policy, that's a real exposure: personal data can leave the device the moment an agent reads a file that contains it, well before a human reviews the output.
How a Local MCP Server Solves It
The Model Context Protocol (MCP) gives AI agents a standard way to call external tools. anonym.plus exposes its PII detection and anonymization engine as an MCP server that runs locally — bound to loopback (127.0.0.1), not a public address — so only processes on the same machine can reach it. Two things make it safe to leave connected day to day:
- Off by default. The local API/MCP server is disabled until you turn it on in Settings and copy the connection config into your agent host. Nothing listens on any port until you opt in.
- Bearer-token authenticated. Every request needs
Authorization: Bearer <token>plus a requiredX-Local-Api: 1header. The token is generated locally and shown once in Settings — there's no account or cloud handshake involved in issuing it.
Because detection runs through the same on-device engine anonym.plus uses for documents — Microsoft Presidio and spaCy, bundled into the desktop app — a tool call to anonymize_text never leaves the host to get its answer. The agent asks a local process to redact a string; the local process answers instantly with the redacted string. No document, image, or fragment of it crosses the network in either direction.
The Six Tools
The MCP server exposes six tools over JSON-RPC 2.0 (POST http://127.0.0.1:<port>/mcp) — the same six are also available as plain REST endpoints under /v1/* for hosts that don't speak MCP yet.
| Tool | What it does | Min plan |
|---|---|---|
analyze_text | Detects PII entities in a text string and returns their type, offsets, and confidence score — no redaction. | Basic |
anonymize_text | Detects and replaces PII with placeholder tokens, returning the anonymized text plus a reversible mapping the caller holds. Nothing is written to the vault or history. | Basic |
deanonymize_text | Takes anonymized text and its mapping and restores the original values. | Deanonymize |
list_entity_types | Lists the built-in, language-agnostic PII entity types the engine can detect (340+). | Basic |
analyze_image | Detects PII inside an image (ID scans, screenshots, forms) up to 10 MiB. | Expert |
redact_image | Box-redacts detected PII in an image and returns the redacted image, base64-encoded. | Expert |
Every tool call is stateless with respect to the vault: none of the six reads, writes, unlocks, or locks your encrypted local vault. The mapping produced by anonymize_text is held entirely by the caller — your agent — for the length of the conversation, not persisted by anonym.plus.
A Worked Example: Anonymize, Then Deanonymize
Say an agent needs to draft a reply to a customer email before sending it through an LLM for tone-checking. It calls anonymize_text first:
// tools/call → anonymize_text
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": { "name": "anonymize_text",
"arguments": { "text": "Email john.doe@acme.com about invoice 4471." } } }
// result
{ "anonymized_text": "Email <EMAIL_ADDRESS_1> about invoice <NUMBER_1>.",
"mapping": { "<EMAIL_ADDRESS_1>": "john.doe@acme.com", "<NUMBER_1>": "4471" } }
The agent sends only "Email <EMAIL_ADDRESS_1> about invoice <NUMBER_1>." to the LLM — the customer's real email address and invoice number never appear in that prompt. Once the model returns its drafted reply (still using the placeholder tokens), the agent calls deanonymize_text with the same mapping to restore the real values locally, before the reply is shown to the user or sent:
// tools/call → deanonymize_text
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "deanonymize_text",
"arguments": {
"anonymized_text": "Hi <EMAIL_ADDRESS_1>, following up on invoice <NUMBER_1> — it's now paid.",
"mapping": { "<EMAIL_ADDRESS_1>": "john.doe@acme.com", "<NUMBER_1>": "4471" }
} } }
// result
{ "text": "Hi john.doe@acme.com, following up on invoice 4471 — it's now paid." }
The round trip is fully reversible because the mapping never leaves the local machine — the LLM only ever sees the tokens, never the values they stand for.
How to Connect Your Agent
Open anonym.plus and go to Settings → Local API / MCP. Turning it on generates a port and a bearer token, and the panel gives you a ready-made connection block to paste into your agent host's MCP config (Claude Desktop's claude_desktop_config.json, Cline's MCP settings, Cursor's mcp.json, or any other MCP-compatible host). Once connected, the six tools above appear alongside your agent's other tools — the agent decides when to call anonymize_text the same way it decides when to call any other tool, based on its system prompt or your explicit instruction to "anonymize before sending."
If a call arrives without the bearer token, without the X-Local-Api: 1 header, from a different origin, or for a tool your plan doesn't include, the server rejects it (401/403) rather than silently degrading. A locked vault only blocks operators that need stored keys (by-id operators return 409 keys_unavailable) — analyze_text, anonymize_text, and deanonymize_text don't touch the vault at all.
Why Local Beats Cloud Redaction
Cloud-based PII redaction APIs solve a different problem: they require sending the raw text or image to a remote endpoint to get a redacted version back — which means the very data you're trying to protect from the LLM has now also been sent to a second third party. A local MCP server collapses that round trip: detection and anonymization happen in the same process space as the agent itself, on the same machine, with the same network boundary the agent's other local tools already respect. There's no additional vendor in the data path, no additional subprocessor to vet, and no additional latency from a network hop — the tool call returns as fast as any other local function call.
FAQ
Does the MCP server work without an internet connection?
Yes. Detection runs through the same offline engine anonym.plus uses everywhere else — Presidio and spaCy bundled into the app. The MCP server itself is just a local HTTP listener on loopback; disconnecting from the internet entirely doesn't change how it responds.
Can any process on my network reach the MCP server?
No. The server binds to 127.0.0.1, so only processes on the same machine can connect, and it additionally requires a bearer token plus the X-Local-Api: 1 header on every request. It's also off by default — you have to enable it in Settings before anything listens.
Does anonym.plus see or store what my agent sends through the MCP tools?
No. The tools are stateless with respect to the vault and history — nothing passed to analyze_text, anonymize_text, or the other tools is persisted by anonym.plus. The reversible mapping from anonymize_text is returned to the caller (your agent) and held there for as long as the agent's session needs it.
See the full tool schemas and error codes in the docs, or download anonym.plus and connect your MCP-compatible agent from Settings → Local API / MCP.