C# Re-implementation (#5)
Re-implementation of C# interceptors SDK with clearer focus on server-side / gateway interceptors. Fixes a lot of issues with the existing implementation. Still more boilerplate than I'm happy with, but this is better than what was there. Will refine further in later PRs.
This commit is contained in:
parent
5bd7ab4d2a
commit
d01a626b76
1 changed files with 7887 additions and 12886 deletions
167
csharp/sdk/docs/ARCHITECTURE_PHASES.md
Normal file
167
csharp/sdk/docs/ARCHITECTURE_PHASES.md
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# Architecture Phases
|
||||
|
||||
This document captures the phased structural changes planned for the C# MCP interceptors SDK so we can reference them during implementation.
|
||||
|
||||
## Product Rule
|
||||
|
||||
The package should expose two distinct surfaces:
|
||||
|
||||
1. `WithInterceptors(...)` / interceptor server: pure SEP surface
|
||||
2. `McpInterceptorGateway`: transparent proxy by default
|
||||
3. Gateway SEP passthrough: opt-in advanced mode
|
||||
4. Shared chain execution/runtime: reused by both surfaces
|
||||
|
||||
This lets the package support both:
|
||||
|
||||
1. SEP-aware clients that explicitly use `interceptors/list` and `interceptor/invoke` (chain execution is SDK-side orchestration over those two)
|
||||
2. Transparent infrastructure deployments where clients do not need any code changes
|
||||
|
||||
## Phase 1: Split Gateway Modes
|
||||
|
||||
Goal: make the gateway's public behavior explicit.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Add `ExposeInterceptorProtocol` to `McpInterceptorGatewayOptions`, defaulting to `false`
|
||||
2. In transparent mode, do not advertise interceptor extension capability
|
||||
3. In transparent mode, do not expose `interceptors/list` or `interceptor/invoke`
|
||||
4. In opt-in SEP mode, preserve the current passthrough behavior
|
||||
|
||||
Expected result:
|
||||
|
||||
1. Default gateway looks like a backend proxy, not a backend-plus-admin endpoint
|
||||
2. Advanced users can still enable interceptor protocol passthrough intentionally
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
1. Transparent mode does not advertise interceptor capability
|
||||
2. Transparent mode does not handle `interceptor/*` requests
|
||||
3. SEP mode preserves current passthrough behavior and tests
|
||||
|
||||
## Phase 2: Make Capability Mirroring Truly Transparent
|
||||
|
||||
Goal: align the gateway's advertised contract with the backend server more faithfully.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Extract capability composition into a dedicated internal component or helper
|
||||
2. Start from the backend `ServerCapabilities` rather than hand-mirroring only selected properties
|
||||
3. Mirror standard and experimental capability surfaces, including `Experimental`, `Extensions`, and `Tasks` where present
|
||||
4. Overlay interceptor capability only when `ExposeInterceptorProtocol = true`
|
||||
|
||||
Expected result:
|
||||
|
||||
1. The gateway remains aligned with the core SDK as new capabilities are added
|
||||
2. The gateway can honestly describe itself as transparent by default
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
1. Transparent mode mirrors backend capabilities broadly
|
||||
2. Interceptor capability is only present in SEP mode
|
||||
3. Existing proxy behavior remains intact for supported primitives
|
||||
|
||||
## Phase 3: Separate Proxy Core from SEP Bridge
|
||||
|
||||
Goal: separate transparent proxy concerns from SEP passthrough concerns.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Extract the built-in MCP proxying logic into a dedicated internal component
|
||||
2. Extract interceptor protocol passthrough into a dedicated internal bridge component
|
||||
3. Keep `InterceptorChainRunner` and related chain semantics shared
|
||||
4. Centralize interceptor extension capability key handling behind one internal constant/provider
|
||||
|
||||
Current implementation note:
|
||||
|
||||
1. Transparent proxy wiring lives in `GatewayProxyConfigurator`
|
||||
2. SEP bridge wiring lives in `GatewayInterceptorProtocolBridge`
|
||||
3. The extension capability key is centralized in `InterceptorProtocolConstants`
|
||||
|
||||
Expected result:
|
||||
|
||||
1. Transparent proxy and SEP bridge can evolve independently
|
||||
2. The gateway type becomes a coordinator rather than a monolith
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
1. Proxy wiring can be enabled without SEP bridge wiring
|
||||
2. SEP bridge can be enabled or disabled explicitly
|
||||
3. Internal tests can target the components independently
|
||||
|
||||
## Phase 4: Improve DI and Runtime Lifecycle Shape
|
||||
|
||||
Goal: align the builder path more closely with the core C# SDK's composition model.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Keep the current `WithInterceptorGateway(options)` overload for convenience
|
||||
2. Add a DI-native overload based on a factory or service-provider callback
|
||||
3. Refactor notification forwarding into an internal connection-bound forwarder abstraction
|
||||
4. Treat transport session identifiers as an implementation detail, not a public concept
|
||||
|
||||
Expected result:
|
||||
|
||||
1. The builder path stays declarative and SDK-native
|
||||
2. Runtime ownership of backend/interceptor connections becomes easier to evolve
|
||||
3. The implementation remains compatible with current session-bearing transports without depending on sessions semantically
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
1. Existing convenience builder API continues to work
|
||||
2. A service-provider-based configuration path exists
|
||||
3. Notification forwarding logic is isolated from proxy handler registration
|
||||
|
||||
Current implementation note:
|
||||
|
||||
1. Builder DI now supports both direct options and `Func<IServiceProvider, McpInterceptorGatewayOptions>`
|
||||
2. Connection-bound forwarding registration lives in `GatewayConnectionForwardingRegistrar`
|
||||
3. Transport session identifiers are only used as an internal deduplication mechanism where available
|
||||
|
||||
## Phase 5: Follow-Up Cleanup
|
||||
|
||||
Goal: tighten API roles after the bigger structural changes are done.
|
||||
|
||||
Changes:
|
||||
|
||||
1. Keep extension methods as the primary low-level SEP client API
|
||||
2. Keep `InterceptingMcpClient` as a convenience/orchestration layer rather than the canonical abstraction
|
||||
3. Consider clarifying or making explicit wrapped-client disposal ownership
|
||||
4. Consolidate any duplicated transparent interception flow that remains after Phases 1-4
|
||||
|
||||
Expected result:
|
||||
|
||||
1. Public API roles are clearer
|
||||
2. Future maintenance burden is lower
|
||||
|
||||
This phase is intentionally lower priority than Phases 1-4.
|
||||
|
||||
## Future Feature: External SEP-Exposing Servers
|
||||
|
||||
This comes after the phase work above.
|
||||
|
||||
Goal: allow transparent gateways to source interceptors from external SEP servers rather than only from in-process/directly-provided clients.
|
||||
|
||||
Possible outcomes:
|
||||
|
||||
1. Configuration-driven gateways (for example `mcp-interceptors.json`)
|
||||
2. Auth-aware or per-user interceptor selection
|
||||
3. Custom MCP middleware built on top of the extension's primitives
|
||||
|
||||
Likely direction:
|
||||
|
||||
1. Introduce an interceptor client/provider abstraction in addition to direct `InterceptorClients`
|
||||
2. Support static, per-request, or per-identity interceptor resolution
|
||||
3. Keep chain semantics unchanged regardless of interceptor source
|
||||
|
||||
Current implementation note:
|
||||
|
||||
1. `McpInterceptorGateway.CreateAsync(...)` now supports static external interceptor connections via `McpInterceptorServerConnectionOptions`
|
||||
2. Those connections use the same transport-driven pattern as `McpClient.CreateAsync(...)`
|
||||
3. Dynamic per-request interceptor resolution is now supported for the transparent proxy path via `InterceptorServerConnectionResolver`
|
||||
4. SEP passthrough still requires statically configured interceptor clients
|
||||
|
||||
## Open Design Notes
|
||||
|
||||
1. The interceptor extension capability key should stay aligned with the SEP for now
|
||||
2. If the SEP changes to a reverse-domain extension identifier, we should centralize the key and support a transition path
|
||||
3. Transparent mode should be the default because it matches the expected operational use of the gateway
|
||||
Loading…
Reference in a new issue