Content
<p align="center">
<img src="https://raw.githubusercontent.com/evidiq/evidiq-redact-mcp/main/assets/evidiq-redact.png" width="200" alt="EVIDIQ Redact" />
</p>
<h1 align="center">EVIDIQ Redact</h1>
<p align="center"><strong>Deterministic detection and removal of sensitive data — before an agent sends anything anywhere.</strong></p>
<p align="center">
Detect · Classify · Redact · Prove — checksum-validated PII, credential, and key detection for text, documents, and datasets, with a signed report and zero retention.
</p>
<p align="center">
<a href="https://evidiq.dev">evidiq.dev</a> ·
<a href="https://evidiq.dev/docs/redact">Redact Docs</a> ·
<a href="https://mcp.evidiq.dev/redact/skill.md">Agent Skill</a> ·
<a href="https://github.com/evidiq/evidiq">EVIDIQ Main</a> ·
<a href="https://github.com/evidiq/evidiq-redact-mcp">Redact MCP</a>
</p>
<p align="center">
<a href="https://mcp.evidiq.dev/redact/mcp"><img src="https://img.shields.io/badge/MCP%20Server-Live-3CCF4E?style=flat-square" alt="MCP Server Live" /></a> <a href="https://www.oklink.com/xlayer"><img src="https://img.shields.io/badge/X%20Layer-USDT0-3CCF4E?style=flat-square" alt="X Layer USDT0" /></a> <a href="https://mcp.evidiq.dev/redact/x402"><img src="https://img.shields.io/badge/x402-0.005%E2%80%930.03%20USDT0-2563EB?style=flat-square" alt="x402: 0.005 to 0.03 USDT0" /></a> <a href="https://web3.okx.com/onchainos/dev-docs/payments/service-seller-sdk"><img src="https://img.shields.io/badge/Payments-Official%20OKX%20SDK-121212?style=flat-square&logo=okx&logoColor=white" alt="Official OKX Payment SDK" /></a> <a href="https://www.oklink.com/xlayer/tx/0x001261081770e0c9bc82a736a4a7e8739d25fe01ca578a445aa311f238e8efc4"><img src="https://img.shields.io/badge/Settlement-Proven%20on%20X%20Layer-3CCF4E?style=flat-square" alt="Settlement proven on X Layer" /></a> <a href="https://www.okx.ai/agents/9700"><img src="https://img.shields.io/badge/OKX.AI-Agent%20%239700%20Listed-121212?style=flat-square&logo=okx&logoColor=white" alt="OKX.AI Agent 9700 listed" /></a> <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-3DA639?style=flat-square" alt="License: MIT" /></a>
</p>
---
> **Launch status: live endpoint, listed on OKX.AI.** The MCP server is
> deployed at `https://mcp.evidiq.dev/redact/mcp`, `onchainos payment quote` returns
> `ok:true`, paid calls settled through the official OKX Payment SDK, and the agent
> is actively listed on OKX.AI as Agent #9700.
The most common way sensitive data leaks is the most ordinary one: someone pastes
a document into a model. A customer record, an invoice, a support transcript, a
`.env` file, a seed phrase. It happens to individuals and to teams, and it happens
to autonomous agents that assemble prompts out of whatever context they were
given.
**EVIDIQ Redact is the outbound content gate for the agent economy.**
It finds sensitive data by *structure* rather than by guesswork — Luhn for card
numbers, mod-97 for IBANs, wordlist plus checksum for BIP-39 mnemonics, EIP-55 for
EVM addresses, issuer prefixes for provider API keys — removes it in the mode you
choose, and returns a signed report of exactly what was found and where. No model
in the hot path, so the same input always produces the same output and the same
digest. Nothing is stored.
## What it does
- **Checksum-validated detection** — card numbers, IBANs, BIP-39 mnemonics, private keys, EVM/BTC/SOL addresses, JWTs, and national IDs are confirmed by their own validation rules, not by a hopeful pattern.
- **Provider credential detection** — AWS, GitHub, OpenAI, Anthropic, Stripe, Slack, Google, Twilio, SendGrid, npm tokens, and `.env` blocks by issuer shape.
- **Five redaction modes** — `mask`, `label`, `hash` (per-request HMAC), `token` (stable, mapping returned once), `remove`. Validated secrets default to `remove`, because a masked private key is still a leaked private key.
- **Structure-preserving output** — markdown, HTML, CSV, JSON, NDJSON, and plain text come back with their shape intact.
- **Policy verdicts** — versioned profiles (`pii-basic`, `pci-lite`, `health-lite`, `crypto-hygiene`, `pre-prompt`) return `PASS` / `REVIEW` / `BLOCK` with the violations that caused it.
- **Dataset de-identification** — column-aware pseudonymization with stable tokens, plus quasi-identifier and re-identification-risk warnings.
- **Signed, offline-verifiable reports** — SHA-256 over a canonical envelope, EIP-191 signature, findings carried as **offsets and detector ids only, never values**.
- **Zero retention** — no content on disk, ever. Artifacts live in a bounded in-memory cache with a short TTL and are addressed by digest.
- **Pay per operation** — five paid tools at `0.005–0.03 USDT0`; five preflight and verification tools are free.
## Route to Redact when
Use Redact when content is about to **leave a trust boundary**: before a prompt
goes to a model, before a log is attached to a ticket, before a dataset is shared
with a vendor, before a transcript is archived, or when you need to prove after
the fact what was stripped out of a document.
Do **not** route endpoint or Agent Skill security scanning here (use **EVIDIQ
Sentinel** — that inspects what an agent *consumes*; Redact inspects what it
*emits*). Do not route durable action logging here (use **EVIDIQ Vault**); Redact
deliberately keeps nothing.
A natural chain: `redact_text` → send to the model → `notarize_inference`
(Notary) → `append_record` (Vault).
## Use it from any agent
```bash
# Read the public Skill document
curl -s https://mcp.evidiq.dev/redact/skill.md
# Inspect current x402 pricing discovery
curl -s https://mcp.evidiq.dev/redact/x402
# Connect the remote MCP server (Claude Code)
claude mcp add --transport http evidiq-redact https://mcp.evidiq.dev/redact/mcp
```
Public endpoints:
| Endpoint | Purpose |
|----------|---------|
| `https://mcp.evidiq.dev/redact/mcp` | Remote MCP transport |
| `https://mcp.evidiq.dev/redact/skill.md` | Agent-readable usage and safety guide |
| `https://mcp.evidiq.dev/redact/x402` | x402 v2 pricing and payment discovery |
| `https://mcp.evidiq.dev/redact/health` | Service health |
| `https://evidiq.dev/docs/redact` | Technical documentation |
## MCP tools
### Paid detection and redaction
| Tool | Cost | Atomic | Description |
|------|------|-------:|-------------|
| `redact_text` | `0.005 USDT0` | `5000` | Detect and redact one text blob; returns redacted text, findings with offsets, and a signed report |
| `scan_document` | `0.01 USDT0` | `10000` | Inventory only, no rewriting: which sensitive entities exist, where, at what confidence |
| `redact_document` | `0.015 USDT0` | `15000` | Structure-preserving redaction of markdown, HTML, CSV, JSON, NDJSON, or plain text |
| `policy_check` | `0.02 USDT0` | `20000` | Evaluate content against a named policy profile → `PASS` / `REVIEW` / `BLOCK` plus violations |
| `deidentify_dataset` | `0.03 USDT0` | `30000` | Column-aware pseudonymization with stable tokens and re-identification-risk warnings |
### Free preflight and verification
| Tool | Cost | Description |
|------|------|-------------|
| `redact_capabilities` | Free | Detector catalog and versions, policy profiles, limits, redaction modes, full pricing |
| `validate_input` | Free | Validate size, format, and encoding **and return a detector count** — without returning content or charging |
| `estimate_cost` | Free | Exact atomic and human-readable price for any paid tool |
| `verify_redaction_report` | Free | Recompute the report digest and verify its EIP-191 signature |
| `get_artifact` | Free | Retrieve a redacted artifact by id, within its in-memory TTL |
## Recommended workflow
Settlement happens **before** a paid tool runs, so a malformed argument is still
a paid call. Preflight for free first:
1. `redact_capabilities` — detector set version, policy profiles, limits, prices.
2. `validate_input` — confirms the format and size and tells you **how many**
findings exist, so you can decide whether redaction is worth paying for.
3. `estimate_cost` — the exact price of the operation you intend to run.
4. One paid call per request.
5. `verify_redaction_report` — free, offline verification of what you received.
## Engine limits
| Parameter | Value |
|-----------|-------|
| `maxInputBytes` | `262144` |
| `artifactTtlMs` | `600000` (10 minutes, in memory only) |
| Detector set version | `1.0.0` — 20 detectors |
| Policy profiles | `pii-basic`, `pci-lite`, `health-lite`, `crypto-hygiene`, `pre-prompt` |
| Redaction modes | `mask`, `label`, `hash`, `token`, `remove` |
| Formats | markdown, HTML, CSV, JSON, NDJSON, plain text |
Live values come from `redact_capabilities`, which is free.
## How a Redact call works
1. The input is validated for size, encoding, and format; oversized or unreadable input is refused before anything else runs.
2. A paid tool clears the x402 v2 payment gate before detection begins.
3. The format parser splits the content so redaction can preserve structure — CSV columns, JSON keys, HTML tags, fenced code blocks.
4. Detectors run in a single deterministic pass; checksum-validated families confirm their matches, pattern families report a confidence tier.
5. Overlapping matches are resolved so the longest validated match wins, and the chosen mode is applied per family.
6. The selected policy profile turns the findings into a `PASS` / `REVIEW` / `BLOCK` verdict with the violations that caused it.
7. A canonical report is hashed with SHA-256 and signed with EIP-191, carrying offsets and detector ids only.
8. Output and any token map are placed in the in-memory artifact cache under a digest, and returned once in the response.
## What a report proves, and what it does not
- It **does** prove that this exact input, under this detector set version and
this policy version, produced this exact output and these findings. Anyone can
re-run and compare digests.
- It **does not** prove the content is now free of sensitive data. Deterministic
detection has a recall limit, and unstructured personal names and postal
addresses are the weak spot — they are reported at low confidence and can never
alone drive a `BLOCK`.
- Findings carry **offsets and detector ids, never the matched values**. A report
that quoted what it found would itself be a leak, and reports get pasted into
tickets.
Confidence tiers: `validated` (a checksum or structural rule passed), `high` (an
issuer-defined credential shape), `medium` (a strong pattern), `low` (a heuristic
hint). Treat `low` as a prompt for human review, never as a verdict.
## Retention
Redact keeps nothing. There is no data directory and no environment variable to
create one.
- Caller content is never written to disk.
- Redacted output and token maps live in a bounded in-memory LRU with a short TTL
(default 10 minutes) and are addressed by digest; `get_artifact` is the only way
back to them.
- Logs record detector counts and digests, never content and never a finding's
value.
- A token map is returned once and never persisted, so a lost map means
re-identification is impossible. That is intended.
- 0G anchoring, when enabled, records the **report digest only** — never content —
and a 0G failure never fails a paid call.
## Pricing and x402
| Operation | Cost | Token | Network | Atomic |
|-----------|------|-------|---------|-------:|
| `redact_text` | `0.005` | USDT0 | X Layer (`eip155:196`) | `5000` |
| `scan_document` | `0.01` | USDT0 | X Layer (`eip155:196`) | `10000` |
| `redact_document` | `0.015` | USDT0 | X Layer (`eip155:196`) | `15000` |
| `policy_check` | `0.02` | USDT0 | X Layer (`eip155:196`) | `20000` |
| `deidentify_dataset` | `0.03` | USDT0 | X Layer (`eip155:196`) | `30000` |
| `redact_capabilities` | Free | — | — | — |
| `validate_input` | Free | — | — | — |
| `estimate_cost` | Free | — | — | — |
| `verify_redaction_report` | Free | — | — | — |
| `get_artifact` | Free | — | — | — |
Asset: USDT0 (6 decimals) on X Layer (`eip155:196`), contract `0x779ded0c9e1022225f8e0630b35a9b54be713736`.
### Official OKX Payment SDK
Payment verification and settlement run through the **official OKX Onchain OS Payment SDK**:
| Package | Role |
|---------|------|
| [`@okxweb3/x402-core`](https://www.npmjs.com/package/@okxweb3/x402-core) | `OKXFacilitatorClient` (HMAC-SHA256 OKX REST auth) and `x402ResourceServer` |
| [`@okxweb3/x402-evm`](https://www.npmjs.com/package/@okxweb3/x402-evm) | `ExactEvmScheme` — the EVM `exact` scheme server implementation |
The OKX facilitator verifies each authorization and settles it on X Layer; Redact
keeps ownership of the detector engine, the policy profiles, and report signing.
Each immutable per-tool price reaches the SDK as an explicit USD₮0 **atomic asset
amount** rather than a USD string, so neither the fee nor its token can be
substituted by currency conversion.
When the facilitator's own confirmation wait elapses it answers `timeout` even
though the transaction it broadcast can still confirm moments later, so Redact
resolves that state through the facilitator's settlement-status lookup rather than
discarding a paid call. Success is only ever reported when the facilitator
confirms it.
Integration guide: [OKX Onchain OS — integrate via SDK](https://web3.okx.com/onchainos/dev-docs/payments/service-seller-sdk).
## Proven on-chain
Live paid calls against the deployed endpoint completed the full x402 v2 round trip
through the official OKX facilitator. Both receipts are `status 0x1` on X Layer, and
both were **broadcast by an OKX facilitator relayer** rather than by a Redact-held
key — the on-chain evidence that settlement ran through the official SDK.
| Tool | Amount | Settlement tx | Result |
|------|--------|---------------|--------|
| `redact_text` | `0.005 USDT0` (`5000` atomic) | [`0x00126108…f238e8efc4`](https://www.oklink.com/xlayer/tx/0x001261081770e0c9bc82a736a4a7e8739d25fe01ca578a445aa311f238e8efc4) · success | `EMAIL`, `CARD_NUMBER`, `BIP39_MNEMONIC`, `EVM_PRIVATE_KEY` all detected; verdict `BLOCK`; every secret removed from the output; no matched value present in the report |
| `redact_text` | `0.005 USDT0` (`5000` atomic) | [`0x248519f5…310b4a65f1`](https://www.oklink.com/xlayer/tx/0x248519f51857b1857a324971151ea34de0c0a6772acf6895f31975310b4a65f1) · success | clean input, verdict `PASS`, digest `a5741299…` — signed by a signer that has since been **retired**, see below |
| `redact_text` | `0.005 USDT0` (`5000` atomic) | [`0x73bfcf0e…78f798bae`](https://www.oklink.com/xlayer/tx/0x73bfcf0ef6ddfb359f285a1b0546567a3723ba1e6b5cf2d5432cee278f798bae) · success | `EMAIL` and `CARD_NUMBER` detected and labelled; report signed by `0x8a3c7524…`, and `verify_redaction_report` returns `valid: true` on it |
The first row is the one that matters: a settled call on clean content proves only
that payment and signing work. Asserting on the *contents* of a result — which
detectors fired, what was removed, and that no matched value appears in the report —
is what proves the product. Free tools stay ungated and answer `200` without any
payment header.
### Retired signer
Reports produced before 2026-07-27 were signed by `0x606E21c6…`, whose private key
was present as a fallback literal in `lib/redact/report.ts` — in this public
repository — because the deployment's signer variable was misnamed. Anyone reading
the repo could have signed a report that passed verification, so those signatures
prove nothing and that address is retired. It never held funds and never sent a
transaction.
There is no fallback signer now: with no key configured, a report is returned
**unsigned** and says so, and `verify_redaction_report` reports the digest as
matching while refusing to attribute the origin. Live reports are signed by
`0x8a3c7524Aaed081825aC88eC7f4cCECFc583ee7D`.
Test vectors above are synthetic: a documented Visa test number, the canonical
all-`abandon` BIP-39 vector, and a well-known public Hardhat account key.
### Live Execution Proof (OKX `onchainos` CLI)
Recorded before the signer change: the `signer` in this transcript is the retired
`0x606E21c6…` described above, so treat this as evidence of the **payment** path
only. Current reports are signed by `0x8a3c7524…`.
```json
{
"ok": true,
"data": {
"status": "success",
"paymentId": "pay_97ad2cde3f87ab2378df4185",
"scheme": "exact",
"txHash": "0x248519f51857b1857a324971151ea34de0c0a6772acf6895f31975310b4a65f1",
"decodedReceipt": {
"status": "settled",
"amount": "5000",
"payer": "0x2a8efe3093278bb4bd3b2d9c7b5ba992ca4fc9b0",
"transaction": "0x248519f51857b1857a324971151ea34de0c0a6772acf6895f31975310b4a65f1"
},
"result": {
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\n \"data\": {\n \"redactedText\": \"EVIDIQ test onchain payment\",\n \"artifactId\": \"art_9bfa66ec93a89aca\",\n \"findings\": [],\n \"report\": {\n \"engine\": \"EVIDIQ-Redact/1.0\",\n \"verdict\": \"PASS\",\n \"integrity\": {\n \"algorithm\": \"SHA-256\",\n \"digest\": \"a57412998ba016df46354ef266643e3b7c4a4d934658020da602b64dfa7c6976\",\n \"signature\": \"0x9f9d5aa0c23027ba3fff62cd00cd0ec1f99c3f5830df2fcfeea5813c383033fc0816a59a6d61952ce00510266ebf92f4d2214f44d8a2e2c39a062fc968814ab71b\",\n \"signer\": \"0x606E21c6DA9aFa21098972EA490e967c76Bcfb05\"\n }\n }\n }\n}"
}
]
}
}
}
}
```
## Architecture
```mermaid
flowchart TB
agent["<b>AI agent / user</b><br/>MCP client"]
request{"Tool call<br/>free or paid?"}
agent -->|POST /redact/mcp| request
free["Free preflight<br/>capabilities · validate_input<br/>estimate · verify · get_artifact"]
gate["x402 v2 gate<br/>EIP-3009 exact · pay per operation"]
xlayer[("X Layer<br/>USD₮0 · eip155:196")]
request -->|free helper| free
request -->|paid operation| gate
gate -. verify and settle .-> xlayer
subgraph redact["EVIDIQ Redact trust boundary — nothing persisted"]
direction TB
parse["1. Format parser<br/>md · html · csv · json · ndjson · text"]
detect["2. Detector engine<br/>checksum-validated · issuer shapes · patterns"]
policy["3. Policy evaluation<br/>versioned profiles · PASS/REVIEW/BLOCK"]
apply["4. Redaction<br/>mask · label · hash · token · remove"]
report["5. Signed report<br/>SHA-256 digest · EIP-191 · offsets only"]
parse --> detect --> policy --> apply --> report
end
ttl[("In-memory artifacts<br/>bounded LRU · short TTL")]
apply -. digest-addressed .-> ttl
free --> parse
gate --> parse
response["<b>MCP response</b><br/>redacted content + findings + report"]
report --> response
classDef client fill:#312e81,stroke:#a78bfa,color:#ffffff,stroke-width:2px;
classDef payment fill:#052e16,stroke:#4ade80,color:#ffffff,stroke-width:2px;
classDef core fill:#0f172a,stroke:#38bdf8,color:#ffffff,stroke-width:2px;
classDef output fill:#4c1d95,stroke:#c4b5fd,color:#ffffff,stroke-width:2px;
class agent,request client;
class free,gate,xlayer payment;
class parse,detect,policy,apply,report core;
class response,ttl output;
style redact fill:#0f172a,stroke:#38bdf8,color:#e0f2fe,stroke-width:2px;
```
## Security boundaries
- Redact processes caller content in memory only; it never executes caller code and never fetches a remote resource on a document's behalf.
- No content on disk, no history, no accounts. Durable logging is Vault's job.
- Reports and logs carry offsets, detector ids, and digests — never matched values.
- Detection is deterministic and linear-time; input size is bounded and each request has a detector time budget, so hostile input cannot stall the service.
- Token maps are single-delivery and never persisted; re-identification is impossible after the response.
- EIP-191 signatures prove authenticity and non-repudiation of the attester key.
- No compliance certification is claimed. Policy profiles are engineering defaults, not legal advice.
## Self-host
Requirements: Node.js `22+` and npm.
```bash
npm install
npm run build
npm start
```
Or run the container:
```bash
docker build -t evidiq-redact .
docker run -d --name evidiq-redact -p 3000:3000 --env-file .env evidiq-redact
```
Local routes: `POST /mcp` · `GET /skill.md` · `GET /x402` · `GET /health`
No volume is required, by design.
### Configuration
Copy `.env.example` to `.env` and set parameters:
```bash
# Server
PORT=3000
HOSTNAME=0.0.0.0
PUBLIC_BASE_URL=https://mcp.evidiq.dev/redact
# Official OKX Payment SDK — all three credentials are required together
OKX_API_KEY=...
OKX_SECRET_KEY=...
OKX_PASSPHRASE=...
OKX_BASE_URL=https://web3.okx.com
# x402 v2 — X Layer mainnet / USDT0 (prices are fixed per tool; no X402_PRICE)
X402_CHAIN=eip155:196
X402_ASSET=0x779ded0c9e1022225f8e0630b35a9b54be713736
X402_PAY_TO=0x2a8efe3093278bb4bd3b2d9c7b5ba992ca4fc9b0
X402_DOMAIN_NAME=USD₮0
X402_DOMAIN_VERSION=1
X402_RPC=https://rpc.xlayer.tech
# Report signing (EIP-191) — accepted with or without the 0x prefix
REDACT_SIGNER_PRIVATE_KEY=...
REDACT_SIGNER_ADDRESS=0x...
# Limits
REDACT_MAX_INPUT_BYTES=262144
REDACT_ARTIFACT_TTL_MS=600000
# Optional: anchor the report DIGEST only, never content
OG_PRIVATE_KEY=...
OG_STORAGE_RPC=https://evmrpc.0g.ai
OG_STORAGE_INDEXER=https://indexer-storage-turbo.0g.ai
```
## Development
```bash
npm install # install dependencies
npm run build # compile TypeScript to dist/
npm test # validators, detectors, engine, policies, formats, report, x402
npm run dev # start local watch server
```
Start with `lib/redact/validators.ts` and its tests. Every checksum must be
verified against published vectors before any detector is written — the whole
product rests on those being correct.
## Links
- **Website** — https://evidiq.dev
- **Redact documentation** — https://evidiq.dev/docs/redact
- **Live MCP endpoint** — https://mcp.evidiq.dev/redact/mcp
- **Agent Skill** — https://mcp.evidiq.dev/redact/skill.md
- **x402 discovery** — https://mcp.evidiq.dev/redact/x402
- **Service health** — https://mcp.evidiq.dev/redact/health
- **OKX Payment SDK guide** — https://web3.okx.com/onchainos/dev-docs/payments/service-seller-sdk
- **EVIDIQ main repository** — https://github.com/evidiq/evidiq
- **x402 Protocol** — https://x402.org
## TypeScript SDK
A typed client for the live endpoint lives in [`sdk/index.ts`](sdk/index.ts) — 10 tools (5 free, 5 paid). Free tools answer a bare call; paid tools run the x402 flow automatically (402 challenge → `pay` hook → replay with the `x-payment` header). No key lives in the file.
```ts
import { RedactClient } from "./sdk/index.js";
const client = new RedactClient(); // endpoint defaults to https://mcp.evidiq.dev/redact/mcp
// free
const caps = await client.callTool("redact_capabilities", {});
// paid — settle the 402 challenge via the constructor's pay hook, or omit it
// to receive a PaymentRequiredError carrying the full x402 v2 challenge
const result = await client.callTool("some_paid_tool", { arg: "value" });
```
The `pay` hook receives the decoded x402 v2 challenge (`{ x402Version, resource, accepts[] }` — payTo, asset, amount) and returns the value for the `x-payment` header, e.g. an EIP-3009 `transferWithAuthorization` settled via the official OKX SDK. Without a hook, paid calls throw `PaymentRequiredError` so the caller can settle however it wants.
## License
MIT © 2026 EVIDIQ — see [LICENSE](./LICENSE). Part of the [EVIDIQ](https://github.com/evidiq/evidiq) trust and execution layer for the AI agent economy.
Connection Info
You Might Also Like
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...
gemini-api-docs-mcp
A remote HTTP MCP server for searching Google Gemini API documentation.