Redacts PII/PHI from text before it reaches an LLM. Fail-closed, self-hosted, no egress.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
An MCP server that redacts PII/PHI from text before it ever reaches an LLM β self-hosted, fail-closed, and HIPAA-aware.
Teams building LLM and agent pipelines in regulated domains have no clean, drop-in way to strip PHI/PII from a payload before it crosses into a model provider's infrastructure. umbryn-mcp is that boundary: three MCP tools β redact, restore, detect β that scrub sensitive values into reversible placeholders, run entirely inside infrastructure you control, and block the request if detection is uncertain instead of leaking data.
Send the redacted text to the model; keep the token_map local; call restore afterward to rehydrate the result. Round-trips are byte-exact and proven with property-based tests.
The PHI/PII-redaction MCP niche is real but underserved β the existing options are thin Presidio wrappers with no HIPAA-specific detection and, critically, no guarantee that a detection failure blocks the request instead of silently passing raw data through. So teams either roll their own boundary or ship sensitive data to a provider and lean on a BAA to cover it β the design-time mistake that causes real compliance incidents.
| Naive Presidio wrapper | Regex-in-your-app | Cloud DLP API | umbryn-mcp | |
|---|---|---|---|---|
| Drop-in MCP tools | sometimes | β | β | β |
| Fail-closed on uncertain detection | β | β | β | β |
| HIPAA identifiers (NPI, DEA, MBI, MRN, CLIA) | β | partial | partial | β |
| Reversible (restore original) | rarely | DIY | some | β |
| Runs self-hosted, zero egress | β | β | β (sends data out) | β |
| Works with zero heavy deps | β (needs spaCy) | β | n/a | β (regex engine) |
| Optional ML NER (names, addresses) | β | β | β | β
([presidio] extra) |
Why it was built: MCP went mainstream fast β it's now first-class in Claude, Cursor, and ChatGPT, across thousands of servers β but the PHI/PII-redaction corner was left to a few unmaintained wrappers. This fills that gap with a single honest, auditable, fail-closed boundary, kept open source so the redaction logic you depend on is fully inspectable rather than a black box.
redact (β scrubbed text + reversible token map), restore (β original), detect (β entities found, no mutation).pip install "umbryn-mcp[presidio]" adds Microsoft Presidio + spaCy for PERSON/LOCATION NER, transparently.restore(redact(x)) == x for arbitrary input; same input + config always yields the same output.Reach for umbryn-mcp when:
redact β send to model β restore.Reach for something else when:
Then register it with your MCP client.
Claude Desktop / Claude Code (claude_desktop_config.json, or claude mcp add umbryn-mcp -- umbryn-mcp):
Cursor (.cursor/mcp.json) and VS Code use the same shape β see examples/ for ready-to-paste configs.
Want name/address detection too?
The server auto-detects Presidio and upgrades β no config change needed. (Set UMBRYN_ENGINE=regex to force the dependency-free engine, or =presidio to require the ML one.)
A tool call comes in over stdio; the Redactor core runs the configured detection engine, resolves overlaps deterministically, applies the fail-closed threshold check, and swaps detected spans for reversible typed placeholders. Only scrubbed text is meant to leave the boundary you run.
The Redactor core depends only on a small DetectionEngine interface β never on Presidio or MCP directly. Raw data and the detection engine stay inside the boundary you run; only scrubbed text leaves it. See docs/ARCHITECTURE.md and docs/THREAT_MODEL.md.
redact(text) β { redacted_text, token_map, entities }Replaces detected PHI/PII with typed placeholders like [NPI_1]. token_map maps each placeholder back to its original value β keep it local; never send it to the model. entities lists what was redacted (type/span/score) for auditing.
restore(redacted_text, token_map) β { text }Reverses a redaction, recovering the original text exactly. Safe to call on model output that still contains the placeholders.
detect(text) β { entities, count }Reports the entities found β type, span, confidence β without modifying the text. Unlike redact, it surfaces low-confidence hits rather than blocking, so you can inspect coverage before trusting the boundary in a pipeline.
The pattern is redact β model β restore, with the token map never leaving your side:
redact(user_text). Send only redacted_text to the LLM. Keep token_map in your process β treat it as sensitively as the raw input, and never pass it to the model.[NPI_1], [US_SSN_1], etc. β semantically neutral tokens it can reason about and echo back.restore(model_output, token_map) to swap the real values back into the model's response before it reaches your user or database.redact returns a [LOW_CONFIDENCE] or [DETECTION_ERROR] tool error, the boundary refused to leak β surface it, tighten input, or lower the risk, but don't send the raw text onward.Before trusting it in a pipeline, call detect(sample_text) on representative (synthetic) data to see exactly what is and isn't caught, and tune the thresholds (below) to your risk tolerance.
Two thresholds govern every redact call:
detection_floor (default 0.35) β the sensitivity boundary. Signals below it are treated as noise.min_confidence (default 0.5) β the trust threshold.No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/umbryn-mcp)<a href="https://allmcps.com/mcp/umbryn-mcp"><img src="https://allmcps.com/api/badge/umbryn-mcp?style=directory" alt="Umbryn MCP on AllMCPs" /></a>