C# SDK: align mode value and priorityHint with the SEP#17
Conversation
The SEP defines mode as "enforce" | "audit"; the C# SDK used "active" on the wire, making it incompatible with the TypeScript SDK. Renames the enum member and wire value, updates the attribute default and the default-skipping logic, and adds a deserialization test. Part of #15. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The SEP allows priorityHint to be either a single number or
{ request?, response? } with different priorities per phase; the C# SDK
only supported a plain int. Adds a PriorityHint type with a converter
that round-trips both wire forms, resolves effective priority per phase
in chain ordering, and exposes RequestPriorityHint/ResponsePriorityHint
on the interceptor attribute.
Attribute-discovered interceptors with no priority set now omit
priorityHint from the wire instead of emitting 0 (semantically identical
per the SEP default, and consistent with Mode/FailOpen default-skipping).
Part of #15.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Aligns the C# interceptors SDK with SEP-1763 by updating the mode wire value to match the spec and extending priorityHint to support both scalar and per-phase object forms, including phase-specific mutation ordering in the chain orchestrator.
Changes:
- Renames
InterceptorMode.Active→InterceptorMode.Enforceand updates default/serialization behavior accordingly. - Introduces
PriorityHintprotocol type + JSON converter to round-tripnumber | { request?, response? }faithfully. - Updates chain orchestration to sort mutations by phase-effective priority and adds/updates tests for new semantics and attribute behavior.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| csharp/sdk/src/ModelContextProtocol.Interceptors/Protocol/InterceptorMode.cs | Changes enum member/wire value from active to enforce. |
| csharp/sdk/src/ModelContextProtocol.Interceptors/Protocol/PriorityHint.cs | Adds new protocol type + converter supporting scalar/object priority hints. |
| csharp/sdk/src/ModelContextProtocol.Interceptors/Protocol/Interceptor.cs | Changes PriorityHint property type to PriorityHint? and updates docs. |
| csharp/sdk/src/ModelContextProtocol.Interceptors/InterceptorJsonContext.cs | Registers PriorityHint for source-generated JSON support. |
| csharp/sdk/src/ModelContextProtocol.Interceptors/Server/McpServerInterceptorAttribute.cs | Adds optional per-phase priority hint attribute properties with backing fields. |
| csharp/sdk/src/ModelContextProtocol.Interceptors/Server/ReflectionMcpServerInterceptor.cs | Omits default Enforce mode on the wire and resolves scalar vs per-phase priority hints (with conflict error). |
| csharp/sdk/src/ModelContextProtocol.Interceptors/Client/InterceptorChainOrchestrator.cs | Sorts mutations by phase-effective priority hint. |
| csharp/sdk/tests/ModelContextProtocol.Interceptors.Tests/ProtocolTypesSerializationTests.cs | Adds serialization/round-trip coverage for PriorityHint and updated InterceptorMode. |
| csharp/sdk/tests/ModelContextProtocol.Interceptors.Tests/ReflectionMcpServerInterceptorTests.cs | Adds tests for per-phase attribute hints, omission when unset, and conflict detection. |
| csharp/sdk/tests/ModelContextProtocol.Interceptors.Tests/InterceptorChainOrchestratorTests.cs | Adds tests for phase-dependent ordering, default-zero behavior, and tie-breaking. |
| csharp/sdk/README.md | Documents per-phase priority hint usage for mutation ordering. |
| csharp/sdk/CLAUDE.md | Updates test count and documents expanded PriorityHint semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ExecuteChainRequestParams.Phase could be set to InterceptorPhase.Both, which is documented as attribute-only and invalid on the wire. The orchestrator would silently match no hooks while ordering and branching as if it were the response phase. Throw ArgumentException up front instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Good catch from Copilot — (Authored by Claude Fable 5) |
sorry let me dismiss for now, current revised sep has "active" and "audit", not "enforce"
The earlier rename (0cc036b) changed mode from "active" to "enforce" against a draft SEP. The revised SEP-1763 (PR #2624, now the current revision) defines mode as "active" | "audit" with default "active" — so "active" was correct all along. jeongukjae flagged this on PR #17, dismissing the approval: 'current revised sep has "active" and "audit", not "enforce"'. Reverts InterceptorMode.Enforce -> Active and wire value "enforce" -> "active", the attribute default, the default-skipping logic, and the serialization tests. The priorityHint object-form work in this PR stays — the revised SEP still defines priorityHint as number | {request, response}. Part of #15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses the first two items of #15 (the chain-orchestrator multi-server item follows in a separate PR).
mode: keep"active", add"audit"round-trip coverageInterceptorModekeeps membersActive(wire"active", default) andAudit(wire"audit"). Added a deserialization test alongside the existing serialization test so both wire forms are covered.priorityHint: supportnumber | { request?, response? }The SDK only supported a plain
int. This adds aPriorityHintprotocol type whose converter accepts both wire forms and preserves them on round-trip (a number stays a number, an object stays an object). Chain ordering now resolves the effective priority per phase exactly as the SEP'sresolvePriorityalgorithm (unset → 0, alphabetical tie-break unchanged).Interceptor.PriorityHintis nowPriorityHint?; an implicit conversion fromintkeeps existing code compiling.[McpServerInterceptor]gainsRequestPriorityHint/ResponsePriorityHint(mutually exclusive with the scalarPriorityHint), following the official SDK's backing-field pattern for optional attribute values.priorityHintfrom the wire instead of emitting0— semantically identical per the SEP default, and consistent with the existing default-skipping forMode/FailOpen.Testing
dotnet testfromcsharp/sdk/: all passing, including new coverage for bothpriorityHintwire forms, partial objects, unknown-key tolerance, phase-dependent mutation ordering (the SEP's pii-redactor/compressor example), the attribute conflict error, and bothmodewire values.Part of #15.
🤖 Generated with Claude Code