privacy
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@privacyanonymize these records with k=5 and give me the utility report"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
privacy
k-anonymity enforcement with utility measurement, built to run entirely inside
the boundary that holds the regulated data. There is no runtime network access:
records are loaded, generalized, and released in-process, and a test
(tests/airgap.test.ts) fails the build if any source file imports a network or
child-process module.
What it does
Given a table of records and a description of which columns are quasi-identifiers
(age, ZIP, gender — the fields that, combined, re-identify a person), it produces
a release where every combination of quasi-identifier values occurs at least k
times. It does this by full-domain generalization (coarsening values along a
taxonomy or into numeric bins) plus suppression of the records that cannot be
protected any other way. It then reports what that cost in utility.
Related MCP server: privacyscrubber-mcp
Architecture
The core is a pure library with no I/O:
generalization.tsturns a raw quasi-identifier value into a coarser label at a chosen level (numeric bins or a categorical taxonomy).kanonymity.tsruns a greedy full-domain search over those levels, suppressing the residual small groups, and provides an independentisKAnonymousaudit.utility.tsscores what enforcement cost (suppression, information loss, discernibility, class size).
Around that core sits the server: tools.ts validates untrusted JSON and applies
resource limits, mcp/server.ts dispatches JSON-RPC, and index.ts frames it
over stdio. Any model-assisted step goes through the PrivacyAdvisor interface,
whose only in-tree implementation is a deterministic local stub — so the whole
system runs offline and, by construction, never sends data off the host. The
decisions behind this shape are recorded in docs/adr/.
Requirements
Node 22.6 or newer (the code is TypeScript executed directly via Node's type stripping; there is no build step).
Install and test
npm ci
npm testnpm test runs the suite with node --test; no API key or network is needed.
Usage
import { enforce, isKAnonymous } from './src/kanonymity.ts';
import { NumericGeneralizer, CategoricalGeneralizer } from './src/generalization.ts';
import { utilityReport } from './src/utility.ts';
const records = [
{ age: 21, zip: 'A1', diagnosis: 'flu' },
{ age: 22, zip: 'A2', diagnosis: 'cold' },
// ...
];
const quasiIdentifiers = [
new NumericGeneralizer('age', 20, 60, 5),
new CategoricalGeneralizer('zip', {
A1: ['A1', 'A', '*'],
A2: ['A2', 'A', '*'],
}),
];
const result = enforce(records, { k: 2, quasiIdentifiers, maxSuppression: 0.05 });
result.satisfied; // true if k met within the suppression ceiling
result.released; // generalized records safe to publish
result.suppressedCount; // records dropped to protect the rest
isKAnonymous(result.released, ['age', 'zip'], 2); // independent audit check
utilityReport(result, quasiIdentifiers); // suppression, info loss, discernibilityField roles without touching the data
StubAdvisor classifies columns into roles (identifier, quasi-identifier,
sensitive, other) from their names only — never their values — so schema
review can happen without exposing cells. It is the deterministic, offline
implementation of the PrivacyAdvisor interface in src/providers/base.ts; a
networked model could replace it, but only behind that same interface and only
by explicit choice.
import { StubAdvisor } from './src/providers/stub.ts';
await new StubAdvisor().suggestRoles(['patient_id', 'age', 'zip', 'diagnosis']);How enforcement chooses levels
The search is greedy. Starting from raw values it repeatedly raises the
generalization level of whichever quasi-identifier most reduces suppression,
breaking ties toward lower information loss, until suppression falls within the
configured ceiling or every field is fully generalized. Greedy full-domain
recoding is fast and produces auditable releases (one level per column), but it
is not guaranteed optimal — a lattice search such as Incognito would find the
minimal generalization at higher cost. That tradeoff is deferred; see the TODO
in src/kanonymity.ts.
Running as an MCP server
The entry point is a Model Context Protocol server speaking JSON-RPC 2.0 over stdio. It has no runtime dependencies and never opens a socket, so it runs where the data lives.
node src/index.tsIt exposes three tools:
classify_fields— assign privacy roles to column names (names only)enforce_kanonymity— generalize/suppress records to meetk, with a utility reportcheck_kanonymity— audit an existing release
Example exchange (one JSON object per line on stdin, responses on stdout):
{"jsonrpc":"2.0","id":1,"method":"initialize"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"enforce_kanonymity","arguments":{"k":2,"records":[{"age":21,"city":"London"},{"age":22,"city":"London"}],"quasiIdentifiers":[{"field":"age","kind":"numeric","min":20,"max":60,"step":5},{"field":"city","kind":"categorical","taxonomy":{"London":["London","*"]}}]}}}Bad input (malformed JSON, unknown tool, oversized request) is reported without
taking the stream down: caller mistakes come back as JSON-RPC errors or
isError tool results, and only genuinely unexpected faults return
-32603. Logs are structured JSON on stderr — stdout carries the protocol only.
Configuration
Set via environment variables; all are optional.
Variable | Default | Meaning |
|
|
|
|
| reject requests with more rows |
|
| cap quasi-identifier columns |
|
| cap categorical taxonomy size |
The limits exist so one oversized request cannot exhaust memory on the host that holds the regulated data. Invalid values fail fast at startup.
Known limitations
k-anonymity alone does not defend against attribute disclosure: if every member of an equivalence class shares the same sensitive value, k-anonymity holds yet the value leaks. l-diversity or t-closeness would address this and are not implemented.
The generalization search is greedy, not optimal (see ADR 0002). It can pick a higher level than a full lattice search would.
Generalizers require explicit bounds/taxonomies; they are not inferred from the data. This is deliberate — inferring bins from values would couple the metadata step to the data it must stay clear of — but it means the caller supplies them.
Enforcement holds the dataset in memory.
PRIVACY_MAX_RECORDSbounds this; there is no streaming or on-disk path for datasets larger than RAM.The
StubAdvisorclassifies by English field-name substrings; non-English or opaque schemas fall through toother.
Layout
src/kanonymity.ts— enforcement and the independentisKAnonymouschecksrc/generalization.ts— numeric and categorical generalizerssrc/utility.ts— suppression rate, information loss, discernibilitysrc/providers/— the advisor interface and its offline stubsrc/mcp/server.ts— JSON-RPC 2.0 message dispatchsrc/tools.ts— input validation, resource limits, tool wiringsrc/config.ts,src/logger.ts— configuration and structured loggingsrc/index.ts— stdio entry point (runServer)tests/— behaviour tests plus the air-gap guard
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Privacy-preserving synthetic health data generation. FHIR R4/R5 compliant.
Stateless PII redaction over MCP/REST. Free ≤1000 words or $0.01/call; file upload supported.
Governed data discovery, exact queries, decisions, simulations, and runtime utilities over MCP.
MCP server for detecting and redacting PII (Personally Identifiable Information) in PDF documents.
Related MCP Servers
- AlicenseAqualityBmaintenanceAnonymize PII and redact text for GDPR using real NLP, not just regex. Czech-first, built on ÚFAL/LINDAT (MasKIT + NameTag NER) with 80+ PII patterns. Also multilingual NER across 35+ languages, morphology (UDPipe), machine translation, and spellcheck. 6 tools. Non-commercial use only. Install: pip install anonymize-mcp64MIT
- AlicenseAqualityBmaintenanceSanitizes text and files by removing PII, secrets, and custom patterns locally before sending to LLMs, with optional reverse-scrubbing.33272MIT
- FlicenseAqualityAmaintenanceA read-only MCP server for bounded table discovery, deterministic profiling, and maintained-library statistical testing (Welch's t-test and two-proportion z-test) using SQLite, pandas, SciPy, and statsmodels.31-
- FlicenseNot gradedqualityCmaintenanceMCP server for anonymizing and deanonymizing PII through the Pseudora API, enabling safe sharing of sensitive text with AI assistants.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/J-X0/ferryyard'
If you have feedback or need assistance with the MCP directory API, please join our Discord server