server

package
v0.1.16 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

README

server

MCP server implementation: Dispatcher, transports, middleware, subscriptions.

What belongs here

  • Server struct and options (NewServer, WithBearerToken, WithToolTimeout, etc.)
  • Dispatcher — JSON-RPC routing, method handlers, session state
  • Transports: SSE (transport.go), Streamable HTTP (streamable_transport.go)
  • InProcessTransportcore.Transport implementation for testing/embedding
  • Middleware chain (WithMiddleware, LoggingMiddleware)
  • Server-to-client request infrastructure (sendServerRequest, routeServerResponse)
  • Resource subscriptions (WithSubscriptions, NotifyResourceUpdated)
  • Broadcast notifications (Broadcast) — fan out to all connected sessions
  • Extension registration (WithExtension) — extensions declare capabilities in initialize response
  • Startup validation (validateExtensionRefs) — calls RefValidator on registered extensions to warn about unresolvable resource references

Dependencies

  • core/ — protocol types (Request, Response, ToolDef, etc.)
  • servicekit — SSE hub, graceful shutdown
  • Does NOT import client/

In-process transport

For testing, use NewInProcessTransport(srv) with client.WithTransport():

transport := server.NewInProcessTransport(srv,
    server.WithServerRequestHandler(func(ctx context.Context, req *core.Request) *core.Response {
        return client.HandleServerRequest(req) // for sampling/elicitation
    }),
    server.WithNotificationHandler(func(method string, params []byte) {
        // capture notifications in tests
    }),
)
c := client.NewClient("memory://", info, client.WithTransport(transport))

