{"_id":"redacta-mcp","_rev":"7-249d59f8644b7a455a9344119323c741","name":"redacta-mcp","dist-tags":{"latest":"2.1.0"},"versions":{"1.1.0":{"name":"redacta-mcp","version":"1.1.0","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@1.1.0","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"1f9608f8b24840fbf7ca742fc5c30322cb272adc","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-1.1.0.tgz","fileCount":6,"integrity":"sha512-PJyUbsyBzWDWQjDC2u3fbVmo6wpHYowOalwUm8WanxN2VHY/Xo0hfy05eBUVv670rD0GO2lVwF8dK64jnp7gwA==","signatures":[{"sig":"MEUCIQCMSxYNRhiJsI4ekUyIyfsGo1R/R1D0XUa03UwwENg74QIgKPveJv5bCxff4fLPxbFP6yGBgZlAE0OX57Zd8DFxK2w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27089},"type":"module","gitHead":"b1f2148ab19bed174c67c891ecb237639b919bc5","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"pharmatools","email":"nickjlamb@gmail.com"},"_npmVersion":"10.8.2","description":"MCP server that pseudonymises patient identifiers and PII in text, and restores them — runs locally, nothing leaves your machine.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"zod":"^3.23.8","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_1.1.0_1781254484815_0.7344137652338507","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"redacta-mcp","version":"1.1.1","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@1.1.1","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"1ab1f42645e53784b0bce7ec489621b85c547298","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-1.1.1.tgz","fileCount":6,"integrity":"sha512-a5/22hyvdOmW+Un0YcrgL/VC20+dYPypoKkqlvNaykPmfZB8ubC/y/JzN4iXRoZXW7Cu0RI//60E65qmEq3g0Q==","signatures":[{"sig":"MEUCIDwhNO05oPqQq4GbkAQ3wPRsNwxQU8BxmnV60/R5jsQKAiEAqAN3KJmc5hu8JUt60zOhe+b4WaJ2OS3vN9qCjEIpmk0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27552},"type":"module","gitHead":"f67db4443bf3898ebd5101fc9f274a9b481e1f3a","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"pharmatools","email":"nickjlamb@gmail.com"},"_npmVersion":"10.8.2","description":"MCP server that pseudonymises patient identifiers and PII in text, and restores them — runs locally, nothing leaves your machine.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"zod":"^3.23.8","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_1.1.1_1781258849492_0.5832913829434914","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"redacta-mcp","version":"1.1.2","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@1.1.2","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"7a84f8d821a13bec6c7ba804766976c55c765d82","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-1.1.2.tgz","fileCount":4,"integrity":"sha512-BIi3jVIeqf1Ee//Pv0yq9urtRED+WP+rPUF2p6lG+kn+Yo/oCybqHamCPC3nCvyrdWjlEQEDpVgnoup0s0SdtQ==","signatures":[{"sig":"MEYCIQClF/NXzGyfkTAlC1XySkDRqZv54YWn3AZIT3/k+/GQSgIhAKujF38E20uSDqx52jEY+6XVNlcRGHknz6zmmyU3RsJo","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":8090},"type":"module","gitHead":"cb3edff8bf71da110a65056bfa0a1884354a5049","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"pharmatools","email":"nickjlamb@gmail.com"},"_npmVersion":"10.8.2","description":"MCP server that pseudonymises patient identifiers and PII in text, and restores them — runs locally, nothing leaves your machine.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"zod":"^3.23.8","@pharmatools/redacta":"^1.1.1","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_1.1.2_1781263233052_0.9966319996773472","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"redacta-mcp","version":"1.2.0","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@1.2.0","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"3a165f41090c7bcd6a695784c9fc2df0fc004371","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-1.2.0.tgz","fileCount":4,"integrity":"sha512-Hm106HLnJVeSuo9GprUB0C7uY0ZmFFJ9Clmx/O9D/ooY61rfMa8njzfc+NJ7KNGQWFvLdi0G6RmogkUO65kZ2w==","signatures":[{"sig":"MEUCICWL8Qnqdb7Lj1YoFPtLwAF054/QvSlgzlCN4O/Ex7/ZAiEA/io5DyWxg3ZgO1eLGR0gtYIfxWB9EK+DdLibUcI49o0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":8351},"type":"module","gitHead":"03a292cd7af75490ba78e686d41d458a12205625","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"pharmatools","email":"nickjlamb@gmail.com"},"_npmVersion":"10.8.2","description":"MCP server that pseudonymises patient identifiers and PII in text, and restores them — runs locally, nothing leaves your machine.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"zod":"^3.23.8","@pharmatools/redacta":"^1.2.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.8","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_1.2.0_1781275346449_0.7575941038374507","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"redacta-mcp","version":"1.2.1","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@1.2.1","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"3a3644518ce40680d5c4d6660678932a011a8db9","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-1.2.1.tgz","fileCount":4,"integrity":"sha512-++r6RkpoJDSB11RgECS3Ajt+HDhaP3ZgSRk3i11PHDuD62Gu2qtBu4F8GSHiEG0CGUOCBhg5HxOQQ9tiK5bn6g==","signatures":[{"sig":"MEYCIQDAKyb+PVa57BysIVkSeuc+sLSX8zQ6ODyDxMsWg/KK5wIhAJ2bkJyTLtIrIiodf2UAiI0s1agLutJK2f5JksKrYjKr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":8399},"type":"module","gitHead":"df8ee9edb757c9362539d22abafb05a01f252759","mcpName":"io.github.nickjlamb/redacta-mcp","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"pharmatools","email":"nickjlamb@gmail.com"},"_npmVersion":"10.8.2","description":"MCP server that pseudonymises patient identifiers and PII in text, and restores them — runs locally, nothing leaves your machine.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"zod":"^3.23.8","@pharmatools/redacta":"^1.2.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.8","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_1.2.1_1781278779836_0.09622175379801323","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"redacta-mcp","version":"2.0.0","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"author":{"url":"PharmaTools.AI","name":"Nick Lamb"},"license":"MIT-0","_id":"redacta-mcp@2.0.0","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"homepage":"https://www.pharmatools.ai/redacta","bugs":{"url":"https://github.com/nickjlamb/redacta/issues"},"bin":{"redacta-mcp":"dist/index.js"},"dist":{"shasum":"5faad175c9a64506f4da323d914cf7c18df09d93","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-2.0.0.tgz","fileCount":16,"integrity":"sha512-BFmMyXKzUioSvY8zhtrqWMgqAXC9al+Cd1lPMeK0Ui6XW9dHstWbliCaOT95E7i0U1RTIppgzftim4vuLjvR5g==","signatures":[{"sig":"MEQCICmk8prQ74NJZO4SXKBg4mCAQV+fFI4UKIQMMkDUPzfvAiBGEAohPNVvm2ZN92vSwmlNTis4mcn4VBfyFOVD19I/LQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/redacta-mcp@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":47246},"type":"module","gitHead":"90940189c6d37985e1f5ad02f397da8d74e8a645","mcpName":"io.github.nickjlamb/redacta-mcp","scripts":{"test":"vitest run","build":"tsc","start":"node dist/index.js","build:mcpb":"node mcpb-build.mjs","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f058eaeb-dfdf-47a8-a2be-d2a27f1c5b65"}},"repository":{"url":"git+https://github.com/nickjlamb/redacta.git","type":"git","directory":"mcp-server"},"_npmVersion":"12.0.2","description":"MCP server that acts as a stateful privacy boundary: pseudonymises patient identifiers and PII before they reach an AI agent, keeps the reversal mapping outside the model context, and restores identifiers only at the trusted boundary. Runs locally, nothin","directories":{},"_nodeVersion":"22.23.1","dependencies":{"zod":"^3.23.8","@pharmatools/redacta":"^1.2.0","@modelcontextprotocol/sdk":"^1.12.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.8","esbuild":"^0.25.12","typescript":"^5.4.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/redacta-mcp_2.0.0_1786088728173_0.7867112947148065","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"redacta-mcp","version":"2.1.0","mcpName":"io.github.nickjlamb/redacta-mcp","description":"MCP server that acts as a stateful privacy boundary: pseudonymises patient identifiers and PII before they reach an AI agent, keeps the reversal mapping outside the model context, and restores identifiers only at the trusted boundary. Runs locally, nothin","license":"MIT-0","author":{"name":"Nick Lamb","url":"PharmaTools.AI"},"homepage":"https://www.pharmatools.ai/redacta","repository":{"type":"git","url":"git+https://github.com/nickjlamb/redacta.git","directory":"mcp-server"},"bugs":{"url":"https://github.com/nickjlamb/redacta/issues"},"type":"module","bin":{"redacta-mcp":"dist/index.js"},"keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"scripts":{"build":"tsc","build:mcpb":"node mcpb-build.mjs","start":"node dist/index.js","test":"vitest run","prepublishOnly":"npm run build"},"dependencies":{"@modelcontextprotocol/sdk":"^1.12.0","@pharmatools/redacta":"^1.4.0","zod":"^3.23.8"},"devDependencies":{"@types/node":"^20.14.0","esbuild":"^0.25.12","typescript":"^5.4.0","vitest":"^4.1.8"},"gitHead":"f386d90dc8b29ce70464c7e7e618979dc5698ad5","_id":"redacta-mcp@2.1.0","_nodeVersion":"22.23.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-cvsMx7eyI2TBoxxYiytjL9rPkK7F6bx0TWHw4kydShHGQmHf7N2bTEZpwA0QSJAdlVYOV1RIPxue5D8/xtGylw==","shasum":"cdfe701aa42cd69e450f05e054e49da72c7b04be","tarball":"https://registry.npmjs.org/redacta-mcp/-/redacta-mcp-2.1.0.tgz","fileCount":12,"unpackedSize":40580,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/redacta-mcp@2.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIH/6V99FLNNfbwQ1jgUEFdXddueKa5hvfR4M+jcPHZRuAiEAldy5IRFP/JP6c7V2ZQ1w40QQ9KLqvBX9Iw3SCrf2x1A="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f058eaeb-dfdf-47a8-a2be-d2a27f1c5b65"}},"directories":{},"maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/redacta-mcp_2.1.0_1786256721085_0.7695529992294039"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-12T08:54:44.746Z","modified":"2026-08-09T06:25:21.561Z","1.1.0":"2026-06-12T08:54:44.955Z","1.1.1":"2026-06-12T10:07:29.619Z","1.1.2":"2026-06-12T11:20:33.198Z","1.2.0":"2026-06-12T14:42:26.620Z","1.2.1":"2026-06-12T15:39:39.993Z","2.0.0":"2026-08-07T07:45:28.333Z","2.1.0":"2026-08-09T06:25:21.242Z"},"bugs":{"url":"https://github.com/nickjlamb/redacta/issues"},"author":{"name":"Nick Lamb","url":"PharmaTools.AI"},"license":"MIT-0","homepage":"https://www.pharmatools.ai/redacta","keywords":["mcp","modelcontextprotocol","redaction","pseudonymisation","de-identification","pii","phi","healthcare","nhs","privacy"],"repository":{"type":"git","url":"git+https://github.com/nickjlamb/redacta.git","directory":"mcp-server"},"description":"MCP server that acts as a stateful privacy boundary: pseudonymises patient identifiers and PII before they reach an AI agent, keeps the reversal mapping outside the model context, and restores identifiers only at the trusted boundary. Runs locally, nothin","maintainers":[{"name":"pharmatools","email":"nickjlamb@gmail.com"}],"readme":"# Redacta MCP server\n\n**Keep patient identifiers out of AI agent context.**\n\nAn [MCP](https://modelcontextprotocol.io) server that acts as a **stateful\nprivacy boundary** between clinical text and AI agents. `protect` replaces\npatient identifiers with labelled tokens (`[NHS_NUMBER_1]`,\n`[PATIENT_NAME_1]`, …) and keeps the reversal mapping **inside the server\nprocess** — the agent receives only the protected text and an opaque session\nID. Restoration happens at the boundary, on your terms.\n\n```text\nclinical text ──▶ protect ──▶ agent sees tokens only\n                     │\n                     └─ token map stays in server memory\n                        (never in the tool result, never in model context)\n\nagent output ──▶ release_to_file ──▶ restored text lands in a folder\n                                     you configured; the agent gets a\n                                     receipt, not the identifiers\n```\n\nEverything runs locally in the server process: **no network calls, no\npersistent storage.** Same deterministic engine as the\n[Redacta skill](https://clawhub.ai/nickjlamb/redacta), libraries, CLI and iOS\napp. Listed in\n[Anthropic's MCP Directory](https://claude.ai/directory/connectors/ant.dir.gh.nickjlamb.redacta)\n— one-click install in Claude Desktop.\n\n## Tools\n\n| Tool | What it does |\n|------|--------------|\n| `protect` | Redact text; the token map stays server-side. Returns protected text, an opaque `session_id`, a category report, and a self-check. |\n| `release_to_file` | Restore identifiers into text from a protected session, writing the result to a file inside `REDACTA_RELEASE_DIR` (atomic, `0600`, generated filename). Returns a receipt only — restored data never enters the model context. |\n| `release_to_client` | Opt-in (`REDACTA_RELEASE=client\\|both`): returns restored text in the tool result, for trusted environments. Carries an explicit warning. |\n| `check_output` | Scan model output for verbatim reappearance of a session's original values (spacing/dash/case tolerant) and re-tokenise anything found. Reports leaked categories — never the raw values. |\n| `discard_session` | Delete a session's mapping immediately instead of waiting for expiry. |\n| `redact`, `reinstate`, `self_check` | **Legacy (v1)** — unchanged, for backward compatibility and client-managed workflows. `redact` returns the token map to the caller, which places the reversal key in the client and potentially the model context; prefer `protect`. Hide with `REDACTA_LEGACY_TOOLS=0`. |\n\n## Sessions\n\nMappings live in server memory only: sessions expire after\n`REDACTA_SESSION_TTL_MINUTES` (default 60), are capped at\n`REDACTA_MAX_SESSIONS` (default 64, oldest evicted), and disappear when the\nserver exits — the safe failure direction. Any invalid, expired or discarded\nsession yields the same generic error, so session IDs cannot be probed.\n\n## Detection\n\nDeterministic patterns with checksum validation — NHS numbers (Modulus-11), UK\nNational Insurance numbers, dates of birth (keyword-anchored; appointment dates\npreserved), UK postcodes, US SSNs/ZIPs, hospital/MRN numbers, emails, phones —\nplus general PII (URLs, IPs, Luhn-validated cards, IBANs, account numbers, UK\nvehicle regs) and keyword-anchored patient/relative/carer names (clinician names\npreserved by design). Names in free prose are not caught; review the output.\n\n## Use with Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"redacta\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"redacta-mcp\"],\n      \"env\": {\n        \"REDACTA_RELEASE_DIR\": \"/Users/you/Documents/Redacta\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop. Then: *\"Protect this letter before you summarise it\"*\n→ `protect` runs and Claude works on tokens only; *\"restore the real details\ninto a file\"* → `release_to_file` writes the re-identified result to your\nrelease folder and Claude sees only the receipt.\n\n## Configuration\n\n| Env var | Default | Meaning |\n|---------|---------|---------|\n| `REDACTA_RELEASE` | `file` | Where restored output may go: `file`, `client`, `both`, or `off` (no release tools at all) |\n| `REDACTA_RELEASE_DIR` | *(unset)* | Existing directory where `release_to_file` may write. Unset → the tool explains how to configure it |\n| `REDACTA_SESSION_TTL_MINUTES` | `60` | Session lifetime |\n| `REDACTA_MAX_SESSIONS` | `64` | Concurrent session cap |\n| `REDACTA_AUDIT_LOG` | *(unset)* | Path to a JSONL audit log (events + category counts + hashed session IDs; never source text, values, or mappings) |\n| `REDACTA_LEGACY_TOOLS` | `1` | `0` hides the v1 `redact` / `reinstate` / `self_check` tools |\n\n## Migrating from v1\n\nNothing breaks: the v1 tools keep their exact schemas and behaviour. The\ndifference is what you should reach for. In v1, `redact` handed the token map\nback to the MCP client — fine when a human drives the round trip, but in an\nagent workflow it puts the reversal key into the model's context. In v2,\n`protect` + `release_to_file` keep the mapping at the boundary. See\n[`DESIGN.md`](DESIGN.md) for the full design, threat notes and test strategy.\n\n## Local development\n\n```bash\nnpm install\nnpm run build\nnpm test          # engine + privacy-boundary tests (vitest)\nnpm start         # run the server on stdio\n```\n\nThe acceptance tests run a real MCP client against the server over an\nin-memory transport and assert that no original identifier value and no token\nmap ever appears in a `protect` or `release_to_file` response.\n\n## Publishing\n\nTo npm (powers the `npx redacta-mcp` install above):\n\n```bash\nnpm publish\n```\n\nThen list it on the MCP registries for discovery:\n\n- **Official MCP registry** — <https://registry.modelcontextprotocol.io>\n- **Smithery** — `smithery mcp publish`\n- **Glama** — auto-indexes published npm MCP servers; verify the listing\n- **mcp.so / PulseMCP** — community submission\n- **awesome-mcp-servers** — open a PR adding the entry\n\n## Privacy Policy\n\nRedacta runs entirely on your device.\n\n- **Data collection:** none. Redacta does not collect or transmit any of the\n  text you pass to it, and makes no network calls.\n- **Usage & storage:** input text is processed in memory. Token maps are held\n  in server memory for the session lifetime, then discarded; they are never\n  returned to the client by `protect` and never written to disk. The only\n  disk writes are the ones you configure: re-identified output into\n  `REDACTA_RELEASE_DIR` when you call `release_to_file`, and the optional\n  audit log (which contains no PHI, no values and no mappings).\n- **Third-party sharing:** none.\n- **Contact:** info@pharmatools.ai\n\nFull policy: https://www.pharmatools.ai/privacy-policy\n\n## Desktop extension (MCPB) for the Claude Connectors Directory\n\nRedacta is a local stdio server, so it's distributed to Claude as a Desktop\nExtension (MCPB), not a remote connector.\n\n```bash\nnpm run build:mcpb                      # bundles mcpb/server.mjs (+ icon)\nnpx @anthropic-ai/mcpb pack mcpb        # produces redacta-<version>.mcpb\n```\n\nThe manifest declares no network access, links the privacy policy, and asks\nthe user for an optional release folder at install time.\n\n### Automated releases (Anthropic MCP Directory)\n\nRedacta is published in the Anthropic MCP Directory via a **pull-based** flow —\nno submission form per release. The workflow at\n[`.github/workflows/mcpb-pack.yaml`](../.github/workflows/mcpb-pack.yaml) builds\nthe bundle, packs a versioned `.mcpb`, and attaches it to the GitHub Release\nwhenever a tag matching `redacta-*` is pushed. The directory review cycle then\npicks the new tag up automatically.\n\n**First decide whether the engine changed.** The workflow publishes only\n`redacta-mcp` — not the shared `@pharmatools/redacta` engine. So:\n\n- **Engine changed?** Publish it first, otherwise the MCP build picks up the old\n  version:\n  ```bash\n  # in npm-package/: bump version, then\n  npm publish\n  # then bump the \"@pharmatools/redacta\" range in mcp-server/package.json to match\n  ```\n- **MCP server only?** Skip the above and go straight to tagging.\n\nTo cut the release:\n\n```bash\n# from repo root, after bumping the version in mcp-server/package.json\ngit tag redacta-2.0.0\ngit push origin redacta-2.0.0\n```\n\nThe workflow syncs `package.json` + `mcpb/manifest.json` to the tag version,\nbuilds, and publishes `redacta-2.0.0.mcpb` to the release. Tag convention:\n`redacta-<version>` → asset `redacta-<version>.mcpb`.\n\nRegistered with the directory as: **repo** `nickjlamb/redacta`, **tag pattern**\n`redacta-*`. For a one-off / first manual submission, pack locally and upload the\n`.mcpb` via the\n[Desktop extension submission form](https://clau.de/desktop-extention-submission).\n\nThe same tag also fans out to the other distribution channels:\n\n1. **GitHub Release** — attaches `redacta-<version>.mcpb` (Anthropic directory).\n2. **npm** — publishes `redacta-mcp@<version>` (`publish-npm` job).\n3. **Official MCP Registry** — publishes `io.github.nickjlamb/redacta-mcp`\n   (`publish-registry` job, after npm has indexed the version).\n\nOne-time setup — **no secrets required**; both npm and the registry authenticate\nwith tokenless GitHub OIDC (`id-token: write`):\n\n- **npm Trusted Publishing** — on npmjs.com, open the `redacta-mcp` package →\n  *Settings → Trusted Publisher → GitHub Actions*, and register:\n  repository `nickjlamb/redacta`, workflow `mcpb-pack.yaml`. After that the\n  `publish-npm` job publishes via OIDC (and gets build provenance for free).\n- **MCP Registry** — needs no setup; the `io.github.nickjlamb/*` namespace is\n  granted automatically because the workflow runs in a repo owned by that account.\n\n## Limits\n\nBe precise about what the boundary does and doesn't give you. Detection is\ndeterministic + keyword-anchored — not a guarantee, and not a substitute for\nformal data-protection processes. `check_output` detects **verbatim**\nreappearance of session values only: paraphrases, inferred identities and\ninformation the model learned elsewhere are out of scope. Sessions live in\nmemory, so a server restart ends them (by design). And if you use the legacy\n`redact` tool, treat the `token_map` as the key that reverses the redaction:\nstore it with the same care as the original data.\n\n## License\n\nMIT-0. Built by [PharmaTools.AI](https://www.pharmatools.ai/redacta).\n","readmeFilename":"README.md"}