mcpkit

package module
v0.0.14 Latest Latest
Warning

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

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

README

MCPKit

Production-grade MCP (Model Context Protocol) server library for Go.

MCPKit handles the transport, protocol negotiation, session management, and auth so you can focus on registering tools, resources, and prompts. Supports both HTTP+SSE (MCP 2024-11-05) and Streamable HTTP (MCP 2025-03-26) transports.

Quick Start

package main

import (
    "context"
    "log"
    "time"
    "github.com/panyam/mcpkit"
)

func main() {
    srv := mcpkit.NewServer(
        mcpkit.ServerInfo{Name: "my-server", Version: "0.1.0"},
        mcpkit.WithListen(":8787"),
        mcpkit.WithToolTimeout(30 * time.Second),
    )

    srv.RegisterTool(
        mcpkit.ToolDef{
            Name:        "greet",
            Description: "Say hello",
            InputSchema: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "name": map[string]any{"type": "string"},
                },
                "required": []string{"name"},
            },
        },
        func(ctx context.Context, req mcpkit.ToolRequest) (mcpkit.ToolResult, error) {
            var args struct {
                Name string `json:"name"`
            }
            if err := req.Bind(&args); err != nil {
                return mcpkit.ErrorResult(err.Error()), nil
            }
            return mcpkit.TextResult("Hello, " + args.Name + "!"), nil
        },
    )

    // Streamable HTTP (recommended) — responses in HTTP body
    srv.ListenAndServe(mcpkit.WithStreamableHTTP(true))
}

Transports

Single endpoint, responses in HTTP body. Session via Mcp-Session-Id header.

srv.ListenAndServe(mcpkit.WithStreamableHTTP(true))
HTTP+SSE (MCP 2024-11-05) — legacy

Long-lived SSE stream + POST endpoint. Session tied to SSE connection.

srv.ListenAndServe() // SSE is the default
Both simultaneously
srv.ListenAndServe(mcpkit.WithStreamableHTTP(true), mcpkit.WithSSE(true))
// SSE at /mcp/sse + /mcp/message, Streamable HTTP at /mcp
Transport options
handler := srv.Handler(
    mcpkit.WithPrefix("/custom"),                       // URL prefix (default: /mcp)
    mcpkit.WithPublicURL("https://proxy.example.com"),  // for reverse proxy
    mcpkit.WithMaxSessions(100),                        // limit concurrent sessions
    mcpkit.WithKeepalivePeriod(15 * time.Second),       // SSE keepalive interval
    mcpkit.WithStreamableHTTP(true),                    // enable Streamable HTTP
)

Capabilities

Capability Methods
Tools tools/list, tools/call
Resources resources/list, resources/read, resources/templates/list, resources/subscribe, resources/unsubscribe, notifications/resources/updated
Prompts prompts/list, prompts/get
Logging logging/setLevel, notifications/message via EmitLog()
Progress notifications/progress via EmitProgress() with _meta.progressToken
Completion completion/complete for argument autocompletion
Cancellation notifications/cancelled with context propagation
Pagination Cursor-based pagination for all list methods

Capabilities are auto-advertised in the initialize response when the corresponding handlers are registered. Logging and completions are always advertised.

Resource Subscriptions

Enable clients to subscribe to resource changes and receive push notifications:

srv := mcpkit.NewServer(info, mcpkit.WithSubscriptions())

srv.RegisterResource(mcpkit.ResourceDef{
    URI: "file:///data/config.yaml", Name: "Config",
}, handler)

// When the resource changes, notify all subscribed clients:
srv.NotifyResourceUpdated("file:///data/config.yaml")

Client side:

client.SubscribeResource("file:///data/config.yaml")
// ... receive notifications/resources/updated when resource changes
client.UnsubscribeResource("file:///data/config.yaml")

Protocol Support

  • MCP 2025-11-25 and 2024-11-05 with automatic version negotiation
  • Initialization gating: requests rejected until initialize + notifications/initialized handshake completes
  • Tool error semantics: handler errors → isError: true in result (not JSON-RPC errors)

Testing

make test         # Unit tests (200+ tests)
make test-auth    # Auth sub-module tests
make test-auth-e2e # E2E auth tests (in-process oneauth AS)
make testconf     # MCP conformance suite (requires Node.js)
make testall      # ALL tests + Keycloak + HTML report
make smoke        # Curl-based transport tests (SSE + Streamable HTTP)
make audit        # Security: govulncheck + gosec + gitleaks + race detection
make serve        # Start SSE test server on :8787
make serve-streamable  # Streamable HTTP on :8787

