</svg>
Warning</span>Once data hits a third-party LLM, you cannot un-send it. Provider data retention policies, log analysis pipelines, and abuse-monitoring queues all become sub-processors of your customers' regulated data. Redaction has to happen before the tool call returns to the model.
</div>
Most engineering teams underestimate the surface area of sensitive data. A typical GET /contacts response from HubSpot or Salesforce isn't just a name and email. It often contains a sprawling JSON tree of liabilities:
Direct identifiers : email, phone, full name, SSN, tax ID, employee ID.
Quasi-identifiers : date of birth, zip code, IP address, device ID (re-identifiable when combined).
Financial : bank routing, card last-four, salary, compensation history (Workday, BambooHR).
Health : anything in a Zendesk or Intercom ticket from a healthcare customer (instant PHI).
Secrets : webhook URLs, API tokens, OAuth refresh tokens stored in custom fields.
Free-text fields : notes, descriptions, comments—the worst offender, because regex misses unstructured PII.
A helpdesk integration is the canonical worst case. A user types their credit card into a support ticket. Your AI agent calls list_zendesk_tickets, the LLM ingests the body, and now Anthropic or OpenAI has logged a PCI violation in their abuse pipeline. If your architecture allows an LLM to request a resource and directly receive the raw SaaS API response, you are flying blind. You need an interception layer.
To understand where to place your redaction logic, you need to understand the MCP JSON-RPC lifecycle. When an MCP client (like Claude Desktop) connects to an MCP server, all communication happens over HTTP POST using JSON-RPC 2.0 messages.
The pattern is simple in concept: insert a redaction step between the upstream SaaS response and the JSON-RPC tools/call reply that the MCP client receives. When the LLM decides to use a tool, it sends a tools/call request. The arguments arrive as a single flat object. The MCP server executes the API request against the third-party SaaS platform, receives the response, and wraps it in an MCP-compliant result object.
PII redaction must happen exactly between the moment the SaaS API returns the data and the moment the MCP server constructs the JSON-RPC result.
Here is the architectural flow for a secure MCP proxy layer:
sequenceDiagram
participant LLM as AI Agent (MCP Client)
participant Gateway as MCP Proxy Gateway
participant Redact as Redaction Layer
participant SaaS as Upstream SaaS API
LLM->>Gateway: JSON-RPC tools/call<br>{"name": "get_employee", "arguments": {"id": "123"} }
Gateway->>SaaS: GET /api/v1/employees/123<br>Authorization: Bearer token
SaaS-->>Gateway: HTTP 200 OK (Raw JSON with PII)
Gateway->>Redact: Scan + transform payload
Redact-->>Gateway: Sanitized payload
Gateway-->>LLM: JSON-RPC Response (PII-free)
If you inspect the raw payload from the upstream SaaS API, it might look like this:
{
"id" : "emp_89324" ,
"first_name" : "Jane" ,
"last_name" : "Doe" ,
"email" : "jane.doe@enterprise.com" ,
"social_security_number" : "999-99-9999" ,
"base_salary" : 125000 ,
"department" : "Engineering"
}
Your proxy layer must intercept this payload, apply a masking policy, and return the sanitized version to the LLM inside the standard MCP content array:
{
"jsonrpc" : "2.0" ,
"id" : 42 ,
"result" : {
"content" : [{
"type" : "text" ,
"text" : "{ \" id \" : \" emp_89324 \" , \" first_name \" : \" Jane \" , \" department \" : \" Engineering \" , \" email \" : \" <EMAIL_1> \" , \" social_security_number \" : \" [REDACTED] \" }"
}]
}
}
This interception guarantees that the LLM only ever sees the data it strictly needs to perform its reasoning. A robust redaction layer must maintain three non-negotiable properties:
Pre-model inspection. Gateways analyze content before it reaches the model, not after. Once data hits an LLM, it's already exposed.
Deterministic transformation. Redaction must produce the same output for the same input across requests, otherwise pagination cursors and follow-up tool calls get confused.
Reversibility for write-back. If the agent later calls update_contact, your gateway needs a way to swap masked tokens back to real values, or the agent will overwrite a real email with <EMAIL_1>.
The redaction layer typically combines three detection strategies:
Strategy
Catches
Misses
Regex / Luhn / IBAN validators
SSNs, credit cards, IBANs, structured IDs
Names, addresses, contextual PII
Named-entity recognition (NER)
Person names, locations, organizations in free text
Domain-specific identifiers (employee IDs, custom field PHI)
Schema-driven field rules
Known sensitive fields by JSON path
New fields added by the SaaS vendor
Production systems run all three. Microsoft Presidio combined with spaCy and a YAML rule file is the open-source baseline. OpenAI's Privacy Filter is a small model with frontier personal data detection capability, designed for high-throughput privacy workflows, able to perform context-aware detection of PII in unstructured text and is a viable drop-in for the NER step.
Once you have the interception layer in place, you must choose how to alter the data. This is where most implementations fail. Replacing every sensitive field with [REDACTED] is the lazy answer, and it actively kills agent reasoning.
Static redaction involves identifying sensitive fields by key name or regex pattern and replacing their values with a static string like [REDACTED], null, or ***. This approach is fast, deterministic, and easy to audit.
However, naive masking breaks LLM context. As noted by AI security firm Protecto AI, removing data entirely degrades AI accuracy. Consider this Salesforce contact list:
[
{ "id" : "003" , "email" : "jane@acme.com" , "company" : "Acme" },
{ "id" : "004" , "email" : "jane@acme.com" , "company" : "Acme" },
{ "id" : "005" , "email" : "bob@globex.com" , "company" : "Globex" }
]
If you use static redaction, every email turns into [REDACTED]. The agent can no longer answer "which contacts are duplicates?" because the values are identical strings. Worse, when the user says "send a follow-up to Jane," the agent has nothing to reference. If an LLM is trying to correlate support tickets submitted by the same user, but every email address has been replaced with the exact same static string, the model loses the ability to group those tickets.
To solve the context degradation problem, enterprise architectures use context-aware tokenization or synthetic data replacement. Enterprise gateways replace actual values with semantically meaningful, format-preserving tokens.
Instead of wiping out the data, the tokenization engine replaces it with a synthetic but consistent value:
[
{ "id" : "003" , "email" : "<EMAIL_1>" , "company" : "<COMPANY_1>" },
{ "id" : "004" , "email" : "<EMAIL_1>" , "company" : "<COMPANY_1>" },
{ "id" : "005" , "email" : "<EMAIL_2>" , "company" : "<COMPANY_2>" }
]
If the LLM sees <EMAIL_1> across five different Jira tickets, it can correctly reason that the same user submitted all five tickets. It can generate a summary report based on that correlation.
When the LLM outputs its final response or attempts to execute a write operation (like update_jira_ticket), the proxy layer intercepts the outbound request, detokenizes <EMAIL_1> back to jane@acme.com, and forwards the request to the SaaS API. This is the same pattern LiteLLM uses with Presidio: for 'replace' operations, the gateway can check the LLM response and replace the masked token with the user-submitted values .
To implement this safely, you must keep a short-lived, in-memory token vault keyed to the conversation or session. Never persist these mappings to disk. If you write the token map to a database, you have just rebuilt the exact data retention problem you were trying to solve.
Security policies fail when they are decentralized. The biggest mistake teams make is putting redaction logic inside the AI agent's internal prompt logic or a client-side library. Every new agent re-implements the rules, drifts, and eventually leaks, a problem that compounds quickly in multi-agent systems . If an engineer updates the agent's system prompt and accidentally removes the instruction to ignore SSNs, the data leaks immediately. Without a centralized control layer, every application must implement its own filtering logic for data privacy. That approach leads to inconsistent security and compliance gaps.
PII redaction must happen at a centralized gateway or proxy layer. The MCP server already holds the privileged credentials, possesses the schema knowledge, and sits at the perfect network position. It is the natural enforcement point. A centralized gateway provides several architectural advantages:
For structured fields, declarative transforms beat imperative code. A response transformation expressed as JSONata is auditable, reviewable in a pull request, and trivially diffable for compliance teams. Instead of writing custom Python or Node.js code for every single integration, you define a JSONata expression that maps the raw payload to a sanitized schema.
Here is an example JSONata expression that strips and tokenizes sensitive HR data from a raw Workday API response:
(
$maskLastName := function($str) { $substring($str, 0, 1) & "***" };
$map($$ , function($v) {
{
"id": $v.id,
"first_name": $v.first_name,
"last_name": $maskLastName($v.last_name),
"email": "<EMAIL_" & $hash($v.email) & ">",
"social_security_number": null,
"compensation": $exists($v.base_salary) ? "<REDACTED>" : null,
"manager_id": $v.manager_id,
"department": $v.department
}
})
)
This pattern—declarative response mapping with a transformation language—is exactly how Truto already handles unified API normalization. The same hooks that map first_name to a unified firstName field can drop, hash, or tokenize the value. See our JSONata mapping guide for the broader pattern.
Structured field rules don't help when the SaaS payload contains a raw Zendesk ticket body or a Salesforce note. Run free-text fields through a detector before serializing:
import { AnalyzerEngine , AnonymizerEngine } from "presidio-client" ;
async function sanitizeFreeText ( payload : any , fields : string []) {
for ( const path of fields ) {
const text = get ( payload , path );
if ( ! text ) continue ;
const findings = await analyzer . analyze ({
text ,
language : "en" ,
entities : [ "PERSON" , "EMAIL_ADDRESS" , "PHONE_NUMBER" ,
"US_SSN" , "CREDIT_CARD" , "IBAN_CODE" ]
});
const anonymized = await anonymizer . anonymize ({ text , analyzer_results : findings });
set ( payload , path , anonymized . text );
}
return payload ;
}
Run the detector with a confidence threshold appropriate to the field. Ticket bodies in healthcare-adjacent products should err toward over-redaction; product feedback fields can be more permissive.
The other half of the gateway story is which tools you expose at all . Instead of exposing every endpoint a SaaS API offers, a gateway can dynamically generate MCP tools based strictly on approved documentation records. If your agent only needs ticket subjects and statuses, do not ship an attachments.download tool. Documentation-driven tool generation forces a deliberate review for every endpoint that touches an LLM. We covered this pattern deeply in Auto-Generated MCP Tools .
Furthermore, when an MCP client calls a tool, all arguments arrive in a single flat JSON object. A centralized gateway uses predefined JSON Schemas to split these arguments into query parameters and body parameters before forwarding them to the proxy API handlers. This prevents prompt injection attacks from smuggling malicious payloads into unexpected HTTP headers or query strings.
AI agents are notoriously aggressive when scraping data. A centralized gateway protects your infrastructure by enforcing rate limits. It is a critical architectural requirement that your gateway does not absorb or silently retry upstream rate limit errors. Truto, for example, explicitly passes upstream HTTP 429 errors directly to the caller. Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF specification. The AI agent's orchestration layer remains in full control of retry logic and exponential backoff, ensuring predictable system behavior.
Redacting PII in transit is only half the battle. Redaction prevents PII from reaching the LLM . It does not prevent PII from being stored by the MCP infrastructure itself .
If the infrastructure routing your MCP calls stores a copy of the unredacted third-party data on its own disks, you have created a massive compliance liability. If your AI agent connects to Salesforce or BambooHR through a managed MCP server platform, the data flowing through that server is governed by that platform's data retention policy. If the platform caches API responses in a database to speed up subsequent queries, they become a sub-processor of your customers' highly regulated enterprise data.
Your SOC 2 scope immediately expands. Your GDPR obligations multiply. Enterprise InfoSec teams will flag your application during procurement when they see a third-party caching their HR records.
As detailed in our breakdown of MCP Server Data Retention Policies , the major LLM providers explicitly wash their hands of what happens during a tool call. OpenAI's documentation states that data sent to remote MCP servers is subject entirely to the third-party's retention policies.
The only defensible architecture for handling sensitive SaaS data is a pass-through proxy with strictly zero data retention. In a zero data retention architecture, the platform acts entirely as a conduit. It receives the request from the LLM, resolves the OAuth tokens from a secure key-value store, proxies the request to the upstream SaaS API, applies the JSONata redaction transformations in memory, and returns the response to the LLM. The underlying SaaS data is never written to a database table, never stored in a durable state mechanism, and never logged in plain text.
</svg>
Tip</span>Ask any MCP platform vendor exactly three questions: (1) Do you store the response body of tool calls? (2) For how long, and where? (3) Is that storage in scope of your SOC 2 report? If they hesitate, walk away.
</div>
For a deeper dive into this compliance posture, review our guide on Building SOC 2 & GDPR Compliant AI Agents .
This architectural rigor is not free. Senior engineers should plan for these realities when implementing gateway-side redaction:
Latency. NER on a 50KB ticket body adds 50-200ms per call. Caching detectors in-process and running regex first helps, but agent loops will feel slower.
False positives. A product name that looks like a person's name will get tokenized. Build an allowlist for known-safe terms per integration.
False negatives. No detector catches everything. Layer schema rules, regex, and NER, and accept that adversarial inputs (creative formatting of SSNs) will sometimes slip through. Assume a 5-10% false-negative rate on free text and design downstream controls to compensate.
Reversibility complexity. Token-to-value swap on write paths is the single most common source of bugs. Test it explicitly with multi-turn agent traces.
Schema drift. When Salesforce adds a new custom field your customer uses for SSNs, your schema-rule list will not know about it. Pair redaction with field-discovery and schema-drift monitoring .
Building a centralized, zero-data-retention MCP gateway that handles OAuth token lifecycles, JSONata transformations, NER scanning pipelines, and dynamic tool generation is a massive engineering undertaking. This is exactly the infrastructure Truto provides out of the box.
Truto is a unified API and MCP server platform built around design choices that line up directly with strict InfoSec compliance requirements:
Pass-Through by Default (Zero Data Retention): Truto's proxy API never stores the third-party SaaS data flowing through its MCP servers. The payload is fetched, processed in memory, returned to the caller, and discarded. Your customers' data is not warehoused on our side, eliminating sub-processor compliance risks entirely.
Declarative Transforms via JSONata: Truto's built-in JSONata transformation layer allows your engineering team to declaratively strip or tokenize sensitive fields from API responses before they ever reach the LLM. Redaction is configuration, not a fork of our code.
Documentation-Driven Tool Exposure: Truto derives MCP tool definitions dynamically from integration resources and documentation records. An integration's resource only becomes an MCP tool if you explicitly document it, ensuring AI agents cannot access unauthorized endpoints.
Transparent Rate Limiting: Truto passes upstream HTTP 429 rate limit errors directly to your agent with standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset), ensuring your orchestration layer maintains precise control over execution flow and retry backoff.
What Truto does not do: it is not a full DLP product. If you need adaptive NER on free text with custom entity training, pair Truto's transform layer with Presidio, OpenAI's Privacy Filter, or a commercial DLP gateway in front of the MCP endpoint. The pass-through architecture supports that composition cleanly.
Exposing enterprise SaaS data to LLMs requires extreme architectural discipline. You cannot rely on prompt engineering to protect PII, and you cannot route sensitive payloads through platforms that cache your customers' data. If you are bringing AI agents anywhere near customer SaaS data, run this sequence:
Inventory the tool surface. List every MCP tool your agent can call and every field each one returns. This alone catches half the leaks.
Classify fields by sensitivity. Tag fields as PII, PHI, PCI, quasi-identifier, or safe. Get legal and security to sign off on the matrix.
Pick a redaction strategy per class. Decide whether to drop, hash, tokenize, or pass through. Document the rule for each field.
Centralize the enforcement at the MCP layer. Not in the agent. Not in the prompt. At the gateway.
Verify zero data retention upstream. Read the SOC 2 report of your MCP infrastructure. If raw payloads land on disk anywhere, your redaction is theater.
Test reversibility on write paths. Send a multi-turn agent trace that reads, then writes, then reads again. Ensure tokens round-trip correctly.
PII redaction is not a feature you bolt on the week before an InfoSec review. It is an architectural choice that determines whether your agent product can be sold to a regulated customer at all.
Evaluating MCP server platforms for PII-sensitive workloads? Stop failing InfoSec reviews over third-party data access. Talk to our engineering team about deploying zero-data-retention MCP servers with declarative JSONata transformations for your AI agents today.
Talk to us