In implementing the TypeScript SDK and using the C# SDK as a model, I found a few potential issues with the C# SDK.
mode value
SEP specifies:
/**
* Execution mode (default: "enforce")
* - "enforce": Normal blocking / transforming behavior
* - "audit": Non-blocking operation
* - For validators: logs violations without blocking execution
* - For mutators: computes transformations without applying them (shadow mutations)
*/
mode?: "enforce" | "audit";
Whereas the C# SDK uses:
[JsonConverter(typeof(JsonStringEnumConverter<InterceptorMode>))]
public enum InterceptorMode
{
/// <summary>
/// Normal blocking / transforming behavior. Validators block on error severity;
/// mutators apply their payload changes.
/// </summary>
[JsonStringEnumMemberName("active")]
Active,
/// <summary>
/// Non-blocking operation. Validators log violations without blocking execution;
/// mutators compute transformations without applying them (shadow mutations).
/// </summary>
[JsonStringEnumMemberName("audit")]
Audit,
}
Our application already had an active/inactive setting which is a client setting indicating that the interceptor should not be run (or advertised) at all. I strongly prefer the enforce language from the SEP as it more accurately describes the difference from the audit mode (I would argue that an audit mode interceptor is still "active").
The TypeScript SDK uses enforce (per the SEP) and is therefore currently incompatible with the C# SDK.
priorityHint not fully supported
The C# SDK does not support the object form of priorityHint per the spec:
/**
* Priority hint for mutation interceptor ordering (lower executes first).
*
* Can be specified as:
* - A single number: applies to both request and response phases
* - An object: specify different priorities per phase
*
* Range: 32-bit signed integer (-2,147,483,648 to 2,147,483,647)
* Default: 0 if omitted
*
* Tie-breaker: Interceptors with equal priorityHint are ordered alphabetically by name.
* For validation interceptors, this field is ignored.
*
* Examples:
* priorityHint: -1000 // Same priority for both phases
* priorityHint: { request: -1000 } // Request: -1000, Response: 0 (default)
* priorityHint: { response: 1000 } // Request: 0 (default), Response: 1000
* priorityHint: { request: -1000, response: 1000 } // Different per phase
*/
priorityHint?: number | {
request?: number;
response?: number;
};
This makes it incompatible with interceptors that use that form (interceptors using the TypeScript SDK can use this form).
Chain orchestrator only supports one MCP server
The SEP is clear that the orchestration pattern should support combining interceptors from multiple MCP servers:
#### Chain Execution
Chain execution is a **convenience utility**, provided by SDKs to enforce the execution model defined above. Its purpose is to execute interceptors — potentially hosted across N MCP servers — in a way that enforces the trust-boundary-aware ordering, type-specific execution semantics, and failure behaviors.
> Important: The execution model defined above MUST be followed by all implementations, whether invoking interceptors individually via `interceptor/invoke` or using this convenience utility.
The orchestration pattern is as follows:
1. **Discover:** Call `interceptors/list` on one or more MCP servers to collect all registered interceptors.
2. **Merge & Sort:** Combine all discovered interceptors into a single chain, sorted by `priorityHint` (ascending, with alphabetical tie-breaking by interceptor name).
3. **Order by Trust Boundary:** Apply the trust-boundary-aware execution model — mutations before validations when sending, validations before mutations when receiving.
4. **Execute:** Call `interceptor/invoke` on the appropriate MCP server for each interceptor. Mutations MUST be invoked sequentially (each receiving the output of the previous). Validations MAY be invoked in parallel.
5. **Aggregate:** Collect all results, assembling the final payload and validation summary.
SDK libraries are expected to provide reference implementations of this orchestration logic so that individual applications do not need to implement it from scratch.
The C# SDK only supports a single host at present.
In implementing the TypeScript SDK and using the C# SDK as a model, I found a few potential issues with the C# SDK.
mode value
SEP specifies:
Whereas the C# SDK uses:
Our application already had an active/inactive setting which is a client setting indicating that the interceptor should not be run (or advertised) at all. I strongly prefer the
enforcelanguage from the SEP as it more accurately describes the difference from theauditmode (I would argue that anauditmode interceptor is still "active").The TypeScript SDK uses
enforce(per the SEP) and is therefore currently incompatible with the C# SDK.priorityHint not fully supported
The C# SDK does not support the object form of priorityHint per the spec:
This makes it incompatible with interceptors that use that form (interceptors using the TypeScript SDK can use this form).
Chain orchestrator only supports one MCP server
The SEP is clear that the orchestration pattern should support combining interceptors from multiple MCP servers:
The C# SDK only supports a single host at present.