Updated SEP#6
Conversation
…n model - Remove `interceptor/executeChain` JSON-RPC method and replace with client-side chain execution convenience utility provided by SDKs - Restructure Execution Model section: summary box, trust boundary pattern, type behaviors, priority resolution, sequence diagrams, then chain execution - Move Timeout and Cancellation to Interceptor Invocation section (per-invocation concern, not execution model) - Move Configuration and Context (InterceptorInvocationParams) to Interceptor Invocation section - Move Short-Circuit Semantics into Execution Model summary box - Move Sequence Diagrams above Chain Execution (illustrate the model) - Add Chain Execution interfaces: InterceptorChain, ChainEntry, ChainExecutionParams, ChainExecutionResult - MCPServerConnection left as implementation-specific type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
|
|
||
| **Created:** 2025-11-04 | ||
|
|
||
| **Authors:** @sambhav |
There was a problem hiding this comment.
@Degiorgio please add yourself as well along with @PederHP 🙏
|
I must admit I would prefer to keep the observability type. It mirrors kubernetes interceptors, and also conceptually a validator or mutator is something where the result matters. An observability interceptor is a sink. I think the semantics of a validator or mutator in audit mode is strange. Adding this makes it less intuitive and more complex than simply having three types. Validator is a blocking gate. It also makes it tricky to handle ordering of observers if they're expressed as the other types in a special mode. With these three anything except control flows (which are probably not a good idea for interceptors anyway, at this stage at least) can be expressed. |
62d3f68 to
9869442
Compare
The move from a dedicated observer type to audit mode was driven by feedback on the original SEP. The core concern raised was that observability is already converging around OpenTelemetry, and baking a parallel observability envelope into the interceptor spec risks fragmenting what is an established standard. That said, at least in my view audit mode actually preserves the semantic clarity you're describing, it just expresses it differently. A validator in audit mode is still a sink: it runs, it logs, its result doesn't gate the chain. The difference is that the logic is the same as the enforcing version, which enables a workflow that comes up a lot in practice: deploy in audit mode first (observe what would be blocked), then promote to enforce with a single field change. With a separate observer type, that promotion requires changing the interceptor even though the logic hasn't changed. It's also worth noting that two types with audit mode is strictly more expressive than three types. A dedicated observer type can only be a sink. An audit-mode mutator gives you shadow mutations, compute a transformation without applying it, useful for canary testing new mutation logic in production. With regards to ordering, audit mode doesn't change the execution model:
Happy to discuss further, I would agree that it would be good to make sure the spec is clear on the relevant semantics here! |
98555af to
18d30b0
Compare
Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
18d30b0 to
73eefde
Compare
Summary
auditmode on validators and mutatorsmodefield ("enforce" | "audit") on the Interceptor interface, replacing the dedicated observability type; audit-mode validators log violations without blocking, audit-mode mutators compute shadow mutations without applying themfailOpenfield (boolean, defaultfalse) on the Interceptor interface for fail-open/fail-closed behavior.Interceptorinterface -- replaced flateventsandphasefields with a nestedhookobject containinghook.eventsandhook.phaseInterceptorEventtoInterceptionEventand added| stringto make the union extensible for custom eventsInterceptionPhasetype alias ("request" | "response" | "both") as a standalone typeBaseInterceptorResult/ObservabilityResult/ unified result envelope -- the original had a shared base type and three result subtypes; the updated SEP definesValidationResultandMutationResultinline within their respective Validator/Mutator sectionsinterceptor/executeChainas a JSON-RPC protocol method -- chain execution is now a client-side SDK convenience utility, not a protocol-level method"*","*/request","*/response", interaction withhook.phase, and extensibility guidance for namespace wildcardstimeoutand cancellation semantics for individual interceptor invocations (timeoutMsfield onInterceptorInvocationParams)failOpen: falsedefault guidanceinterceptors/listresponse fromtype: "observability"totype: "validation"withmode: "audit"andfailOpen: trueChanges
1. Type System: Two Types Instead of Three
The original SEP defined three interceptor types:
validation,mutation, andobservability. The updated SEP collapses this to two types:validationandmutation.The
observabilitytype is replaced by a cross-cuttingmodefield:mode: "enforce"(default) -- normal blocking/transforming behaviormode: "audit"-- non-blocking operation; validators log without blocking, mutators compute without applyingA new
failOpenboolean (defaultfalse) controls failure routing: whether a crashed/timed-out interceptor blocks or allows the message to proceed.2. Interceptor Interface Restructuring
Original: Flat structure with
events: InterceptorEvent[]andphase: "request" | "response" | "both"at the top level.Updated: Nested
hookobject:The type name changed from
InterceptorEventtoInterceptionEventand gained a| stringextension point. A newInterceptionPhasetype alias was added.3. Result Types Simplified
Original: A
BaseInterceptorResultbase interface with three subtypes (ValidationResult,MutationResult,ObservabilityResult) and a union typeInterceptorResult. These were defined in a "Unified Result Envelope" section.Updated:
ValidationResultandMutationResultare defined inline within their respective Validator and Mutator subsections.ObservabilityResultandBaseInterceptorResultare removed entirely.4. Chain Execution: Protocol Method to SDK Utility
Original:
interceptor/executeChainwas a JSON-RPC method with full request/response schemas, making it part of the MCP protocol.Updated: Chain execution is described as a "convenience utility provided by SDKs." It uses client-side
InterceptorChain,ChainEntry,ChainExecutionParams, andChainExecutionResultinterfaces. The orchestration pattern is documented as a 5-step process (Discover, Merge & Sort, Order by Trust Boundary, Execute, Aggregate) that callsinterceptor/invokeon individual servers. TheChainEntrytype includes anMCPServerConnectionreference (implementation-specific) for routing invocations to the correct server.5. New Formal Definitions and Callouts
The updated SEP adds:
6. Wildcard and Extensibility Documentation
The updated SEP adds detailed documentation on wildcard behavior (
"*","*/request","*/response"), their interaction withhook.phase, guidance on namespace wildcards (e.g.,"tools/*"), and how implementations MAY extend the event set with custom events.7. Payload Formats Section Removed
The original Section 4 ("Payload Formats") containing detailed request/response schemas for all interceptable events across Server Features, Client Features, and LLM Interactions was removed.
8. Execution Model Restructuring
The updated Execution Model section adds:
9. Sequence Diagrams Simplified
All three sequence diagrams (Client-Side, Server-Side, Cross-Boundary) updated to remove the separate Observability participant, reflecting the two-type model.
10. Backward Compatibility and Security Hardened
Both sections updated to use RFC 2119 normative language. Security Best Practices now explicitly state that interceptors "MUST default to
failOpen: false."