The in-process transport passes *core.Request/*core.Response directly — no JSON envelope serialization. This catches logic bugs; HTTP transport tests catch wire format bugs.

Documentation

Index

Constants

View Source
const ErrCodeCancelled = -32800

ErrCodeCancelled is the JSON-RPC error code for a cancelled request.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseErrorHandler added in v0.1.14

type BaseErrorHandler struct{}

BaseErrorHandler provides no-op defaults for all ErrorHandler methods. Embed this in your implementation to only override specific methods:

type MyHandler struct {
    server.BaseErrorHandler
    logger *slog.Logger
}
func (h *MyHandler) OnSessionExpire(id string, err error) {
    h.logger.Error("session expired", "id", id, "err", err)
}

func (BaseErrorHandler) OnKeepaliveFailure added in v0.1.14

func (BaseErrorHandler) OnKeepaliveFailure(string, int)

func (BaseErrorHandler) OnSessionExpire added in v0.1.14

func (BaseErrorHandler) OnSessionExpire(string, error)

func (BaseErrorHandler) OnTransportError added in v0.1.14

func (BaseErrorHandler) OnTransportError(error)

type Dispatcher

type Dispatcher struct {
	Reg *Registry
	// contains filtered or unexported fields
}

Dispatcher routes JSON-RPC requests to the appropriate handler.

func NewDispatcher

func NewDispatcher(info core.ServerInfo) *Dispatcher

NewDispatcher creates a dispatcher with the given server identity.

func (*Dispatcher) Close

func (d *Dispatcher) Close()

Close tears down all per-session state on the Dispatcher. Transports must call this when a session disconnects (SSE stream closes, DELETE request, client close). Centralizes cleanup so that adding new per-session state (subscriptions, sampling, elicitation) only requires updating this method, not every transport. Safe to call multiple times and on dispatchers with no session state.

func (*Dispatcher) Dispatch

func (d *Dispatcher) Dispatch(ctx context.Context, req *core.Request) *core.Response

Dispatch routes a JSON-RPC request and returns the response. Returns nil for notifications (no response expected).

func (*Dispatcher) NegotiatedVersion

func (d *Dispatcher) NegotiatedVersion() string

NegotiatedVersion returns the protocol version negotiated during initialization.

func (*Dispatcher) RegisterCompletion

func (d *Dispatcher) RegisterCompletion(refType, name string, handler core.CompletionHandler)

RegisterCompletion registers a completion handler for a specific reference. refType is "ref/prompt" or "ref/resource". name is the prompt name or resource URI template.

func (*Dispatcher) RegisterPrompt

func (d *Dispatcher) RegisterPrompt(def core.PromptDef, handler core.PromptHandler)

RegisterPrompt adds a prompt to the dispatcher's registry.

func (*Dispatcher) RegisterResource

func (d *Dispatcher) RegisterResource(def core.ResourceDef, handler core.ResourceHandler)

RegisterResource adds a resource to the dispatcher's registry.

func (*Dispatcher) RegisterResourceTemplate

func (d *Dispatcher) RegisterResourceTemplate(def core.ResourceTemplate, handler core.TemplateHandler)

RegisterResourceTemplate adds a URI template resource to the dispatcher's registry.

func (*Dispatcher) RegisterTool

func (d *Dispatcher) RegisterTool(def core.ToolDef, handler core.ToolHandler)

RegisterTool adds a tool to the dispatcher's registry.

func (*Dispatcher) RouteResponse

func (d *Dispatcher) RouteResponse(resp *core.Response) bool

RouteResponse routes an incoming JSON-RPC response from the client to a pending server-to-client request. Returns true if matched, false if no pending request was found for the response ID.

func (*Dispatcher) SetNotifyFunc

func (d *Dispatcher) SetNotifyFunc(fn core.NotifyFunc)

SetNotifyFunc sets the notification delivery function for this dispatcher. Thread-safe: can be called concurrently with getNotifyFunc reads.

type ErrorHandler added in v0.1.14

type ErrorHandler interface {
	// OnSessionExpire is called when a session is terminated due to idle
	// timeout, keepalive failure, or explicit close.
	OnSessionExpire(sessionID string, reason error)

	// OnTransportError is called for transport-level errors that don't
	// result in a client response (connection drops, body read failures).
	OnTransportError(err error)

	// OnKeepaliveFailure is called each time a keepalive ping fails.
	// consecutiveFailures is the current streak count.
	OnKeepaliveFailure(sessionID string, consecutiveFailures int)
}

ErrorHandler receives out-of-band errors that aren't returned to a specific client request — session lifecycle errors, transport failures, keepalive timeouts. Implement for observability, alerting, or diagnostics.

Embed BaseErrorHandler to only override the methods you care about.

type ExecConfig added in v0.1.16

type ExecConfig struct {
	// Name is the MCP tool name (required).
	Name string

	// Description is the tool description shown in tools/list.
	Description string

	// Command is the executable path or name (required).
	Command string

	// Args are static arguments prepended to every invocation.
	Args []string

	// Env are additional environment variables in KEY=VALUE format.
	// These are appended to the current process environment.
	Env []string

	// Dir is the working directory for the subprocess.
	// If empty, inherits the current process working directory.
	Dir string

	// Timeout is the maximum execution time per invocation.
	// Zero means no timeout beyond the request context.
	Timeout time.Duration

	// InputSchema is the JSON Schema for the tool's arguments.
	// If nil, defaults to {"type": "object"}.
	InputSchema any

	// BuildArgs transforms the tool request's JSON arguments into CLI args.
	// The returned args are appended after the static Args.
	// If nil, no dynamic arguments are added — only static Args are used.
	BuildArgs func(args json.RawMessage) ([]string, error)
}

ExecConfig configures a ToolExec tool that wraps a CLI binary as an MCP tool.

This is useful for wrapping existing CLI tools (like build systems, linters, code generators) as MCP tools without reimplementing their logic. For example, a presentation tool could expose its build command:

srv.Register(server.ToolExec(server.ExecConfig{
    Name:    "build_deck",
    Command: "slyds",
    Args:    []string{"build"},
    BuildArgs: func(args json.RawMessage) ([]string, error) {
        var p struct{ Deck string `json:"deck"` }
        json.Unmarshal(args, &p)
        return []string{"--deck", p.Deck}, nil
    },
}))

type InProcessOption

type InProcessOption func(*InProcessTransport)

InProcessOption configures an InProcessTransport.

func WithNotificationHandler

func WithNotificationHandler(h core.NotificationHandler) InProcessOption

WithNotificationHandler sets a callback for server-to-client notifications (logging, progress, resource updates). Useful in tests to verify notification delivery.

func WithServerRequestHandler

func WithServerRequestHandler(h core.ServerRequestHandler) InProcessOption

WithServerRequestHandler sets a handler for server-to-client requests (sampling/createMessage, elicitation/create). When the server sends a request during tool execution, this handler is called to produce a response.

type InProcessTransport

type InProcessTransport struct {
	// contains filtered or unexported fields
}

InProcessTransport implements core.Transport by dispatching directly to a Server in the same process. No HTTP, no serialization of the Request/Response envelope — domain params (json.RawMessage) pass through as-is.

func NewInProcessTransport

func NewInProcessTransport(srv *Server, opts ...InProcessOption) *InProcessTransport

NewInProcessTransport creates a transport that dispatches to the given server in-memory. Use with client.WithTransport() to create a client that talks to the server without HTTP.

Example:

srv := server.New(core.ServerInfo{Name: "test", Version: "1.0"})
srv.RegisterTool(def, handler)
transport := server.NewInProcessTransport(srv,
    server.WithServerRequestHandler(mySamplingHandler),
)
c := client.New("memory://", core.ClientInfo{...}, client.WithTransport(transport))

func (*InProcessTransport) Call

Call dispatches a JSON-RPC request and returns the response. Passes *Request directly to the server — no HTTP marshal/unmarshal overhead.

func (*InProcessTransport) Close

func (t *InProcessTransport) Close() error

Close tears down the session.

func (*InProcessTransport) Connect

func (t *InProcessTransport) Connect(ctx context.Context) error

Connect creates a per-session dispatcher and wires notification delivery and server-to-client request handling.

func (*InProcessTransport) Notify

func (t *InProcessTransport) Notify(ctx context.Context, req *core.Request) error

Notify dispatches a JSON-RPC notification (no response expected).

func (*InProcessTransport) SessionID

func (t *InProcessTransport) SessionID() string

SessionID returns "memory" for the in-process transport.

type Middleware

type Middleware func(ctx context.Context, req *core.Request, next MiddlewareFunc) *core.Response

Middleware intercepts a JSON-RPC request. Call next to continue the chain, or return a *core.Response directly to short-circuit (e.g., reject a request).

Middleware sees the full request (method, params, ID) and the context (which includes auth claims via core.AuthClaims(ctx) and session notification state). The response from next can be inspected or modified before returning.

Example — logging middleware:

mcpkit.WithMiddleware(mcpkit.LoggingMiddleware(logger))

Example — per-method rate limiting:

func RateLimitMiddleware(limiter *rate.Limiter) mcpkit.Middleware {
    return func(ctx context.Context, req *mcpkit.Request, next mcpkit.MiddlewareFunc) *mcpkit.Response {
        if !limiter.Allow() {
            return mcpkit.NewErrorResponse(req.ID, -32000, "rate limit exceeded")
        }
        return next(ctx, req)
    }
}

func LoggingMiddleware

func LoggingMiddleware(logger *log.Logger) Middleware

LoggingMiddleware logs every JSON-RPC request with method name, latency, and error status. Useful for debugging and operational monitoring.

Example output:

MCP initialize ok [1.2ms]
MCP tools/call ok [45.3ms]
MCP tools/call error=-32602 (invalid params) [0.1ms]

type MiddlewareFunc

type MiddlewareFunc func(context.Context, *core.Request) *core.Response

MiddlewareFunc is the signature for the next handler in the middleware chain.

type Option

type Option func(*serverOptions)

Option configures a Server.

func WithAllowedRoots

func WithAllowedRoots(roots ...string) Option

WithAllowedRoots restricts tool cwd to the given directory prefixes.

func WithAuth

func WithAuth(v core.AuthValidator) Option

WithAuth sets a custom auth validator (e.g. JWT via mcpkit/auth).

func WithBearerToken

func WithBearerToken(token string) Option

WithBearerToken sets a static bearer token for authentication. Uses constant-time comparison to prevent timing attacks.

func WithErrorHandler added in v0.1.14

func WithErrorHandler(h ErrorHandler) Option

WithErrorHandler sets a callback for out-of-band errors (session lifecycle, transport failures, keepalive timeouts). When not set, these errors are only logged via log.Printf.

func WithExtension

func WithExtension(ext core.ExtensionProvider) Option

WithExtension registers a protocol extension that will be advertised in the initialize response. Extensions declare their ID, spec version, and stability level.

func WithListen

func WithListen(addr string) Option

WithListen sets the HTTP listen address.

func WithMiddleware

func WithMiddleware(mw ...Middleware) Option

WithMiddleware registers server-side middleware that intercepts all JSON-RPC requests. Middleware executes in registration order: the first registered middleware is the outermost (runs first on request, last on response).

Middleware runs after auth checks (claims are in context) but before method routing and dispatch.

func WithRequestLogging

func WithRequestLogging(logger *log.Logger) Option

WithRequestLogging enables HTTP-level request/response logging on the server. Logs every incoming HTTP request with method, path, headers (Mcp-Session-Id, Accept, Authorization presence), and the response status code and content-type. This is transport-level logging — for JSON-RPC dispatch-level logging, use WithMiddleware(LoggingMiddleware(logger)).

Example:

srv := mcpkit.NewServer(info, mcpkit.WithRequestLogging(log.Default()))

func WithSubscriptions

func WithSubscriptions() Option

WithSubscriptions enables resource subscription support (resources/subscribe, resources/unsubscribe, and notifications/resources/updated). When enabled, the server advertises "subscribe": true in the resources capability and accepts subscription requests from clients.

Use Server.NotifyResourceUpdated(uri) to push change notifications to all sessions that have subscribed to the given URI.

func WithToolTimeout

func WithToolTimeout(d time.Duration) Option

WithToolTimeout sets the maximum duration for tool execution.

type PendingMap

type PendingMap = pendingMap

PendingMap is a type alias for SyncMap used to track pending server-to-client requests. Exported because it's referenced by transport implementations.

type Prompt added in v0.1.14

type Prompt struct {
	core.PromptDef
	Handler core.PromptHandler
}

Prompt bundles a prompt definition with its handler.

type Registry

type Registry struct {
	OnChange RegistryChangeFunc // called after mutations; nil = no notification
	// contains filtered or unexported fields
}

Registry holds all tool, resource, prompt, and completion registrations. Shared by reference across all session Dispatchers so that dynamic adds/removes are immediately visible to every session. Protected by mu: readers (list/call handlers) acquire RLock, writers (AddTool/RemoveTool etc.) acquire Lock.

When OnChange is set, it is called after every mutation with the appropriate list_changed notification method. The Server wires this to Broadcast so that connected clients are notified automatically.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty registry with initialized maps.

func (*Registry) AddCompletion

func (r *Registry) AddCompletion(refType, name string, handler core.CompletionHandler)

AddCompletion adds a completion handler. Thread-safe.

func (*Registry) AddPrompt

func (r *Registry) AddPrompt(def core.PromptDef, handler core.PromptHandler)

AddPrompt adds a prompt to the registry. Thread-safe. Broadcasts notifications/prompts/list_changed if OnChange is set.

func (*Registry) AddResource

func (r *Registry) AddResource(def core.ResourceDef, handler core.ResourceHandler)

AddResource adds a resource to the registry. Thread-safe. Broadcasts notifications/resources/list_changed if OnChange is set.

func (*Registry) AddResourceTemplate

func (r *Registry) AddResourceTemplate(def core.ResourceTemplate, handler core.TemplateHandler)

AddResourceTemplate adds a resource template to the registry. Thread-safe. Broadcasts notifications/resources/list_changed if OnChange is set.

func (*Registry) AddTool

func (r *Registry) AddTool(def core.ToolDef, handler core.ToolHandler)

AddTool adds a tool to the registry. Thread-safe. Broadcasts notifications/tools/list_changed if OnChange is set.

func (*Registry) RemovePrompt

func (r *Registry) RemovePrompt(name string) bool

RemovePrompt removes a prompt by name. Returns true if it existed. Thread-safe. Broadcasts notifications/prompts/list_changed if the prompt was removed.

func (*Registry) RemoveResource

func (r *Registry) RemoveResource(uri string) bool

RemoveResource removes a resource by URI. Returns true if it existed. Thread-safe. Broadcasts notifications/resources/list_changed if the resource was removed.

func (*Registry) RemoveResourceTemplate

func (r *Registry) RemoveResourceTemplate(uriTemplate string) bool

RemoveResourceTemplate removes a resource template by URI template. Returns true if it existed. Thread-safe. Broadcasts notifications/resources/list_changed if the template was removed.

func (*Registry) RemoveTool

func (r *Registry) RemoveTool(name string) bool

RemoveTool removes a tool by name. Returns true if it existed. Thread-safe. Broadcasts notifications/tools/list_changed if the tool was removed.

type RegistryChangeFunc

type RegistryChangeFunc func(method string)

RegistryChangeFunc is called after a registry mutation with the notification method that should be broadcast (e.g., "notifications/tools/list_changed").

type Resource added in v0.1.14

type Resource struct {
	core.ResourceDef
	Handler core.ResourceHandler
}

Resource bundles a resource definition with its handler.

type ResourceTemplate added in v0.1.14

type ResourceTemplate struct {
	core.ResourceTemplate
	Handler core.TemplateHandler
}

ResourceTemplate bundles a resource template definition with its handler.

type SSEData

type SSEData struct {
	// contains filtered or unexported fields
}

SSEData represents SSE event data that is either raw text or pre-encoded JSON. MCP uses both: the "endpoint" event carries a plain URL string, while "message" events carry JSON-RPC response objects. This type implements json.Marshaler so the servicekit JSONCodec passes the bytes through without double-encoding.

func SSEJSON

func SSEJSON(j json.RawMessage) SSEData

SSEJSON creates an SSEData containing pre-encoded JSON bytes.

func SSEText

func SSEText(s string) SSEData

SSEText creates an SSEData containing raw text that will not be JSON-encoded.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is an MCP server that can run over multiple transports.

func NewServer

func NewServer(info core.ServerInfo, opts ...Option) *Server

NewServer creates an MCP server with the given identity and options.

func (*Server) Broadcast

func (s *Server) Broadcast(method string, params any)

Broadcast sends a JSON-RPC notification to ALL connected sessions across all transports. Unlike NotifyResourceUpdated (which targets only sessions that have called resources/subscribe for a specific URI), Broadcast fans out unconditionally to every session with push capability.

Typical use cases: notifications/tools/list_changed, notifications/prompts/list_changed, or application-level broadcasts.

Safe to call from any goroutine. No-op if no sessions are connected. Sessions without push capability (e.g., Streamable HTTP without GET SSE stream) are silently skipped. Does not hold the server mutex during notification delivery.

Note: only reaches sessions registered through Handler() (SSE and Streamable HTTP transports). In-process transports manage their own notification delivery via WithNotificationHandler.

Example:

// After registering a new tool at runtime:
srv.Broadcast("notifications/tools/list_changed", nil)

func (*Server) CheckAuth

func (s *Server) CheckAuth(r *http.Request) (*core.Claims, error)

CheckAuth validates an HTTP request against the server's auth configuration. Returns the authenticated claims (if the validator provides them) and any error. Returns (nil, nil) if no auth is configured.

func (*Server) CloseAllSessions

func (s *Server) CloseAllSessions()

CloseAllSessions terminates all active sessions across all transports.

func (*Server) CloseSession

func (s *Server) CloseSession(id string) bool

CloseSession terminates an active session by ID across all transports. Returns true if the session was found and closed.

func (*Server) Dispatch

func (s *Server) Dispatch(ctx context.Context, req *core.Request) *core.Response

Dispatch routes a JSON-RPC request through the server's dispatch layer.

func (*Server) Handler

func (s *Server) Handler(opts ...TransportOption) http.Handler

Handler returns an http.Handler implementing MCP transports. By default, only the legacy SSE transport is enabled. Use WithStreamableHTTP(true) to enable the Streamable HTTP transport (MCP 2025-03-26). Both transports can be enabled simultaneously for backward compatibility.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(opts ...TransportOption) error

ListenAndServe starts the HTTP transport(s) with graceful shutdown support. On SIGTERM/SIGINT it stops accepting new connections, closes active sessions, drains in-flight requests, and exits.

func (*Server) NotifyResourceUpdated

func (s *Server) NotifyResourceUpdated(uri string)

NotifyResourceUpdated sends a notifications/resources/updated notification to all clients that have subscribed to the given resource URI. This is the application-facing API for triggering resource change notifications.

Safe to call from any goroutine. No-op if subscriptions are not enabled or no clients are subscribed to the URI.

Example:

// After updating config.yaml on disk:
srv.NotifyResourceUpdated("file:///data/config.yaml")

func (*Server) Register added in v0.1.14

func (s *Server) Register(items ...any)

Register registers one or more tools, resources, resource templates, or prompts using single-struct registration. Each argument must be a Tool, Resource, ResourceTemplate, or Prompt value.

The existing two-argument methods (RegisterTool, RegisterResource, etc.) remain available for backward compatibility.

Example:

srv.Register(
    server.Tool{ToolDef: core.ToolDef{Name: "a"}, Handler: handlerA},
    server.Resource{ResourceDef: core.ResourceDef{URI: "test://b"}, Handler: handlerB},
    server.Prompt{PromptDef: core.PromptDef{Name: "c"}, Handler: handlerC},
)

func (*Server) RegisterCompletion

func (s *Server) RegisterCompletion(refType, name string, handler core.CompletionHandler)

RegisterCompletion registers a completion handler for argument autocompletion. refType is "ref/prompt" or "ref/resource". name is the prompt name or resource URI template.

func (*Server) RegisterExperimentalPrompt

func (s *Server) RegisterExperimentalPrompt(def core.PromptDef, handler core.PromptHandler)

RegisterExperimentalPrompt registers a prompt marked as experimental via annotations.

func (*Server) RegisterExperimentalResource

func (s *Server) RegisterExperimentalResource(def core.ResourceDef, handler core.ResourceHandler)

RegisterExperimentalResource registers a resource marked as experimental via annotations.

func (*Server) RegisterExperimentalTool

func (s *Server) RegisterExperimentalTool(def core.ToolDef, handler core.ToolHandler)

RegisterExperimentalTool registers a tool marked as experimental via annotations.

func (*Server) RegisterPrompt

func (s *Server) RegisterPrompt(def core.PromptDef, handler core.PromptHandler)

RegisterPrompt adds a prompt to the server.

func (*Server) RegisterResource

func (s *Server) RegisterResource(def core.ResourceDef, handler core.ResourceHandler)

RegisterResource adds a resource to the server.

func (*Server) RegisterResourceTemplate

func (s *Server) RegisterResourceTemplate(def core.ResourceTemplate, handler core.TemplateHandler)

RegisterResourceTemplate adds a URI template resource to the server.

func (*Server) RegisterTool

func (s *Server) RegisterTool(def core.ToolDef, handler core.ToolHandler)

RegisterTool adds a tool to the server.

func (*Server) Registry

func (s *Server) Registry() *Registry

Registry returns the server's shared registry. All session dispatchers share this registry, so changes (AddTool, RemoveTool, etc.) are immediately visible to every session. When the server has active sessions, mutations automatically broadcast the appropriate notifications/*/list_changed notification.

