The io.github.presidio-v/presidio-hardened-x402-mcp MCP server is a pre-payment PII screener for x402. It is intended to catch emails, SSNs, and names before agents sign, supporting privacy and security engineering workflows for agentic payments.
🛠️ Key Features
Pre-payment PII screening for x402
Detects emails
Detects SSNs
Detects names
MCP server for Model Context Protocol integration
🚀 Use Cases
Screening payment-related input before agent execution/signing
Reducing exposure of PII in agentic payments pipelines
Privacy-focused hardening steps for x402 flows
⚡ Developer Benefits
Clear PII detection scope (emails, SSNs, names)
Fits into MCP-based tool/service architectures
Aligns with topics including hardening, privacy, and security engineering
⚠️ Limitations
Described functionality is limited to identifying emails, SSNs, and names before agents sign (no additional behaviors specified)
Pre-payment safety gate for x402 — agents call screen_payment_metadata(...), check_payment_policy(...), and check_payment_replay(...) before signing, catching PII, budget overruns, and duplicate payments before metadata or money leaves the agent host.
Part of the presidio-hardened-* toolkit family. Thin MCP (Model Context Protocol) adapter over the presidio-hardened-x402 library, pinned for parent 0.11.x compatibility (presidio-hardened-x402>=0.11.1,<0.12.0). The >=0.11.1 floor is a security floor, not a preference — it is the release that closed the percent-encoded PII redaction bypass.
Why this exists
x402 agentic payments routinely carry user-supplied free text — descriptions, memos, query-string parameters — straight through to merchants and facilitators. When an LLM agent generates that text, it can include PII the user never intended to share. Once the merchant logs it, retention is their decision, not yours.
This MCP server gives agents a small default-deny gate before payment leaves the agent host. Three tools expose the parent library's stable pre-payment controls: PII redaction, spending policy, and replay detection. They are designed to compose with payment-execution and endpoint-safety MCP servers (x402station, Coinbase x402, Sardis, ...), while newer parent-library surfaces — evidence-ref@1 verification, the v0.9.1 SLO broker, the v0.10.0 settlement-ref@1 treasury binding, and the v0.11.0 CapabilityEnforcer — stay in the Python library unless an MCP tool explicitly wraps them later.
Install & configure
Requires Python ≥ 3.10. Distributed on PyPI; recommended invocation via uvx (no global install).
Claude Desktop / Claude Code
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on your platform:
Detects and redacts PII in payment metadata. No side effects — safe to call repeatedly.
jsonc
// Input{"resource_url":"https://api.foo.com/u/jane@example.com","description":"monthly fee for jane@example.com","reason":""}// Output{"redacted_resource_url":"https://api.foo.com/u/<EMAIL_ADDRESS>","redacted_description":"monthly fee for <EMAIL_ADDRESS>","redacted_reason":"","entities_found":[{"entity_type":"EMAIL_ADDRESS","field":"resource_url","count":1},{"entity_type":"EMAIL_ADDRESS","field":"description","count":1}],"mode":"in_process"}
entities (optional list of Presidio entity types) narrows detection to a whitelist. Field-length caps mirror the screening-api wire contract that remains stable through parent 0.7.x: resource_url ≤ 2048, description ≤ 4096, reason ≤ 4096 characters. Oversized inputs raise ValueError.
check_payment_policy(resource_url, amount_usd)
Spending-policy gate. Records the spend on success — call exactly once, immediately before payment. Skipping the actual payment after a successful check inflates the daily-limit ledger until the window rolls over.
jsonc
// Input{"resource_url":"https://api.foo.com/x","amount_usd":1.50}// Output (allowed){"allowed":true}// Output (denied — over per-call limit of $5.00){"allowed":false,"reason":"...","limit_usd":5.00,"amount_usd":6.00}
Duplicate-payment gate via HMAC-SHA256 fingerprint of the canonical fields. Records the fingerprint on success — call exactly once, immediately before payment.
amount is a string to preserve precision. Cross-process detection requires PRESIDIO_X402_FINGERPRINT_KEY (and optionally PRESIDIO_X402_MCP_REDIS_URL); otherwise each MCP server process keeps its own in-memory store.
jsonc
// Input{"resource_url":"https://api.foo.com/x","pay_to":"0xabc...","amount":"1.50","currency":"USDC","deadline_seconds":1700000000}// Output (first seen){"is_replay":false,"fingerprint":"29aaf60f..."}// Output (duplicate within TTL){"is_replay":true,"fingerprint":"29aaf60f..."}
Modes
In-process (default). Wraps the local presidio-hardened-x402 library in the same process as the MCP server. No network, no API key, no quota. PII never leaves the agent host. Use this unless you have a specific reason not to.
HTTP-proxy. When both PRESIDIO_X402_MCP_REMOTE_BASE_URL and PRESIDIO_X402_MCP_REMOTE_API_KEY are set, screen_payment_metadata calls /v1/screen on the configured host (e.g. https://screen.presidio-group.eu) for centralized audit. On auth / quota / network failure, returns a structured { "error": "auth_error" | "rate_limit" | "unavailable", "detail": ..., "mode": "remote" } — never silently falls back to in-process. Tools 2 and 3 always stay in-process.
Composability
Designed to slot into agent flows alongside payment-execution and endpoint-safety MCP servers:
code
agent intent: pay https://api.foo.com/x with 1.50 USDC
│
├─ x402station preflight(url) ← is the ENDPOINT safe? (decoys, dead, traps)
│
├─ presidio-x402 screen_payment_metadata ← is the PAYLOAD safe? (PII)
├─ presidio-x402 check_payment_policy ← within budget?
├─ presidio-x402 check_payment_replay ← not a duplicate?
│
└─ pay()
screen_payment_metadata is read-only and safe to interleave anywhere. The policy and replay gates record state on call — sequence them immediately before payment.
What none of these gates can see: a request body the agent made up. The three tools screen the 402 challenge's metadata and the spend; they never see the body the agent sends to a POST route. Independent measurement of the x402 and MPP catalogues (probe402, MCRI #001, 1 September 2026) found 1,521 of 8,056 listed POST routes — 18.9% — publish no usable request example, and 72% of those still return a payable quote at the wall. A route like that is listed, priced, and not machine-executable from the published contract. An agent that fills the gap by synthesising a body is guessing, and a guessed body is where user data enters the request unscreened. Posture: if the catalogue entry carries no request example or schema, stop at the 402 quote and surface it; do not invent a body to get past the wall. Put that rule in the agent's instructions — it is a decision the agent makes before any of these tools run.
Combined snippet: preflight → screen → pay
Endpoint-safety and payload-safety are independent signals — calling both is what you actually want before signing. Configure the two MCP servers side-by-side:
Agent flow before signing a payment (pseudocode — each step is one MCP tool call):
python
# 1. endpoint safety: is the URL trustworthy? (x402station-mcp)
pf = preflight(url)
ifnot pf["ok"]:
abort(reason=pf["warnings"]) # decoy / zombie / dead / price-trap# 2. payload safety: redact PII before it leaves the host (presidio-x402)
s = screen_payment_metadata(resource_url=url, description=description, reason="")
url, description = s["redacted_resource_url"], s["redacted_description"]
# 3. spend gates: record-on-success, call exactly once each (presidio-x402)ifnot check_payment_policy(url, amount_usd)["allowed"]:
abort(reason="policy")
if check_payment_replay(url, pay_to, amount, currency, deadline_seconds)["is_replay"]:
abort(reason="replay")
# 4. sign + pay
pay(url, amount, description=description)
The two servers are developed independently, on purpose — keeping the signals uncorrelated is the point. See x402station-mcp for the preflight tool's full output schema and warning catalog.
Notes for developers
Logs go to stderr (MCP clients capture stderr). stdout is reserved for JSON-RPC frames.
The package is a thin adapter. All security logic lives in presidio-hardened-x402 — read its docs for the entity-type catalog, policy semantics, evidence-ref verification, SLO broker, and audit-chain details.
This MCP release intentionally exposes the same three tools as 0.1.1; the compatibility update is dependency and metadata alignment with parent 0.7.x, not a promotion of the full parent SLO/evidence surface into MCP.
When testing via mcp-inspector --cli, bare numeric --tool-arg amount=1.50 is auto-coerced to a float and rejected by the schema. Real MCP clients send proper JSON types; the tool's amount argument is a string to preserve precision.
Now / in flight — OpenSSF Best Practices silver and a Scorecard above 7:
governance docs, a real CodeQL job alongside Bandit, least-privilege workflow
tokens, and Atheris fuzzing of the configuration validators. Closing the
remaining findings in SECURITY-AUDIT.md.
Next — a release carrying the raised parent floor, so the published package
no longer resolves a parent with the percent-encoding redaction bypass.
Hash-pinned CI dependencies, ideally as a family-wide change rather than in
this repo alone.
Later(under evaluation) — signed releases with build provenance; tracking
the MCP specification as it stabilises; exposing the parent library's
capability-grant@1 enforcement as a fourth tool, if agent demand justifies the
added surface.
Governance, Architecture, Security
Governance — roles, decision process, and how to become a maintainer.
Architecture — components, trust boundaries, and the core processing path.
Assurance case — the security claims and the evidence backing each one.
Security policy — supported versions and how to report a vulnerability.
Contributing — review bar, test policy, and verification commands.