# Keycloak interop tests (optional, requires Docker)
make upkcl                # Start Keycloak
make test-auth-keycloak   # Run Keycloak interop tests
make downkcl              # Stop Keycloak
Conformance Suite

Validated against the official MCP conformance test suite. Current status: 28/30 server scenarios passing, 14/14 auth conformance passing (remaining tracked in conformance/baseline.yml).

bash scripts/conformance-test.sh                    # full suite
bash scripts/conformance-test.sh tools-call-simple-text  # single scenario

When a feature's conformance scenario starts passing, remove it from conformance/baseline.yml — stale entries cause CI failure.

Manual testing
# Start test server (Streamable HTTP)
STREAMABLE=1 go run ./cmd/testserver

# MCP Inspector
npx @modelcontextprotocol/inspector
# Point it at http://localhost:8787/mcp

Stack Dependencies

Core module (github.com/panyam/mcpkit):

  • servicekit v0.0.14 — SSE connection/hub, graceful shutdown, HTTP middleware

Sub-module (github.com/panyam/mcpkit/auth) — separate go.mod:

  • oneauth — JWT/OIDC validation (only pulled in when you import this sub-module)

Documentation

Index

Constants

View Source
const (
	ErrCodeParse          = -32700
	ErrCodeInvalidRequest = -32600
	ErrCodeMethodNotFound = -32601
	ErrCodeInvalidParams  = -32602
	ErrCodeInternal       = -32603

	// ErrCodeServerError is the base code for custom server errors (-32000 to -32099).
	// Use this for application-specific errors that are not covered by standard codes.
	ErrCodeServerError = -32000
)

