experimental-ext-interceptors/go/sdk/doc/CONFORMANCE.md
Kurt Degiorgio c9900f02ab
Implement Go interceptor chain (#4)
## Summary

Implements the Go SDK for MCP interceptors — validation and mutation
middleware for any MCP server.

The framework treats interceptors as first-class MCP primitives: they
are registered on an MCP server, discoverable via `interceptors/list`,
and invocable via `interceptor/invoke` — the same JSON-RPC pattern as
tools, prompts, and resources. A chain engine orchestrates execution
across one or more interceptor servers, and an optional go-sdk
middleware integration applies interceptors automatically on every
matching request/response.

## Architecture

**Three-layer design:**

1. **`interceptors`** — Protocol-agnostic core. Defines interceptor
types (validators, mutators), metadata, invocation, wire types, and
results. Zero MCP dependencies.

2. **`interceptors/mcpserver`** — MCP server integration. Wraps
`mcp.Server` to register `interceptors/list` and `interceptor/invoke` as
custom JSON-RPC methods and advertise interceptor capabilities during
`initialize`.

3. **`interceptors/chain`** — Chain engine. Orchestrates execution
across N interceptor servers with trust-boundary-aware ordering,
priority-based mutation sequencing, parallel validation, audit-mode
isolation, and fail-open/fail-closed semantics.

4. **`interceptors/integrations/gomiddleware`** — Optional go-sdk
middleware. Installs on `mcp.Server` via `AddReceivingMiddleware()` to
automatically run the interceptor chain on every matching
request/response.

**Key design decisions:**

- **Trust-boundary ordering** — request phase: validate → mutate;
response phase: mutate → validate. Validation always guards the boundary
crossing.
- **Wire-level invocation** — the chain calls `interceptor/invoke` over
the MCP transport (even in-process via `LocalChain()`), so local and
remote interceptor servers use the same interface.
- **Audit-mode isolation** — audit-mode mutators compute transformations
without applying them. Only audit mutators pay the serialization cost.
- **Concurrency** — validators run in parallel; mutators run
sequentially in priority order.

### Package Structure

| Package | File | Responsibility |
|---------|------|----------------|
| `interceptors` | `interceptor.go` | Enums, Metadata, Interceptor
interface, Validator/Mutator structs, handler types, Invocation |
| `interceptors` | `wire.go` | Wire types: ListParams/Result,
InvokeParams/Result, InterceptorInfo, event/method constants |
| `interceptors` | `priority.go` | Priority with phase-aware resolution
and JSON marshaling |
| `interceptors` | `doc.go` | Package documentation with examples |
| `interceptors/chain` | `chain.go` | Chain engine: discovery,
filtering, sorting, execution orchestration |
| `interceptors/chain` | `result.go` | ExecutionResult, AbortInfo |
| `interceptors/chain` | `doc.go` | Sub-package documentation |
| `interceptors/mcpserver` | `server.go` | MCP server wrapper,
interceptor registry, capability advertisement, `LocalChain()` |
| `interceptors/mcpserver` | `rpc.go` | `interceptors/list` and
`interceptor/invoke` JSON-RPC handlers |
| `interceptors/mcpserver` | `doc.go` | Sub-package documentation |
| `integrations/gomiddleware` | `middleware.go` | go-sdk `Middleware`
that runs the chain on every request/response |
| `integrations/gomiddleware` | `errors.go` | Abort-to-JSONRPC error
conversion |
| `integrations/gomiddleware` | `doc.go` | Sub-package documentation |

### Documentation

- `doc/DESIGN.md` — architecture, execution model, integration with
go-sdk
- `doc/CONFORMANCE.md` — SEP conformance status
- `doc/PERFORMANCE.md` — per-request cost model

### Examples

- `examples/validator` — blocks dangerous tool calls, demonstrates
`WithContextProvider`
- `examples/mutator` — tags tool responses with audit trail

## Vendor: go-sdk v1.4.0 with custom method support

Vendors `go-sdk` with minimal extensions for custom JSON-RPC methods:

- `Server.AddCustomMethod` — registers a handler that bypasses the typed
pipeline
- `ClientSession.CallCustom` — sends raw JSON-RPC calls for custom
methods

These changes are generic (not interceptor-specific) and enable any MCP
extension to define its own JSON-RPC methods.

## TODO

- More integration tests
- Unit tests
- Support wildcards for event interception (separate PR)

---------

Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
2026-04-29 15:29:25 +01:00

3.6 KiB

SEP Conformance

Status of this Go SDK implementation against the SEP-1763 interceptor proposal.

Implemented

Area Notes
Validation interceptors Parallel execution, severity-based blocking, fail-open support
Mutation interceptors Sequential execution, priority ordering, payload threading via json.RawMessage
Interceptor metadata Name, version, description, events, phase, priorityHint (polymorphic JSON), compat, configSchema, mode, failOpen
Event names Constants for all standard server-side MCP methods; JSON-RPC method names used directly as event names
Protocol methods interceptors/list for discovery, interceptor/invoke for invocation — both registered as custom JSON-RPC methods
InterceptorChain (SEP) chain.Chain type with chain.ChainEntry objects pairing interceptor descriptors with MCP client sessions
ChainEntry (SEP) chain.ChainEntry struct holds InterceptorInfo + *mcp.ClientSession
Chain discovery chain.Chain.AddMCPServer() calls interceptors/list to discover interceptors from an MCP server
Chain execution chain.Chain.Execute() invokes interceptors via interceptor/invoke on the appropriate server per entry
InvokeResult envelope Per-interceptor result with interceptor name, type, phase, duration, validation/mutation result, mutated payload
chain.ExecutionResult Aggregated chain result with status, results, finalPayload, validationSummary, abortedAt, totalDurationMs
JSON-RPC error mapping Typed error data structs: -32602 for validation, -32603 for mutation, -32000 for timeout
Trust-boundary execution order Request: validate (parallel) then mutate (sequential); Response: mutate (sequential) then validate (parallel)
Priority ordering Mutators sorted by priorityHint.Resolve(phase) ascending, alphabetical tiebreak
Fail-open behavior FailOpen: true interceptors log errors without aborting the chain
Audit mode ModeAudit records results without blocking; mutated payloads not propagated
Timeout & context Per-interceptor timeouts via InvokeParams.TimeoutMs, chain-level context cancellation, InvocationContext with principal/traceId
Receiving direction (client → server) All server-side method calls intercepted via AddReceivingMiddleware
Capability declaration Interceptor metadata injected into initialize response via Capabilities.Experimental
First-party (in-process) deployment Server.LocalChain() creates an in-memory transport chain.Chain; interceptors invoked via JSON-RPC even in-process
Third-party and hybrid deployment Chain entries can point to any *mcp.ClientSession — local (in-memory), stdio, or HTTP transport
json.RawMessage payloads Interceptor handlers receive json.RawMessage via interceptor/invoke, matching the SEP's JSON-level payload model

Not Implemented

Area SEP expects Notes
Wildcard event matching "*/request", "*/response", "*" matchesEvent does exact match only; wildcard patterns are planned
Server → client interception Client features as interceptable events: "sampling/createMessage", "elicitation/create", "roots/list" Requires Server.AddSendingMiddleware support in the go-sdk
Per-interceptor config passthrough ChainExecutionParams.Config map Wired through to InvokeParams.Config but not yet used by middleware
Remote interceptor servers Connecting chain to external MCP servers over stdio/HTTP Infrastructure is ready (chain.Chain.AddMCPServer accepts any *mcp.ClientSession); no convenience helpers yet