func (*Server) Run

func (s *Server) Run(addr string, opts ...TransportOption) error

Run is a convenience entry point that starts the server with Streamable HTTP on the given address. It is equivalent to:

srv.ListenAndServe(mcpkit.WithStreamableHTTP(true))

with the address set via WithListen. For more control over transport options, use ListenAndServe directly.

Example:

srv := mcpkit.NewServer(mcpkit.ServerInfo{Name: "my-server", Version: "1.0"})
srv.RegisterTool(def, handler)
srv.Run(":8787")

func (*Server) RunStdio

func (s *Server) RunStdio(ctx context.Context, opts ...StdioOption) error

RunStdio runs the MCP server over stdio using Content-Length framed JSON-RPC. Blocks until ctx is cancelled or the input stream reaches EOF.

This is the primary entry point for editor-spawned MCP servers. The server reads JSON-RPC messages from stdin (or the configured input), dispatches them through the standard Server dispatch pipeline, and writes responses to stdout (or the configured output).

Example:

srv := server.NewServer(core.ServerInfo{Name: "my-server", Version: "1.0"})
srv.RegisterTool(def, handler)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
if err := srv.RunStdio(ctx); err != nil {
    log.Fatal(err)
}

type StdioOption

type StdioOption func(*stdioConfig)