Standard JSON-RPC 2.0 error codes (https://www.jsonrpc.org/specification#error_object).

Reserved ranges:

-32700           Parse error (invalid JSON)
-32600           Invalid Request (not a valid JSON-RPC request)
-32601           Method not found
-32602           Invalid params
-32603           Internal error
-32000 to -32099 Server error (implementation-defined)
View Source
const ErrCodeCancelled = -32800

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

View Source
const (

	// StreamableHTTPAccept is the required Accept header value for Streamable HTTP requests.
	// Per MCP spec (2025-11-25, Streamable HTTP transport): clients MUST accept both
	// application/json and text/event-stream.
	// https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server
	StreamableHTTPAccept = "application/json, text/event-stream"
)

Variables

This section is empty.

Functions

func EmitLog added in v0.0.4

func EmitLog(ctx context.Context, level LogLevel, logger string, data any)

EmitLog sends a notifications/message to the connected client if the session's log level allows it. Safe to call even if no session context is present (no-op).

level is the severity of the message. logger is an optional logger name (typically the tool or subsystem name). data is the log payload (string, map, etc.).

Usage in a tool handler:

func myHandler(ctx context.Context, req mcpkit.ToolRequest) (mcpkit.ToolResult, error) {
    mcpkit.EmitLog(ctx, mcpkit.LogInfo, "my-tool", "processing started")
    // ... do work ...
    return mcpkit.TextResult("done"), nil
}

func EmitProgress added in v0.0.5

func EmitProgress(ctx context.Context, token any, progress, total float64, message string)

EmitProgress sends a notifications/progress to the connected client. Safe to call even if no session context is present or if token is nil (both are no-ops).

token is the ProgressToken from the ToolRequest — pass req.ProgressToken directly. progress is the current progress value, total is the expected total (0 for indeterminate). message is an optional human-readable status string.

Usage in a tool handler:

func myHandler(ctx context.Context, req mcpkit.ToolRequest) (mcpkit.ToolResult, error) {
    mcpkit.EmitProgress(ctx, req.ProgressToken, 0, 100, "starting")
    // ... do work ...
    mcpkit.EmitProgress(ctx, req.ProgressToken, 50, 100, "halfway")
    // ... more work ...
    mcpkit.EmitProgress(ctx, req.ProgressToken, 100, 100, "done")
    return mcpkit.TextResult("complete"), nil
}

func HasScope added in v0.0.11

func HasScope(ctx context.Context, scope string) bool

HasScope checks if the context's authenticated claims include the given scope. Returns false if no claims are present.

func Notify added in v0.0.4

func Notify(ctx context.Context, method string, params any) bool

Notify sends an arbitrary server-to-client JSON-RPC notification. Returns false if no notification sender is available in the context. This is the low-level API; prefer EmitLog for logging notifications.

func ParseWWWAuthenticate added in v0.0.11

func ParseWWWAuthenticate(header string) (resourceMetadata string, scopes []string, err error)

ParseWWWAuthenticate extracts the resource_metadata URL and scopes from a WWW-Authenticate: Bearer header value. Used by MCP clients to discover the PRM endpoint after receiving a 401, and to parse required scopes from a 403 insufficient_scope response.

Per MCP spec (2025-11-25): clients MUST use resource_metadata from WWW-Authenticate when present.

Types

type AuthError

type AuthError struct {
	Code            int
	Message         string
	WWWAuthenticate string // optional WWW-Authenticate header value
}

AuthError is returned when authentication fails.

func (*AuthError) Error

func (e *AuthError) Error() string

type AuthValidator

type AuthValidator interface {
	Validate(r *http.Request) error
}

AuthValidator validates an HTTP request and returns claims on success.

type CallResult added in v0.0.7

type CallResult struct {
	Raw any
}

CallResult holds the raw result from a JSON-RPC call.

func (*CallResult) JSON added in v0.0.7

func (r *CallResult) JSON() string

JSON returns the result as indented JSON.

func (*CallResult) Unmarshal added in v0.0.7

func (r *CallResult) Unmarshal(v any) error

Unmarshal decodes the result into the given value.

type Claims added in v0.0.11

type Claims struct {
	// Subject is the authenticated principal (user ID or client ID).
	Subject string `json:"sub"`

	// Issuer identifies the authorization server that issued the token.
	Issuer string `json:"iss"`

	// Audience lists the intended recipients of the token (RFC 8707).
	Audience []string `json:"aud"`

	// Scopes lists the granted scopes.
	Scopes []string `json:"scope"`

	// Extra holds additional claims not covered by the standard fields.
	Extra map[string]any `json:"extra,omitempty"`
}

Claims holds the authenticated identity extracted from a validated request. Populated by AuthValidators that also implement ClaimsProvider.

func AuthClaims added in v0.0.11

func AuthClaims(ctx context.Context) *Claims

AuthClaims returns the authenticated identity from the context, or nil if no auth was configured or the validator does not provide claims.

Usage in a tool handler:

func myHandler(ctx context.Context, req mcpkit.ToolRequest) (mcpkit.ToolResult, error) {
    claims := mcpkit.AuthClaims(ctx)
    if claims != nil {
        log.Printf("called by %s", claims.Subject)
    }
    // ...
}

type ClaimsProvider added in v0.0.11

type ClaimsProvider interface {
	Claims(r *http.Request) *Claims
}

ClaimsProvider is an optional interface for AuthValidators that can extract identity claims from a validated request. Called only after Validate succeeds.

Validators that only perform pass/fail checks (like bearerTokenValidator) do not need to implement this interface.

type Client added in v0.0.7

type Client struct {

	// ServerInfo is populated after Connect.
	ServerInfo ServerInfo
	// contains filtered or unexported fields
}

Client is an MCP client that communicates over Streamable HTTP or SSE.

func NewClient added in v0.0.7

func NewClient(url string, info ClientInfo, opts ...ClientOption) *Client

NewClient creates a new MCP client targeting the given server URL. By default uses Streamable HTTP. Use WithSSEClient() for SSE transport. Call Connect() to perform the protocol handshake.

func (*Client) Call added in v0.0.7

func (c *Client) Call(method string, params any) (*CallResult, error)

Call makes a JSON-RPC call and returns the parsed response.

func (*Client) Close added in v0.0.7

func (c *Client) Close() error

Close terminates the client session and transport.

func (*Client) Connect added in v0.0.7

func (c *Client) Connect() error

Connect establishes the transport and performs the MCP initialize handshake.

func (*Client) ListResourceTemplates added in v0.0.7

func (c *Client) ListResourceTemplates() ([]ResourceTemplate, error)

ListResourceTemplates returns all registered resource templates.

func (*Client) ListResources added in v0.0.7

func (c *Client) ListResources() ([]ResourceDef, error)

ListResources returns all registered static resources.

func (*Client) ListTools added in v0.0.7

func (c *Client) ListTools() ([]ToolDef, error)

ListTools returns all registered tool definitions.

func (*Client) ReadResource added in v0.0.7

func (c *Client) ReadResource(uri string) (string, error)

ReadResource reads a resource by URI and returns the first text content.

func (*Client) SessionID added in v0.0.7

func (c *Client) SessionID() string

SessionID returns the current session ID.

func (*Client) SubscribeResource added in v0.0.14

func (c *Client) SubscribeResource(uri string) error

SubscribeResource subscribes to change notifications for a resource URI. The server will send notifications/resources/updated when the resource changes.

func (*Client) ToolCall added in v0.0.7

func (c *Client) ToolCall(name string, args any) (string, error)

ToolCall invokes a tool and returns the first text content.

func (*Client) UnsubscribeResource added in v0.0.14

func (c *Client) UnsubscribeResource(uri string) error

UnsubscribeResource removes a subscription for a resource URI.

type ClientAuthError added in v0.0.11

type ClientAuthError struct {
	// StatusCode is the HTTP status (401 or 403).
	StatusCode int
	// Message describes the failure.
	Message string
	// WWWAuthenticate is the raw WWW-Authenticate header from the server response.
	WWWAuthenticate string
	// RequiredScopes are the scopes parsed from the WWW-Authenticate header (403 only).
	RequiredScopes []string
}

ClientAuthError is returned by the client transport when the server rejects a request with 401 or 403 and the transport has exhausted its retry budget.

func (*ClientAuthError) Error added in v0.0.11

func (e *ClientAuthError) Error() string

type ClientCapabilities

type ClientCapabilities struct {
	Sampling    *struct{} `json:"sampling,omitempty"`
	Roots       *RootsCap `json:"roots,omitempty"`
	Elicitation *struct{} `json:"elicitation,omitempty"`
}

ClientCapabilities describes features the client supports.

type ClientInfo

type ClientInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

ClientInfo identifies the MCP client from the initialize request.

type ClientOption added in v0.0.7

type ClientOption func(*Client)

ClientOption configures a Client.

func WithClientBearerToken added in v0.0.11

func WithClientBearerToken(token string) ClientOption

WithClientBearerToken sets a static bearer token for all client requests.

func WithClientLogging added in v0.0.12

func WithClientLogging(logger *log.Logger) ClientOption

WithClientLogging enables debug logging of all client transport operations. Every connect, call, notify, and close is logged with method name, latency, and error details. Pass nil to use the default logger.

Example:

client := mcpkit.NewClient(url, info,
    mcpkit.WithClientLogging(log.Default()),
)

func WithInMemoryServer added in v0.0.12

func WithInMemoryServer(srv *Server) ClientOption

WithInMemoryServer creates a client that talks to the given server directly in-memory, bypassing HTTP transport entirely.

Example:

srv := mcpkit.NewServer(mcpkit.ServerInfo{Name: "test", Version: "1.0"})
srv.RegisterTool(def, handler)
client := mcpkit.NewClient("memory://", info, mcpkit.WithInMemoryServer(srv))
client.Connect()
result, _ := client.ToolCall("my-tool", args)

func WithMaxRetries added in v0.0.12

func WithMaxRetries(n int) ClientOption

WithMaxRetries sets the maximum number of reconnection attempts on transient transport failure. Default 0 (reconnection disabled). Each retry includes a full reconnect + initialize handshake.

Example:

client := mcpkit.NewClient(url, info,
    mcpkit.WithMaxRetries(3),
    mcpkit.WithReconnectBackoff(time.Second),
)

func WithNotificationHandler added in v0.0.14

func WithNotificationHandler(fn func(method string, params any)) ClientOption

WithNotificationHandler sets a callback for server-to-client notifications received by the in-memory transport. Use in tests to verify notification delivery (e.g., notifications/resources/updated from resource subscriptions).

func WithReconnectBackoff added in v0.0.12

func WithReconnectBackoff(d time.Duration) ClientOption

WithReconnectBackoff sets the base delay for exponential backoff between reconnection attempts. Default 1s. Actual delay is base * 2^attempt + jitter.

func WithSSEClient added in v0.0.7

func WithSSEClient() ClientOption

WithSSEClient configures the client to use SSE transport instead of Streamable HTTP. The URL should point to the SSE endpoint (e.g., "http://localhost:8787/mcp/sse").

func WithTokenSource added in v0.0.11

func WithTokenSource(ts TokenSource) ClientOption

WithTokenSource sets a dynamic token source for all client requests. Use this for OAuth flows where tokens are refreshed automatically.

type CompletionArgument added in v0.0.5

type CompletionArgument struct {
	// Name is the argument name being completed.
	Name string `json:"name"`

	// Value is the partial input the user has typed so far.
	Value string `json:"value"`
}

CompletionArgument describes the argument being completed and the partial input so far.

type CompletionHandler added in v0.0.5

type CompletionHandler func(ctx context.Context, ref CompletionRef, arg CompletionArgument) (CompletionResult, error)

CompletionHandler provides autocompletion suggestions for a specific reference. ref identifies the prompt or resource being completed, arg contains the argument name and partial value. Return matching suggestions.

type CompletionRef added in v0.0.5

type CompletionRef struct {
	// Type is "ref/prompt" for prompt argument completion or "ref/resource" for resource URI completion.
	Type string `json:"type"`

	// Name is the prompt name (when Type is "ref/prompt").
	Name string `json:"name,omitempty"`

	// URI is the resource URI template (when Type is "ref/resource").
	URI string `json:"uri,omitempty"`
}

CompletionRef identifies what is being completed — a prompt argument or resource URI.

type CompletionResult added in v0.0.5

type CompletionResult struct {
	// Values is the list of completion suggestions.
	Values []string `json:"values"`

	// Total is the total number of available completions (may be larger than len(Values)).
	Total int `json:"total,omitempty"`

	// HasMore indicates there are additional completions beyond what was returned.
	HasMore bool `json:"hasMore"`
}

CompletionResult is the server's response with completion suggestions.

type Content

type Content struct {
	Type     string           `json:"type"`
	Text     string           `json:"text,omitempty"`
	MimeType string           `json:"mimeType,omitempty"`
	Data     string           `json:"data,omitempty"`
	Resource *ResourceContent `json:"resource,omitempty"`
}

Content is a single content item in a tool result. Supports text, image, audio, and embedded resource types per MCP spec.

type Dispatcher

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

Dispatcher routes JSON-RPC requests to the appropriate handler.

func NewDispatcher

func NewDispatcher(info ServerInfo) *Dispatcher

NewDispatcher creates a dispatcher with the given server identity.

func (*Dispatcher) Close added in v0.0.14

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 *Request) *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 added in v0.0.5

