## Summary - Rename `interceptors/mcpserver/` → `interceptors/extension/`, replacing the `Server` wrapper with a lightweight `Extension` that can install itself on any `*mcp.Server` - Remove the stored `*mcp.Server` field — `Extension` is now a pure interceptor container with no server reference - Add `Install(server)` method to register JSON-RPC methods and init middleware on a given server - Update `LocalChain(ctx)` → `LocalChain(ctx, server)` to accept the server as a parameter - Remove `MCPServer()`, `Run()`, and `NewStreamableHTTPHandler()` wrapper methods — users interact with `mcp.Server` directly - Update all examples, tests, and documentation to use the new API ## Why `mcpserver.Server` pretended to *be* the server — it had `Run()`, `NewStreamableHTTPHandler()`, etc. — but it could never cover the full `*mcp.Server` API, so users constantly needed `MCPServer()` to unwrap it. `Extension` doesn't pretend to be the server. It's a pure interceptor container that can install itself on any server (or multiple servers) on the fly. No stored server reference, no wrapping, no delegation surface to maintain. ### Before ```go mcpServer := mcp.NewServer(...) srv := mcpserver.NewServer(mcpServer) srv.AddInterceptor(v) chain, err := srv.LocalChain(ctx) ``` ### After ```go mcpServer := mcp.NewServer(...) ext := extension.New() ext.AddInterceptor(v) ext.Install(mcpServer) chain, err := ext.LocalChain(ctx, mcpServer) ``` Signed-off-by: Kurt Degiorgio <kdegiorgio@bloomberg.net>
55 lines
1.9 KiB
Go
55 lines
1.9 KiB
Go
// Copyright 2025 The MCP Interceptors Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache-2.0
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package extension registers interceptors as first-class MCP
|
|
// primitives. Adding an interceptor to the extension makes it
|
|
// discoverable via "interceptors/list" and invocable via
|
|
// "interceptor/invoke", so any MCP client — local or remote — can
|
|
// discover and call interceptors using standard JSON-RPC.
|
|
//
|
|
// # Getting Started
|
|
//
|
|
// Create an [Extension], register interceptors, and install on an
|
|
// [mcp.Server]:
|
|
//
|
|
// ext := extension.New(extension.WithLogger(logger))
|
|
// ext.AddInterceptor(myValidator)
|
|
// ext.AddInterceptor(myMutator)
|
|
// ext.Install(mcpServer)
|
|
//
|
|
// At this point any connected MCP client can call interceptors/list
|
|
// and interceptor/invoke.
|
|
//
|
|
// For convenience, [Extension.LocalChain] creates a [chain.Chain] wired
|
|
// to the server over an in-memory transport, ready for use with the
|
|
// gomiddleware package:
|
|
//
|
|
// chain, err := ext.LocalChain(ctx, mcpServer)
|
|
// mcpServer.AddReceivingMiddleware(
|
|
// gomiddleware.Middleware(chain,
|
|
// gomiddleware.WithContextProvider(myProvider),
|
|
// ),
|
|
// )
|
|
//
|
|
// # JSON-RPC Methods
|
|
//
|
|
// The extension installs two JSON-RPC methods on the server:
|
|
//
|
|
// - "interceptors/list": Returns all registered interceptors,
|
|
// optionally filtered by event name.
|
|
// - "interceptor/invoke": Invokes a single interceptor by name
|
|
// for a given event, phase, and payload.
|
|
//
|
|
// # Transports
|
|
//
|
|
// Users interact with the [mcp.Server] directly for transport
|
|
// configuration. For stdio, use [mcp.Server.Run]. For HTTP, use
|
|
// [mcp.NewStreamableHTTPHandler]:
|
|
//
|
|
// handler := mcp.NewStreamableHTTPHandler(
|
|
// func(r *http.Request) *mcp.Server { return mcpServer },
|
|
// nil,
|
|
// )
|
|
// http.ListenAndServe(":8080", handler)
|
|
package extension
|