StdioOption configures the stdio transport.

func WithStdioInput

func WithStdioInput(r io.Reader) StdioOption

WithStdioInput overrides stdin for the stdio transport. Primarily used for testing with pipe pairs.

func WithStdioLogger

func WithStdioLogger(l *log.Logger) StdioOption

WithStdioLogger sets a logger for debug output on stderr. Debug logging is separate from the MCP protocol — it goes to stderr, never to stdout.

func WithStdioOutput

func WithStdioOutput(w io.Writer) StdioOption

WithStdioOutput overrides stdout for the stdio transport. Primarily used for testing with pipe pairs.

type Tool added in v0.1.14

type Tool struct {
	core.ToolDef
	Handler core.ToolHandler
}

Tool bundles a tool definition with its handler for single-struct registration via Server.Register. This is the recommended way to register tools — it keeps the definition and handler together as a single value, making it easy to build tool registries or load tools from configuration.

Example:

srv.Register(server.Tool{
    ToolDef: core.ToolDef{Name: "echo", Description: "Echo input", InputSchema: schema},
    Handler: func(ctx context.Context, req core.ToolRequest) (core.ToolResult, error) {
        return core.TextResult("echoed"), nil
    },
})

func ToolExec added in v0.1.16

func ToolExec(cfg ExecConfig) Tool

