MCP Output Sanitization Guide
Mask PII, escape unsafe HTML, and cap oversized payloads before an MCP tool response reaches an AI client.
Quick Answer / TL;DR
Never return a tool's raw output to the client. Mask likely PII patterns (emails, phone numbers, card numbers), escape any HTML before it can be rendered, and truncate oversized arrays so a single tool response cannot leak sensitive data or blow out the model's context window.
Key Takeaways
- Sanitize on the server, always; never rely on the client to do it.
- Mask PII with pattern matching as a baseline, not a complete solution — pair it with schema-level data minimization.
- Truncate large arrays with an explicit _truncated flag so the model knows the data was cut, rather than silently dropping items.
Masking likely PII patterns
Regex-based masking is a baseline safety net, not a substitute for only selecting the fields a tool actually needs. Apply it recursively across strings, arrays, and nested objects before the response leaves the server.
function sanitizeOutput(data: unknown): unknown {
if (typeof data === "string") {
return data
.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "[EMAIL_REDACTED]")
.replace(/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g, "[CARD_REDACTED]");
}
if (Array.isArray(data)) return data.map(sanitizeOutput);
if (typeof data === "object" && data !== null) {
return Object.fromEntries(Object.entries(data).map(([k, v]) => [k, sanitizeOutput(v)]));
}
return data;
}Capping payload size
A tool that can return an unbounded array should truncate it and say so explicitly, rather than either failing or silently flooding the model's context window.
if (Array.isArray(data) && data.length > 100) {
return { _truncated: true, _original_length: data.length, _sample: data.slice(0, 100) };
}MCP Output Sanitization Guide FAQs
Direct answers for developers, operators, and Indian teams evaluating MCP.