using System.Text.Json.Nodes; using ModelContextProtocol.Interceptors.Protocol; using ModelContextProtocol.Interceptors.Server; /// /// Sample interceptors demonstrating validation, mutation, and sink types. /// [McpServerInterceptorType] public class SampleInterceptors { /// /// Validates that tool call arguments don't contain PII patterns. /// [McpServerInterceptor( Name = "pii-validator", Description = "Checks tool call arguments for PII patterns", Type = InterceptorType.Validation, Events = [InterceptionEvents.ToolsCall], Phase = InterceptorPhase.Request)] public static ValidationInterceptorResult ValidatePii(JsonNode payload) { var json = payload.ToJsonString(); // Simple pattern check for demonstration if (json.Contains("ssn", StringComparison.OrdinalIgnoreCase) || json.Contains("social security", StringComparison.OrdinalIgnoreCase)) { return ValidationInterceptorResult.Failure( new ValidationMessage { Path = "$.arguments", Message = "Payload may contain Social Security Number data", Severity = ValidationSeverity.Error, }); } return ValidationInterceptorResult.Success(); } /// /// Redacts email addresses from tool call payloads. /// [McpServerInterceptor( Name = "email-redactor", Description = "Redacts email addresses from payloads", Type = InterceptorType.Mutation, Events = [InterceptionEvents.ToolsCall], Phase = InterceptorPhase.Request, PriorityHint = -1000)] public static MutationInterceptorResult RedactEmails(JsonNode payload) { var json = payload.ToJsonString(); var redacted = System.Text.RegularExpressions.Regex.Replace( json, @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", "[EMAIL_REDACTED]"); if (redacted != json) { return new MutationInterceptorResult { Modified = true, Payload = JsonNode.Parse(redacted), }; } return new MutationInterceptorResult { Modified = false, Payload = payload }; } /// /// Logs all intercepted events. /// [McpServerInterceptor( Name = "request-logger", Description = "Logs all requests", Type = InterceptorType.Sink, Events = [InterceptionEvents.All])] public static SinkInterceptorResult LogRequest( JsonNode payload, string @event, InterceptorPhase phase, InvokeInterceptorContext? context) { Console.Error.WriteLine($"[interceptor] event={@event} phase={phase} traceId={context?.TraceId ?? "none"} payloadSize={payload.ToJsonString().Length}"); return new SinkInterceptorResult { Recorded = true, Metrics = new Dictionary { ["payloadBytes"] = payload.ToJsonString().Length, }, }; } }