ToolExec creates a Tool that wraps a CLI command execution. The returned Tool can be registered via srv.Register(server.ToolExec(cfg)).

On success (exit code 0), returns TextResult with the combined stdout/stderr. On failure (non-zero exit), returns ErrorResult with the output and exit code. Context cancellation (including Timeout) is propagated to the subprocess.

type TransportOption

type TransportOption func(*transportConfig)

TransportOption configures the HTTP transports.

func WithAllowedOrigins

func WithAllowedOrigins(origins ...string) TransportOption

WithAllowedOrigins sets the allowed Origin header values for DNS rebinding protection. When empty (default), only localhost origins are accepted.

func WithEventStore added in v0.1.11

func WithEventStore(store gohttp.EventStore) TransportOption

WithEventStore sets an optional EventStore for SSE event persistence. When configured, all SSE events (GET SSE stream notifications and POST SSE response events) are stored with unique IDs. Clients that reconnect with a Last-Event-ID header receive missed events via replay.

Pass nil to disable (default). Use gohttp.NewMemoryEventStore(maxPerStream) for an in-memory implementation.

func WithKeepalive added in v0.1.11

func WithKeepalive(interval time.Duration, maxFailures int) TransportOption

WithKeepalive enables application-level keepalive pings for session liveness detection. When enabled, the server periodically sends JSON-RPC ping requests to clients via their GET SSE stream. If maxFailures consecutive pings fail (timeout or error), the session is expired.

