Documentation
¶
Overview ¶
Package middleware holds the receiving-side MCP middlewares an MCP resource server installs: request logging, tools/call authorization (Auth) and tools/list visibility filtering (Visibility).
Index ¶
- Constants
- func Auth(lc log.Logger) sdkmcp.Middleware
- func Deadline(ceiling time.Duration) sdkmcp.Middleware
- func DecodeArguments(lc log.Logger) sdkmcp.Middleware
- func Logging(lc log.Logger) sdkmcp.Middleware
- func RejectToolsList(err error) sdkmcp.Middleware
- func Visibility(lc log.Logger, client RouteAuthorizer, ...) sdkmcp.Middleware
- type AuthRoute
- type AuthRouteResult
- type RouteAuthorizer
Constants ¶
const OAuthAuthRoutesPath = "/api/v3/oauth/auth-routes"
OAuthAuthRoutesPath is proxy-auth's batch OAuth route-authz endpoint.
const ToolCallCeiling = 30 * time.Second
ToolCallCeiling bounds the authorization sub-call, the upstream request and its body — not any registry/address lookup a service resolves outside the call.
Variables ¶
This section is empty.
Functions ¶
func Auth ¶
func Auth(lc log.Logger) sdkmcp.Middleware
Auth attaches the caller's bearer token to the context of every tools/call and reports the authorization outcome of whatever upstream calls the tool then makes.
It does not decide anything. The decision is made once, per outgoing request, inside authz.Transport — which is looking at the request being sent rather than at a prediction of it. This middleware exists so the caller's identity reaches that transport, and so a refusal reads to the model as a refusal.
Local tools have no route-authorized upstream call. Endpoint-level bearerAuthn has already required a valid token, but any upstream access must perform the additional validation documented for Local tools.
func Deadline ¶
func Deadline(ceiling time.Duration) sdkmcp.Middleware
Deadline bounds every ceilinged method at ceiling, on the caller's own context. ceiling is a parameter so a test can pass 50 ms instead of waiting 30 s. ⚠ Register it LAST so it nests OUTERMOST — only from there does it bound the whole call.
func DecodeArguments ¶
func DecodeArguments(lc log.Logger) sdkmcp.Middleware
DecodeArguments accepts an array or object argument that a client sent as a JSON string. Claude Desktop and the claude.ai connector serialise every argument declared as an array or object, leaving scalars alone, and the SDK's schema gate rejects those calls before any tool handler runs.
It must stay innermost (installed first, see the middleware chain): it reads the advertised schemas back through `next`, which outside Visibility would return a per-caller subset and outside Logging would log a request no client made.
func Logging ¶
func Logging(lc log.Logger) sdkmcp.Middleware
Logging returns a pass-through middleware that logs every incoming MCP request's method, tool name (when method is tools/call), duration, an approximate response-token count, and error.
func RejectToolsList ¶
func RejectToolsList(err error) sdkmcp.Middleware
RejectToolsList fails every tools/list with err while passing other methods through. tools/call is left alone deliberately: it is refused further down, by the transport, so rejecting it here as well would be a second copy of one decision.
func Visibility ¶
func Visibility(lc log.Logger, client RouteAuthorizer, toolRoutes func() map[string][]tool.Route, isLocal func(string) bool, resource string) sdkmcp.Middleware
Visibility filters tools/list down to the tools the calling user may actually use: it batch-authorizes the union of every listed tool's declared route universe and keeps a tool when any one route is allowed, and declares the result private so no intermediary may forward one caller's catalogue to the next. Union semantics, the local-tool exemption, the fail-closed paths and the pagination caveat are all explained in README.md.
Types ¶
type AuthRoute ¶
type AuthRoute struct {
Path string `json:"path" validate:"required,dto-none-empty-string"`
// The Method oneof constraint must stay in sync with tool.validMethods, which
// Register enforces at startup (see pkg/mcp/tool/registry.go).
Method string `json:"method" validate:"required,oneof=GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH QUERY MUTATION SUBSCRIPTION"`
}
type AuthRouteResult ¶
AuthRouteResult defines the content for auth route result
type RouteAuthorizer ¶
type RouteAuthorizer interface {
AuthRoutes(ctx context.Context, headers map[string]string, routes []tool.Route) ([]AuthRouteResult, error)
}
RouteAuthorizer is the proxy-auth subset tools/list filtering needs: authorize a whole route set for the bearer's user in one round-trip.
func NewAuthRoutesClient ¶
func NewAuthRoutesClient(baseURL string, injector restinterfaces.AuthenticationInjector) RouteAuthorizer
NewAuthRoutesClient builds the proxy-auth batch route-authz client Visibility uses.