mcphttp

package
v1.39.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package mcphttp carries the HTTP plumbing an MCP server needs around the protocol handler: the middleware chain, the health and RFC 9728 metadata endpoints, and the bearer-token authentication that turns a token into the per-request values tool handlers read.

It lives here rather than in a server's main package because a main package cannot be imported. Authentication especially must not be forked: two copies drift, and the one that drifts is the one that stops rejecting what it should.

Index

Constants

View Source
const DefaultMaxBodySize = 10 * 1024 * 1024 // 10 MB

DefaultMaxBodySize is the request body limit LimitBody applies unless a server passes its own. Pin the same value into mcp.StreamableHTTPOptions.MaxRequestBodyBytes: left at zero the SDK applies its own smaller default, silently tightening the limit this one advertises.

Variables

This section is empty.

Functions

func Auth

func Auth(resources config.Resources, validator *auth.Validator, next http.Handler) http.Handler

Auth authenticates every request with a bearer token, rejecting the ones that carry no usable credential and populating the context of the ones that do.

Unauthenticated paths are the ones that cannot require a token: health checks, browser favicon probes, and the /.well-known OAuth metadata an unauthorised client fetches to discover where to authorise. A request with no Authorization header on any other path is allowed through only when its JSON body names a protocol method auth.Bypass whitelists, which is how a client negotiates capabilities before it holds a token.

func Chain

func Chain(h http.Handler, mws ...func(http.Handler) http.Handler) http.Handler

Chain applies middlewares so the first argument is the outermost wrapper (runs first on the request, last on the response).

func Health

func Health(mux *http.ServeMux, path string)

Health registers a GET/OPTIONS health check that requires no authentication.

func LimitBody

func LimitBody(maxBodySize int64, next http.Handler) http.Handler

LimitBody caps the request body a client may send.

func Log

func Log(logger *slog.Logger, skipPaths map[string]struct{}, next http.Handler) http.Handler

Log records one line per request: the trace id, the request and response, and the installation and user the token resolved to. Request bodies go through logsafe, which strips anything token-shaped.

skipPaths keeps the noisy endpoints out: health checks fire constantly, and an SSE stream lives as long as the request, so its body is logged by SSELog instead.

func ProtectedResource

func ProtectedResource(mux *http.ServeMux, resources config.Resources, groups []*toolsets.ToolsetGroup)

ProtectedResource registers the RFC 9728 protected-resource metadata an unauthorised client fetches to discover where and for what to authorise.

The advertised scopes come from what the registered groups declare, so a scope a client may ask for always has a group behind it. A group declaring a scope the authorization server does not know will still fail at registration — the authorization server keeps its own catalogue, and this endpoint cannot check against it.

https://datatracker.ietf.org/doc/html/rfc9728/#section-2

func RequestInfo

func RequestInfo(next http.Handler) http.Handler

RequestInfo attaches the per-request trace and installation info every later middleware and the MCP logging middleware read.

func SSELog

func SSELog(logger *slog.Logger, next http.Handler) http.Handler

SSELog logs a Server-Sent Events endpoint, where the long-lived GET stream and the short-lived POST message deliveries need different treatment: the stream is logged once when it opens and once when it closes, so a connection held for hours does not sit unlogged, or buffer its body until it ends.

func Sentry

func Sentry(resources config.Resources, next http.Handler) http.Handler

Sentry scopes a Sentry hub to the request so a panic or reported error carries the request that caused it. A no-op when no DSN is configured.

func StripProfile

func StripProfile(profiles []string, next http.Handler) http.Handler

StripProfile checks whether the request path starts with a known profile name, and if so strips it and sets a "TW-MCP-Profile" header. This lets clients use URLs like "/project-manager/endpoint" to reach "/endpoint" with a profile context.

func Tracer

func Tracer(resources config.Resources, skipPaths map[string]struct{}, next http.Handler) http.Handler

Tracer wraps the handler in Datadog APM tracing, naming each span by method and path. Returns next unchanged when APM is disabled.

skipPaths drops the endpoints not worth a trace: health checks are constant noise, and a long-lived SSE stream does not fit a request span. Every /.well-known path is skipped too.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL