omitly-mcp
OfficialClick 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., "@omitly-mcpFind and redact all emails and phone numbers in my PDF"
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.
omitly-mcp
A Model Context Protocol server that exposes Omitly's local, verifiable PDF redaction to AI agents (Claude Code, Claude Desktop, and any other MCP client).
Repository scope and licence — please read before opening a PR.
This repository is source-available, not open source. See
LICENSE: the code is published so you can read exactly what runs on your machine before you let it touch a confidential document. It is not licensed for reuse in other projects.It contains the MCP server and the compiled wasm detection bundle. The Omitly redaction engine, the tamper-evidence seal and the licensing implementation are not in this repository and are developed privately; this code calls the engine, it does not contain it.
Development happens in a private repository and is mirrored here on release, so pull requests cannot be merged. Issues and security reports are very welcome — see
SECURITY.md.
The point of difference: an agent can redact a document without uploading it anywhere. Redaction runs on-device through the Omitly engine and returns a signed audit log proving the data was removed — the opposite of pasting a confidential file into a chat model.
Four of the eight tools (find_sensitive_regions, locate_text,
check_redaction, verify_redaction) work out of the box — npm install,
no Rust toolchain, no native binary, no desktop app. They run on a
wasm-bindgen build of the same detector that powers the web leak-checker at
omitly.app, bundled directly in this package. create_pdf, the two
write tools (redact_pdf, redact_by_entity), and verify_seal still need
a configured native engine — see "Build & run" below. verify_seal has no
wasm fallback at all: there is no wasm seal-verification path, so it always
requires the native engine.
Tools
Tool | What it does |
| Scans a PDF on-device and returns PII candidates — email/SSN/phone/card plus Australian identifiers (TFN, ABN, ACN, Medicare, Centrelink CRN, IHI, BSB; check-digit validated where a published algorithm exists) — with page + exact coordinates, so the agent selects by entity and never guesses geometry. Best-effort pattern matching, not a compliance assessment. Optional |
| Resolves literal strings the model supplies (names, addresses — anything regex can't catch) to their page + coordinates. The model does the recognition; the engine does the geometry. |
| One-shot: find + filter by kind ( |
| Removes the underlying data from given regions of a PDF, verifies nothing survives, writes the redacted file, and returns the audit log. |
| Re-scans an already-redacted PDF and returns the verification verdict — the redaction-completeness check. |
| Cryptographically checks a PDF's embedded Omitly audit report and trailing Ed25519 tamper-evidence seal — the tamper-evidence check, distinct from |
| Generates a clean PDF from Markdown/HTML on-device, rendered through a real browser engine so it looks printed — instead of writing a throwaway reportlab/LaTeX script. |
Related MCP server: PDF Redaction MCP Server
PDF generation (create_pdf)
create_pdf is served by a separate binary, omitly-pdf (in
crates/omitly-pdf), kept apart from the redaction engine because generation is
a different trust model from verifiable redaction. It renders Markdown (or raw
HTML) through a headless Chromium-family browser (Chrome/Chromium/Edge/Brave;
override with OMITLY_BROWSER_BIN) — the same engine family the Omitly app's
webview uses, so output looks printed rather than script-generated. omitly-pdf
ships with the Omitly desktop application; its source is not in this repository.
Point OMITLY_PDF_BIN at the binary to enable this tool.
// stdin
{ "command": "create", "outputPath": "/abs/out.pdf",
"source": "# Hello\n\nBody **markdown**", "format": "markdown", "title": "Hello" }
// stdout
{ "ok": true, "output": "/abs/out.pdf" }Typical agent flows:
Quick:
redact_by_entity(find + redact + verify in one call).Careful:
find_sensitive_regions/locate_text→ review →redact_pdf→verify_redaction. Coordinates fromfind/locatedrop straight intoredactas itsregionsargument.
See DEMO.md for a full Claude Code walkthrough.
Status
The MCP surface (eight tools, schemas, transport), the native engine binary
(crates/omitly-cli, built as omitly-redact), and the bundled wasm engine
(crates/leakcheck-wasm, covering the four free tools without a native
binary) are all implemented and pass end-to-end tests. find_sensitive_regions
is a first-pass detector (ASCII patterns, per-show-operator matching): treat
its hits as candidates for review, not a completeness guarantee. An LLM can
always supply additional regions directly.
Privacy of findings. Detection results are returned with a masked
preview (e.g. •••-••-6789), never the raw value. The file isn't uploaded and
the secret detected inside it isn't sent back through the model — redaction is
driven entirely by page + coordinates, so the plaintext stays on the machine.
Engine contract (implemented in crates/omitly-cli)
The server spawns OMITLY_REDACT_BIN, writes a JSON request to stdin, and reads
a JSON response from stdout. Any failure returns { "ok": false, "error": "..." }
(the process still exits 0, so the caller reads ok rather than the exit code).
// stdin
{ "command": "find", "pdfPath": "..." }
// stdout
{ "ok": true, "count": 2, "regions": [
{ "page": 0, "x": 250.4, "y": 610.4, "width": 79.2, "height": 14.4, "kind": "ssn", "preview": "•••-••-6789" } ] }
// `preview` is masked — the raw value never leaves the process; redaction is driven by coordinates.// stdin
{ "command": "redact", "pdfPath": "...", "outputPath": "...",
"regions": [{ "page": 0, "x": 72, "y": 700, "width": 200, "height": 14, "reason": "PII.SSN" }] }
// stdout — also writes "<outputPath>.audit.json" beside the file
{ "ok": true, "output": "...", "audit": { "verdict": "pass", "regions": [ ... ], "warnings": [], "metadataScrubbed": true } }// stdin — recovers the redacted regions from "<pdfPath>.audit.json"
{ "command": "verify", "pdfPath": "..." }
// stdout — hiddenContent re-checks thumbnails / document actions / embedded
// files on the delivered bytes (omitly#171); any fail flips the verdict
{ "ok": true, "verdict": "pass", "regions": [ ... ], "metadataScrubbed": true,
"hiddenContent": [ { "class": "thumbnails", "verification": { "result": "pass" } }, ... ] }// stdin — checks the embedded audit report + trailing Ed25519 seal, not
// redaction completeness (that's "verify" above)
{ "command": "verify_seal", "pdfPath": "..." }
// stdout — verdict is one of: no_report | seal_invalid |
// seal_unsupported_version | incomplete | verified. seal_unsupported_version
// means this verifier is too old to check the seal at all — sealValid is
// `null` (checked nothing), never true or false; carriesAuditReport flags
// whether the file also carries an Omitly audit report (escalation signal).
{ "ok": true, "verdict": "verified", "sealValid": true, "sealFingerprint": "...",
"allPassed": true, "metadataScrubbed": true, "regionCount": 2, "pageCount": 4,
"warnings": [], "licenseProvenance": null,
"inputSha256": "...", "outputSha256": "...",
"sourceFilename": "...", "outputFilename": "..." }Build & run
Free tools only (find_sensitive_regions, locate_text, check_redaction, verify_redaction) — no native engine needed:
cd omitly-mcp
npm install # published releases ship the wasm build already bundled
npm run build # plain tsc; the wasm bundle ships prebuilt in wasm/
node dist/index.jsnpm install omitly-mcp from the registry gets a package with wasm/
already built — a published install never needs Rust.
This repository also ships the compiled wasm bundle in wasm/, alongside
wasm/leakcheck_wasm_bg.wasm.sha256 so you can verify the byte-for-byte
artifact you received. It is the same bundle published in the npm package.
That means npm install && npm run build && npm test works here with no Rust
toolchain: npm run build is plain tsc. The wasm is compiled from the
Omitly detection engine, whose Rust source is not part of this repository
(see "Repository scope" below).
Everything, including create_pdf, verify_seal, and the two write tools
(redact_pdf, redact_by_entity): verify_seal has no wasm fallback —
unlike the four free tools above, it always needs the native engine
configured, even though it carries no licence requirement (see "Licensing"
below).
# Build and start the MCP server (no Rust toolchain needed)
npm install
npm run build
node dist/index.js
# To enable the native-engine tools as well, point at a directory containing
# the Omitly engine binaries (omitly-redact, omitly-pdf). These ship with the
# Omitly desktop application; their source is not in this repository.
OMITLY_ENGINE_DIR=/abs/path/to/engine node dist/index.jsOne env var covers both binaries: OMITLY_ENGINE_DIR is the directory holding
omitly-redact and omitly-pdf. Per-binary overrides (OMITLY_REDACT_BIN,
OMITLY_PDF_BIN) win over the directory when set. When OMITLY_ENGINE_DIR
(or OMITLY_REDACT_BIN) isn't set, find_sensitive_regions, locate_text,
and check_redaction transparently use the bundled wasm engine instead —
same detector, no native binary. verify_redaction does too, but with a
narrower check: without a native engine there's no <path>.audit.json
sidecar to verify specific regions against, so it falls back to a general
re-scan of the whole file (still useful — a non-empty result still means the
file isn't clean — just not the same rigor as the sidecar-based check).
find/redact need qpdf for the redaction pipeline (QPDF_BIN overrides the
PATH lookup). find alone (native or wasm) is read-only and works without it.
Access control
Every path in a tool call comes from the model, so the server confines all reads and writes to one allowed directory:
OMITLY_ALLOWED_DIR— set it in the MCP config (recommended). Without it, the directory the server was started in is used.Symlinks are resolved before the check, so a link inside the root pointing outside it is refused.
Outputs never overwrite an existing file (or its
.audit.jsonsidecar); the agent is asked to pick a fresh name instead.OMITLY_ENGINE_TIMEOUT_MS(default 120000) — a wedged engine process is killed at the deadline instead of hanging the agent's tool call.
These are guardrails against confused-deputy mistakes, not a sandbox against a
hostile local user — see docs/THREAT-MODEL.md.
Licensing
redact_pdf/redact_by_entity are the write surface, enforced inside the
engine binary (not in this server, and not bypassable by the bundled wasm
fallback — wasm never touches these two tools): a Pro or Personal licence
(OMITLY_LICENSE_FILE, or the Omitly desktop app's activated licence on the
same machine) runs unmarked; otherwise the shared 14-day trial applies and
the audit output is permanently marked as evaluation output. The redaction
itself is never degraded, and licence checks never touch the network.
find_sensitive_regions, locate_text, check_redaction, verify_redaction,
and verify_seal are free — and verify_redaction/verify_seal are free
forever with no cap and no marking (recipient-side verification everywhere
is the point). The two free detection tools (find_sensitive_regions,
check_redaction) on the wasm tier — i.e. with no native engine configured —
are metered (omitly#226): results carry an evaluation: true flag plus an
EVALUATION banner, and after a monthly number of free checks (default 10,
OMITLY_FREE_CAP to tune) the tool returns a structured
{ blocked: true, reason: "free-cap" } refusal until the month rolls over.
The count lives in ~/.omitly/usage.json (override the directory with
OMITLY_STATE_DIR; written 0600) and is local-only — nothing ever phones
home; deleting the file resets the free count, which is accepted (the
no-network doctrine makes it unavoidable), and the counter is deliberately
never consulted by any paid write path. Calls served by a configured native
engine are not metered here — the licence rules above apply on that path
instead. verify_seal (native-only) stays free by the same design in the
engine (no Pro/Personal licence check on that command path either).
Register with Claude Code
claude mcp add omitly -- env \
OMITLY_ENGINE_DIR=/path/to/engine-dir \
OMITLY_ALLOWED_DIR=/path/agents/may/touch \
node /abs/path/to/omitly-mcp/dist/index.jsOr in Claude Desktop's claude_desktop_config.json:
{
"mcpServers": {
"omitly": {
"command": "node",
"args": ["/abs/path/to/omitly-mcp/dist/index.js"],
"env": {
"OMITLY_ENGINE_DIR": "/path/to/engine-dir",
"OMITLY_ALLOWED_DIR": "/path/agents/may/touch"
}
}
}
}One-click install for Claude Desktop (MCPB, free tier only)
mcpb/ packages the four free/diagnosis tools (check_redaction,
find_sensitive_regions, locate_text, verify_redaction) — never the write
tools — as a self-contained MCPB .mcpb
extension: no Node/npm/Rust toolchain on the end user's machine, just
"Install Extension…" in Claude Desktop. This is a deliberately smaller,
separate server (mcpb/server/index.js) from dist/index.js above, so the
bundle can never expose redact_pdf/redact_by_entity/create_pdf even by
accident.
Download: releases.omitly.app/mcp/omitly-leak-check.mcpb
— always the current version (published by publish-npm.yml on every real
omitly-mcp release; a versioned copy + checksum also live at
mcp/latest.json). Drag the
downloaded file into Claude Desktop, or use "Install Extension…".
Or build it yourself from source:
npm run mcpb:pack # copy wasm/ into mcpb/wasm + npm install + mcpb pack
# → dist-mcpb/omitly-leak-check.mcpbmcpb:pack needs no Rust toolchain — it reuses the prebuilt wasm/ in this repository
(builds the shared wasm detector once, then copies it into mcpb/ — see
mcpb/scripts/copy-wasm.mjs). The packed .mcpb itself needs nothing but
Node, already bundled inside Claude Desktop.
Not signed (mcpb sign needs a code-signing cert we don't have yet — same
gate as desktop app signing). mcpb info on the packed file confirms
WARNING: Not signed. Whether Claude Desktop's "Install Extension…" flow
blocks or just warns on an unsigned .mcpb has NOT been confirmed against the
real Desktop app in this change (no Desktop GUI in this environment) — that
check is still open, tracked in omitly#225.
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 Servers
- Flicense-qualityDmaintenanceA local MCP server that extracts text-layer content from PDF files, enabling AI agents to inspect, extract text, outlines, and page content.
- AlicenseAqualityDmaintenanceA Model Context Protocol (MCP) server that provides comprehensive PDF redaction capabilities, including text and image redaction, search, and session-based in-memory operations using FastMCP and pymupdf.11MIT
- AlicenseAqualityBmaintenanceA local-first MCP server that ingests PDFs, extracts structure, and provides semantic search and sequential navigation tools for AI clients to query and learn from documents.10MIT
- AlicenseAqualityCmaintenanceFast, local PDF parsing as an MCP server with text extraction, bounding boxes, OCR, and visual citations. No cloud or API key required.5MIT
Related MCP Connectors
Remote MCP for C2PA intake verifier MCP, structured receipts, audit logs, and reviewer-ready evidenc
Generate PDFs from templates via AI chat. Works with Claude, ChatGPT, Cursor, and any MCP client.
Remote MCP for C2PA disclosure policy MCP, structured receipts, audit logs, and reviewer-ready evide
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/omitly/omitly-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server