npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

omitly-mcp

v0.1.0

Published

Model Context Protocol server exposing Omitly's local, verifiable PDF redaction to AI agents. Redaction runs on-device — documents are never uploaded.

Readme

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).

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 seven 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 and the two write tools (redact_pdf, redact_by_entity) still need a configured native engine — see "Build & run" below.

Tools

| Tool | What it does | |------|--------------| | find_sensitive_regions | 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 regions (generic/us/au) narrows the listed kinds. | | locate_text | 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. | | redact_by_entity | One-shot: find + filter by kind (email/ssn/phone/card/tfn/abn/acn/medicare/crn/ihi/bsb) and/or regions + redact + verify. The "just scrub the obvious PII" shortcut. | | redact_pdf | Removes the underlying data from given regions of a PDF, verifies nothing survives, writes the redacted file, and returns the audit log. | | verify_redaction | Re-scans an already-redacted PDF and returns the verification verdict. | | create_pdf | 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. |

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. Build it and point OMITLY_PDF_BIN at the binary:

cargo build -p omitly-pdf --release   # → target/release/omitly-pdf
// 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_pdfverify_redaction. Coordinates from find/locate drop straight into redact as its regions argument.

See DEMO.md for a full Claude Code walkthrough.

Status

The MCP surface (seven 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
{ "ok": true, "verdict": "pass", "regions": [ ... ], "metadataScrubbed": true }

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  # local/dev only: also runs wasm-pack (needs Rust + wasm-pack)
node dist/index.js

npm install omitly-mcp from the registry gets a package with wasm/ already built — a published install never needs Rust. Building from source (this repo) does need wasm-pack (cargo install wasm-pack) and the wasm32-unknown-unknown target, since npm run build regenerates the wasm bundle from ../crates/leakcheck-wasm via npm run build:wasm.

Everything, including create_pdf and the two write tools (redact_pdf, redact_by_entity):

# 1. Build the local engine binaries (from the repo root)
cargo build -p omitly-cli -p omitly-pdf --release   # → target/release/{omitly-redact,omitly-pdf}

# 2. Build and start the MCP server
cd omitly-mcp
npm install
npm run build
OMITLY_ENGINE_DIR=/abs/path/to/target/release node dist/index.js

One 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.json sidecar); 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, and verify_redaction are free forever — the wasm build backing them has no licence logic at all, because there's nothing to gate.

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.js

Or 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"
      }
    }
  }
}