Skip to main content
Glama

Sentry MCP

Official
by getsentry
sentry.ts3.29 kB
interface ScrubPattern { pattern: RegExp; replacement: string; description: string; } // Patterns for sensitive data that should be scrubbed // Pre-compile patterns with global flag for replacement const SCRUB_PATTERNS: ScrubPattern[] = [ { pattern: /\bsk-[a-zA-Z0-9]{48}\b/g, replacement: "[REDACTED_OPENAI_KEY]", description: "OpenAI API key", }, { pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+={0,}/g, replacement: "Bearer [REDACTED_TOKEN]", description: "Bearer token", }, { pattern: /\bsntrys_[a-zA-Z0-9_]+\b/g, replacement: "[REDACTED_SENTRY_TOKEN]", description: "Sentry access token", }, ]; // Maximum depth for recursive scrubbing to prevent stack overflow const MAX_SCRUB_DEPTH = 20; /** * Recursively scrub sensitive data from any value. * Returns tuple of [scrubbedValue, didScrub, descriptionsOfMatchedPatterns] */ function scrubValue(value: unknown, depth = 0): [unknown, boolean, string[]] { // Prevent stack overflow by limiting recursion depth if (depth >= MAX_SCRUB_DEPTH) { return ["[MAX_DEPTH_EXCEEDED]", false, []]; } if (typeof value === "string") { let scrubbed = value; let didScrub = false; const matchedDescriptions: string[] = []; for (const { pattern, replacement, description } of SCRUB_PATTERNS) { // Reset lastIndex to avoid stateful regex issues pattern.lastIndex = 0; if (pattern.test(scrubbed)) { didScrub = true; matchedDescriptions.push(description); // Reset again before replace pattern.lastIndex = 0; scrubbed = scrubbed.replace(pattern, replacement); } } return [scrubbed, didScrub, matchedDescriptions]; } if (Array.isArray(value)) { let arrayDidScrub = false; const arrayDescriptions: string[] = []; const scrubbedArray = value.map((item) => { const [scrubbed, didScrub, descriptions] = scrubValue(item, depth + 1); if (didScrub) { arrayDidScrub = true; arrayDescriptions.push(...descriptions); } return scrubbed; }); return [scrubbedArray, arrayDidScrub, arrayDescriptions]; } if (value && typeof value === "object") { let objectDidScrub = false; const objectDescriptions: string[] = []; const scrubbed: Record<string, unknown> = {}; for (const [key, val] of Object.entries(value)) { const [scrubbedVal, didScrub, descriptions] = scrubValue(val, depth + 1); if (didScrub) { objectDidScrub = true; objectDescriptions.push(...descriptions); } scrubbed[key] = scrubbedVal; } return [scrubbed, objectDidScrub, objectDescriptions]; } return [value, false, []]; } /** * Sentry beforeSend hook that scrubs sensitive data from events */ export function sentryBeforeSend(event: any, hint: any): any { // Always scrub the entire event const [scrubbedEvent, didScrub, descriptions] = scrubValue(event); // Log to console if we found and scrubbed sensitive data // (avoiding LogTape dependency for edge/browser compatibility) if (didScrub) { const uniqueDescriptions = [...new Set(descriptions)]; console.warn( `[Sentry] Event contained sensitive data: ${uniqueDescriptions.join(", ")}`, ); } return scrubbedEvent as any; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server