Conversation
e9dedc9 to
b008a8f
Compare
| strategy: | ||
| matrix: | ||
| go: ["1.23", "1.24", "1.25"] | ||
| go: ["1.24", "1.25"] |
There was a problem hiding this comment.
Can you include go version 1.26 too
| // work across all transports (stdio, HTTP) and compose with other extensions | ||
| // like variants. | ||
| type Server struct { | ||
| inner *mcp.Server |
There was a problem hiding this comment.
Will it be better to embed the mcp.Server direclty?
type Server struct {
*mcp.Server
// ...
}
There was a problem hiding this comment.
I opted not to embed *mcp.Server to avoid leaking AddReceivingMiddleware (or the sending equiv). The interceptor server installs its own middleware during construction, and exposing AddReceivingMiddleware on the wrapper would let callers unknowingly affect middleware ordering. Wrapping keeps the API surface explicit.
22dec21 to
d836df8
Compare
|
|
||
| // interceptResponse runs the response-phase interceptor chain. Mutators | ||
| // modify the typed result in place, so no marshal/unmarshal is needed. | ||
| func (s *Server) interceptResponse( |
There was a problem hiding this comment.
interceptResponse may need access to the request payload too.
Can you include it as one of the argument or part of InvocationContext?
There was a problem hiding this comment.
I agree this will be useful, added a getter, see tests
| // InterceptorType identifies the category of an interceptor. | ||
| type InterceptorType string | ||
|
|
||
| const ( |
There was a problem hiding this comment.
Is there a plan to support the third interceptor type from the SEP, observability?
There was a problem hiding this comment.
No, check the comments on the SEP, in short, we added an audit mode for validators and mutators instead
d836df8 to
e9bc172
Compare
0a4611f to
84baa99
Compare
710da16 to
5f6bd56
Compare
Add the interceptor implementation for servers built with the go-sdk.
Interceptors sit between the transport and method handlers, enabling
policy enforcement, data sanitization, and traffic auditing without
modifying handler code.
The core interceptor framework (chain engine, validators, mutators,
invocations, results) is fully protocol-agnostic with zero MCP
dependencies, so it can be used with any server that processes
request/response pairs (gRPC, custom HTTP, etc.).
The MCP-specific server integration lives in a separate mcpserver
sub-package, wiring interceptors into go-sdk's middleware for all
transports (stdio, HTTP).
This covers the server-side chain execution model only. The SEP's
protocol-level methods (interceptors/register, interceptors/update,
interceptors/list, interceptors/execute) are not yet implemented.
Package structure:
interceptors/
chain.go — public Chain type, protocol-agnostic API
chain_executor.go — chainExecutor, filtering, sorting, snapshots
chain_validate.go — parallel validator dispatch
chain_mutate.go — sequential mutator execution
interceptor.go — types, Metadata, Validator/Mutator structs
invocation.go — Invocation with audit-mode payload cloning
result.go — ValidationResult, MutationResult, ChainResult
doc.go — package documentation with examples
interceptors/mcpserver/
server.go — Server wrapper, middleware, capability declaration
events.go — MCP event name constants
doc.go — sub-package documentation
Also includes:
- examples/validator and examples/mutator
- HTTP integration tests (httptest + StreamableHTTPHandler)
- doc/DESIGN.md, doc/CONFORMANCE.md, doc/PERFORMANCE.md
Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
5f6bd56 to
bfa239f
Compare
Summary
Implements the server-side interceptor chain for Go, enabling validation and mutation middleware on
any server that processes request/response pairs.
The core interceptor framework (chain engine, validators, mutators, invocations, results) is fully
protocol-agnostic with zero MCP dependencies. The MCP-specific server integration lives in a
separate
mcpserversub-package, wiring interceptors into go-sdk's middleware for all transports(stdio, HTTP).
Protocol-Level Methods — Current Limitation
The SEP defines interceptors as a first-class resource type, like tools, prompts, and resources.
The server should expose them via
interceptors/listandinterceptor/executeChain, andconsumers — including the middleware integration — should call them as clients through the
transport, the same way a client calls
tools/call.Where we want to be:
interceptors/listandinterceptor/executeChainas JSON-RPC methodsinterceptor/executeChainviamcp.Clientto run the chain, rather than calling theChainengine directlyWhere we are right now:
Chainengine directly (in-process only)checkRequest()rejects unknown methods before middleware runs, and there is noAddMethodAPIBlocked on go-sdk:
AddMethod(or equivalent) to go-sdkinterceptors/listandinterceptor/executeChainas protocol methodsmcp.Clientas the entry pointArchitecture
interceptorspackage exposes a publicChaintype that managesinterceptor registration and execution with no transport coupling. Any server can use
Chain.ExecuteForReceiving/Chain.ExecuteForSendingdirectly.Invocation.Payloadcarries the live Go value (any) directly through the chain, thesame pattern as gRPC-Go interceptors. Handlers type-assert to the concrete type and mutate in place. Zero JSON
operations in the normal path.
response phase runs mutate → validate (mutations prepare before validation).
modifications don't affect the real payload. Only audit mutators pay this cost.
chainExecutors are cached perevent|phasein async.Map, invalidated implicitly onAddvia atomic snapshot swap.order.
Package Structure
interceptorschain.goChaintype,NewChain,Add,ExecuteForReceiving/Sending,IsEmptyinterceptorschain_executor.gochainExecutor, filtering, sorting, snapshot cachinginterceptorschain_validate.gointerceptorschain_mutate.gointerceptorsinterceptor.gointerceptorsinvocation.gointerceptorsresult.gointerceptorsdoc.gointerceptors/mcpserverserver.gointerceptors/mcpserverevents.gointerceptors/mcpserverdoc.goDocumentation
doc/DESIGN.md— architecture, execution model, integration with go-sdkdoc/CONFORMANCE.md— SEP conformance statusdoc/PERFORMANCE.md— per-request cost modeldoc.go— detailed go docsTODO
interceptors/*) — blocked on go-sdk custom method support