interval controls how often pings are sent (e.g., 30*time.Second). maxFailures is the threshold before session cleanup (e.g., 3). Set interval to 0 to disable (default).

func WithKeepalivePeriod

func WithKeepalivePeriod(d time.Duration) TransportOption

WithKeepalivePeriod sets the interval for SSE keepalive comments.

func WithMaxSessions

func WithMaxSessions(n int) TransportOption

WithMaxSessions limits the number of concurrent sessions.

func WithPrefix

func WithPrefix(p string) TransportOption

WithPrefix sets the URL path prefix for transport endpoints.

func WithPublicURL

func WithPublicURL(u string) TransportOption

WithPublicURL sets the public base URL used in the SSE endpoint event. Use this when the server is behind a reverse proxy.

func WithSSE

func WithSSE(enabled bool) TransportOption

WithSSE enables or disables the legacy SSE transport (MCP 2024-11-05).

func WithSessionTimeout

func WithSessionTimeout(d time.Duration) TransportOption

WithSessionTimeout sets the idle timeout for Streamable HTTP sessions. Sessions that receive no POST requests for this duration are automatically expired and cleaned up. Active requests (in-flight tool calls, open GET SSE streams) pause the timer so sessions are never closed mid-execution. Default is 0 (no timeout — sessions persist until explicit DELETE or server restart).

func WithStateless

func WithStateless(enabled bool) TransportOption

WithStateless enables stateless mode for the Streamable HTTP transport. In stateless mode, every request gets a fresh Dispatcher — no session storage, no Mcp-Session-Id header, no state carried across requests. The initialize handshake is auto-performed per request.

Use for simple tool servers that don't need session state (e.g., single-tool APIs, serverless functions, CLI wrappers).

func WithStreamableHTTP

func WithStreamableHTTP(enabled bool) TransportOption

WithStreamableHTTP enables or disables the Streamable HTTP transport (MCP 2025-03-26).

Jump to

Keyboard shortcuts

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