func (d *Dispatcher) RegisterCompletion(refType, name string, handler 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 added in v0.0.3

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

RegisterPrompt adds a prompt to the dispatcher.

func (*Dispatcher) RegisterResource added in v0.0.3

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

RegisterResource adds a resource to the dispatcher.

func (*Dispatcher) RegisterResourceTemplate added in v0.0.3

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

RegisterResourceTemplate adds a URI template resource to the dispatcher.

func (*Dispatcher) RegisterTool

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

RegisterTool adds a tool to the dispatcher.

type Error

type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

Error is a JSON-RPC 2.0 error object.

type Extension added in v0.0.11

type Extension struct {
	// ID is the extension identifier (e.g., "io.mcpkit/auth").
	ID string `json:"id"`

	// SpecVersion is the version of the spec this extension implements.
	SpecVersion string `json:"specVersion"`

	// Stability indicates the maturity of this extension.
	Stability Stability `json:"stability"`

	// Config holds extension-specific configuration, if any.
	Config map[string]any `json:"config,omitempty"`
}

Extension describes a protocol extension with maturity metadata. Extensions are advertised in the initialize response under capabilities.extensions.

type ExtensionProvider added in v0.0.11

type ExtensionProvider interface {
	Extension() Extension
}

ExtensionProvider is implemented by sub-modules to declare their extension. This is how mcpkit/auth registers itself without the core module knowing about auth.

type LogLevel added in v0.0.4

type LogLevel int

LogLevel represents MCP log severity levels (syslog-based, ascending severity). Used with logging/setLevel to control the minimum level of log notifications sent to the client, and with EmitLog to specify the severity of a message.

const (
	LogDebug     LogLevel = iota // debug: detailed debugging information
	LogInfo                      // info: general informational messages
	LogNotice                    // notice: normal but significant events
	LogWarning                   // warning: warning conditions
	LogError                     // error: error conditions
	LogCritical                  // critical: critical conditions
	LogAlert                     // alert: action must be taken immediately
	LogEmergency                 // emergency: system is unusable
)

func ParseLogLevel added in v0.0.4

func ParseLogLevel(s string) (LogLevel, bool)

ParseLogLevel converts a string to a LogLevel. Returns the level and true on success, or (LogDebug, false) for unknown strings.

func (LogLevel) String added in v0.0.4

func (l LogLevel) String() string

String returns the MCP wire name for the log level.

type LogMessage added in v0.0.4

type LogMessage struct {
	Level  string `json:"level"`
	Logger string `json:"logger,omitempty"`
	Data   any    `json:"data"`
}

LogMessage is the params payload for a notifications/message notification.

type Middleware added in v0.0.12

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

Middleware intercepts a JSON-RPC request. Call next to continue the chain, or return a *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 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 added in v0.0.12

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 added in v0.0.12

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

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

type NotifyFunc added in v0.0.4

type NotifyFunc func(method string, params any)

NotifyFunc sends a server-to-client JSON-RPC notification. method is the notification method (e.g., "notifications/message"). params will be JSON-marshaled as the notification's params field. This type is reusable for all server→client notifications (logging, progress, etc.).

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 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 WithExtension added in v0.0.11

func WithExtension(ext 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 added in v0.0.12

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 added in v0.0.13

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 added in v0.0.14

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 ProgressNotification added in v0.0.5

type ProgressNotification struct {
	// ProgressToken is the token from the request's _meta.progressToken field.
	// It links this notification to the original request.
	ProgressToken any `json:"progressToken"`

	// Progress is the current progress value (e.g., bytes processed, items completed).
	Progress float64 `json:"progress"`

	// Total is the expected total value. Zero means indeterminate progress.
	Total float64 `json:"total,omitempty"`

	// Message is an optional human-readable status message.
	Message string `json:"message,omitempty"`
}

ProgressNotification is the params payload for a notifications/progress notification. Servers send this during long-running operations to report progress to the client. The ProgressToken must match the token from the client's original request _meta.

type PromptArgument added in v0.0.3

type PromptArgument struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Required    bool   `json:"required,omitempty"`
}

PromptArgument describes a single argument to a prompt.

type PromptDef added in v0.0.3

type PromptDef struct {
	// Name is the prompt identifier used in prompts/get.
	Name string `json:"name"`

	// Title is an optional display title.
	Title string `json:"title,omitempty"`

	// Description explains what this prompt does.
	Description string `json:"description,omitempty"`

	// Arguments defines the parameters this prompt accepts.
	Arguments []PromptArgument `json:"arguments,omitempty"`

	// Annotations holds optional metadata for this prompt.
	Annotations map[string]any `json:"annotations,omitempty"`
}

PromptDef describes a prompt exposed via MCP.

type PromptHandler added in v0.0.3

type PromptHandler func(ctx context.Context, req PromptRequest) (PromptResult, error)

PromptHandler generates prompt messages, optionally using arguments.

type PromptMessage added in v0.0.3

type PromptMessage struct {
	Role    string  `json:"role"`
	Content Content `json:"content"` // reuses Content from tool.go
}

PromptMessage is a single message in a prompt result.

type PromptRequest added in v0.0.3

type PromptRequest struct {
	Name      string
	Arguments map[string]string
}

PromptRequest is the validated input passed to a PromptHandler.

type PromptResult added in v0.0.3

type PromptResult struct {
	Description string          `json:"description,omitempty"`
	Messages    []PromptMessage `json:"messages"`
}

PromptResult is the response from a prompt handler.

type Request

type Request struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      json.RawMessage `json:"id"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
}

Request is a JSON-RPC 2.0 request envelope.

func (*Request) IsNotification

func (r *Request) IsNotification() bool

IsNotification returns true if this request has no ID (JSON-RPC notification).

type ResourceContent

type ResourceContent struct {
	URI      string `json:"uri"`
	MimeType string `json:"mimeType,omitempty"`
	Text     string `json:"text,omitempty"`
	Blob     string `json:"blob,omitempty"`
}

ResourceContent is an embedded resource reference in a tool result.

type ResourceDef added in v0.0.3

type ResourceDef struct {
	// URI uniquely identifies this resource.
	URI string `json:"uri"`

	// Name is a human-readable short name.
	Name string `json:"name"`

	// Title is an optional display title.
	Title string `json:"title,omitempty"`

	// Description explains what this resource provides.
	Description string `json:"description,omitempty"`

	// MimeType is the MIME type of the resource content.
	MimeType string `json:"mimeType,omitempty"`

	// Annotations holds optional metadata for this resource.
	Annotations map[string]any `json:"annotations,omitempty"`
}

ResourceDef describes a resource exposed via MCP.

type ResourceHandler added in v0.0.3

type ResourceHandler func(ctx context.Context, req ResourceRequest) (ResourceResult, error)

ResourceHandler reads a resource by URI.

type ResourceReadContent added in v0.0.3

type ResourceReadContent struct {
	URI      string `json:"uri"`
	MimeType string `json:"mimeType,omitempty"`
	Text     string `json:"text,omitempty"`
	Blob     string `json:"blob,omitempty"`
}

ResourceReadContent is a single content item returned by resources/read. Either Text or Blob is set, not both.

type ResourceRequest added in v0.0.3

type ResourceRequest struct {
	URI string
}

ResourceRequest is the validated input passed to a ResourceHandler.

type ResourceResult added in v0.0.3

type ResourceResult struct {
	Contents []ResourceReadContent `json:"contents"`
}

ResourceResult is the response from a resource handler.

type ResourceTemplate added in v0.0.3

type ResourceTemplate struct {
	// URITemplate is an RFC 6570 URI template (e.g., "file:///{path}").
	URITemplate string `json:"uriTemplate"`

	// Name is a human-readable short name.
	Name string `json:"name"`

	// Title is an optional display title.
	Title string `json:"title,omitempty"`

	// Description explains what this template provides.
	Description string `json:"description,omitempty"`

	// MimeType is the default MIME type for resources matching this template.
	MimeType string `json:"mimeType,omitempty"`

	// Annotations holds optional metadata for this template.
	Annotations map[string]any `json:"annotations,omitempty"`
}

ResourceTemplate describes a parameterized resource URI template.

type ResourceUpdatedNotification added in v0.0.14

type ResourceUpdatedNotification struct {
	URI string `json:"uri"`
}

ResourceUpdatedNotification is the params payload for notifications/resources/updated. Sent by the server to subscribed clients when a resource's content has changed.

type Response

type Response struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      json.RawMessage `json:"id"`
	Result  json.RawMessage `json:"result,omitempty"`
	Error   *Error          `json:"error,omitempty"`
}

Response is a JSON-RPC 2.0 response.

func NewErrorResponse

func NewErrorResponse(id json.RawMessage, code int, message string) *Response

NewErrorResponse creates an error response for the given request ID.

func NewErrorResponseWithData

func NewErrorResponseWithData(id json.RawMessage, code int, message string, data any) *Response

NewErrorResponseWithData creates an error response with additional structured data. Used for protocol errors that carry machine-readable context (e.g., supported versions).

func NewResponse

func NewResponse(id json.RawMessage, result any) *Response

NewResponse creates a success response for the given request ID.

type RootsCap

type RootsCap struct {
	ListChanged bool `json:"listChanged,omitempty"`
}

RootsCap describes the client's roots capability.

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 ScopeAwareTokenSource added in v0.0.11

type ScopeAwareTokenSource interface {
	TokenSource
	// TokenForScopes invalidates the cached token and triggers a new
	// authorization flow with the given scopes merged into the existing set.
	TokenForScopes(scopes []string) (string, error)
}

ScopeAwareTokenSource extends TokenSource with scope step-up capability. When the server returns 403 with required scopes in the WWW-Authenticate header, the client transport calls TokenForScopes to re-authenticate with broader permissions.

Implementations that support interactive re-auth (like OAuthTokenSource) should implement this interface. Static tokens and implementations that cannot acquire new scopes need not implement it — the transport will return a ClientAuthError instead of retrying.

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 ServerInfo, opts ...Option) *Server

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

func (*Server) CheckAuth

func (s *Server) CheckAuth(r *http.Request) (*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 added in v0.0.12

func (s *Server) CloseAllSessions()

CloseAllSessions terminates all active sessions across all transports.

func (*Server) CloseSession added in v0.0.12

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 *Request) *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 added in v0.0.14

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) RegisterCompletion added in v0.0.5

func (s *Server) RegisterCompletion(refType, name string, handler 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 added in v0.0.11

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

RegisterExperimentalPrompt registers a prompt marked as experimental via annotations.

func (*Server) RegisterExperimentalResource added in v0.0.11

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

RegisterExperimentalResource registers a resource marked as experimental via annotations.

func (*Server) RegisterExperimentalTool added in v0.0.11

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

RegisterExperimentalTool registers a tool marked as experimental via annotations.

func (*Server) RegisterPrompt added in v0.0.3

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

RegisterPrompt adds a prompt to the server.

func (*Server) RegisterResource added in v0.0.3

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

RegisterResource adds a resource to the server.

func (*Server) RegisterResourceTemplate added in v0.0.3

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

RegisterResourceTemplate adds a URI template resource to the server.

func (*Server) RegisterTool

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

RegisterTool adds a tool to the server.

func (*Server) Run added in v0.0.12

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")

type ServerInfo

type ServerInfo struct {
	Name         string `json:"name"`
	Version      string `json:"version"`
	Title        string `json:"title,omitempty"`
	Description  string `json:"description,omitempty"`
	Instructions string `json:"instructions,omitempty"`
	WebsiteURL   string `json:"websiteUrl,omitempty"`
}

ServerInfo identifies this MCP server in the initialize response.

type Stability added in v0.0.11

type Stability string

Stability represents the maturity level of an extension.

const (
	// Experimental indicates the extension is in development and may change.
	Experimental Stability = "experimental"
	// Stable indicates the extension is production-ready.
	Stable Stability = "stable"
	// Deprecated indicates the extension will be removed in a future version.
	Deprecated Stability = "deprecated"
)

type TemplateHandler added in v0.0.3

type TemplateHandler func(ctx context.Context, uri string, params map[string]string) (ResourceResult, error)

TemplateHandler reads a resource matched by a URI template. The uri parameter is the full resolved URI, params contains the extracted template variables.

type TokenSource added in v0.0.11

type TokenSource interface {
	// Token returns a valid access token, refreshing if necessary.
	Token() (string, error)
}

TokenSource provides access tokens for the MCP client. Simple implementations return a static token; OAuth implementations handle the full flow including discovery, browser auth, and refresh.

type ToolDef

type ToolDef struct {
	// Name is the tool identifier used in tools/call.
	Name string `json:"name"`

	// Description is a human-readable summary of what the tool does.
	Description string `json:"description"`

	// InputSchema is the JSON Schema for the tool's arguments.
	// Typically a map[string]any with "type": "object", "properties": {...}, "required": [...].
	InputSchema any `json:"inputSchema"`

	// OutputSchema is an optional JSON Schema for the tool's structuredContent output.
	// When present, the tool SHOULD return StructuredContent matching this schema.
	// Per MCP spec: enables clients to validate and process tool output programmatically.
	OutputSchema any `json:"outputSchema,omitempty"`

	// Annotations holds optional metadata for this tool.
	// Convention: {"experimental": true} marks experimental tools.
	Annotations map[string]any `json:"annotations,omitempty"`
}

ToolDef describes a tool exposed via MCP.

type ToolHandler

type ToolHandler func(ctx context.Context, req ToolRequest) (ToolResult, error)

ToolHandler is the function signature for tool implementations.

type ToolRequest

type ToolRequest struct {
	// Name of the tool being called.
	Name string

	// Arguments is the raw JSON arguments from the tools/call params.
	Arguments json.RawMessage

	// RequestID is the JSON-RPC request ID.
	RequestID json.RawMessage

	// ProgressToken is the token from the request's _meta.progressToken field.
	// Nil if the client did not request progress reporting. Pass this to
	// EmitProgress to send notifications/progress notifications.
	ProgressToken any
}

ToolRequest is the validated input passed to a ToolHandler.

func (*ToolRequest) Bind

func (r *ToolRequest) Bind(v any) error

Bind unmarshals the tool arguments into the provided struct.

type ToolResult

type ToolResult struct {
	// Content is the list of content items to return.
	Content []Content `json:"content"`

	// IsError indicates the tool execution failed (but the JSON-RPC call itself succeeded).
	IsError bool `json:"isError,omitempty"`

	// StructuredContent holds optional structured data for the tool result.
	// When the tool has an OutputSchema, this field carries typed data matching
	// that schema. On error (IsError=true), it can carry structured error details.
	// Per MCP spec: "If outputSchema is present, structuredContent SHOULD be included."
	StructuredContent any `json:"structuredContent,omitempty"`
}

ToolResult is the response from a tool handler.

func ErrorResult

func ErrorResult(text string) ToolResult

ErrorResult creates a ToolResult marked as an error with the given message.

func StructuredError added in v0.0.12

func StructuredError(text string, data any) ToolResult

StructuredError creates a ToolResult marked as an error with both text and structured error data. Use this to return machine-readable error details alongside a human-readable error message.

func StructuredResult added in v0.0.12

func StructuredResult(text string, data any) ToolResult

StructuredResult creates a ToolResult with both text content and structured data. Use this when the tool has an OutputSchema — structuredContent carries typed data matching the schema, while content provides a human-readable summary.

func TextResult

func TextResult(text string) ToolResult

TextResult creates a ToolResult with a single text content item.

type TransportOption

type TransportOption func(*transportConfig)

TransportOption configures the HTTP transports.

func WithAllowedOrigins added in v0.0.6

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 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 WithStateless added in v0.0.12

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).

Directories

Path Synopsis
cmd
testclient command
Command testclient is the MCP auth conformance test client.
Command testclient is the MCP auth conformance test client.
testserver command
testserver is a minimal MCP server for manual testing and conformance validation.
testserver is a minimal MCP server for manual testing and conformance validation.
examples
common module
experimental
ext/events module
ext/protogen module
ext
auth module
otel module
protogen module
tasks module
ui module
Package testutil provides test helpers for MCP servers built with mcpkit.
Package testutil provides test helpers for MCP servers built with mcpkit.

Jump to

Keyboard shortcuts

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