mcp

package
v0.1.0-beta.8 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: Apache-2.0 Imports: 46 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ReplicaPolicyRoundRobin       = "round-robin"
	ReplicaPolicyLeastConnections = "least-connections"
)

Dispatch policies for a ReplicaSet.

View Source
const (
	// DefaultRequestTimeout is the timeout for individual MCP JSON-RPC requests.
	DefaultRequestTimeout = 30 * time.Second

	// DefaultReadyPollInterval is the interval between readiness checks.
	DefaultReadyPollInterval = 500 * time.Millisecond

	// DefaultReadyTimeout is the overall timeout for server readiness.
	DefaultReadyTimeout = 30 * time.Second
)

Default timeouts for MCP transport clients.

View Source
const DefaultAutoscalerInterval = 10 * time.Second

DefaultAutoscalerInterval is the tick cadence Gateway.StartAutoscaler uses when callers pass 0. Kept short enough that reap/spawn latencies are observable; the per-direction cooldowns (ScaleUpAfter / ScaleDownAfter) gate actual actions so a 10s tick does not cause flapping.

View Source
const DefaultCodeModeTimeout = 30 * time.Second

DefaultCodeModeTimeout is the default code mode execution timeout.

View Source
const DefaultFetchMaxResponseBytes = 1 * 1024 * 1024

DefaultFetchMaxResponseBytes is the default response size cap (1MB).

View Source
const DefaultFetchRequestTimeout = 10 * time.Second

DefaultFetchRequestTimeout is the per-request timeout for fetch calls.

View Source
const DefaultHealthCheckInterval = 30 * time.Second

DefaultHealthCheckInterval is the default interval between health checks.

View Source
const DefaultPingTimeout = 5 * time.Second

DefaultPingTimeout is the timeout for health check pings.

View Source
const MCPProtocolVersion = "2025-11-25"

MCPProtocolVersion is the MCP protocol version supported by this implementation.

View Source
const MaxCodeSize = 64 * 1024

MaxCodeSize is the maximum allowed code input size (64KB).

View Source
const MaxRequestBodySize = 1 * 1024 * 1024

MaxRequestBodySize is the maximum allowed size for incoming JSON-RPC request bodies (1MB).

View Source
const MetaToolExecute = "execute"

MetaToolExecute is the name of the execute meta-tool.

View Source
const MetaToolSearch = "search"

MetaToolSearch is the name of the search meta-tool.

View Source
const ToolNameDelimiter = "__"

ToolNameDelimiter is the separator between agent name and tool name in prefixed tool names. Format: "agentname__toolname" Uses double underscore to be compatible with Claude Desktop's tool name validation: ^[a-zA-Z0-9_-]{1,64}$

Variables

View Source
var ErrNoHealthyReplicas = errors.New("no healthy replicas")

ErrNoHealthyReplicas is returned by ReplicaSet.Pick when every replica in the set is marked unhealthy.

View Source
var ErrReadyTimeout = errors.New("ready timeout")

ErrReadyTimeout indicates that an HTTP/SSE MCP server did not become reachable within the configured readiness window. Callers can use errors.Is to distinguish this from context cancellation or other registration errors.

Functions

func ParsePrefixedTool

func ParsePrefixedTool(prefixed string) (agentName, toolName string, err error)

ParsePrefixedTool parses a prefixed tool name into agent and tool names.

func PrefixTool

func PrefixTool(agentName, toolName string) string

PrefixTool creates a prefixed tool name: "agent__tool"

func Transpile

func Transpile(code string) (string, error)

Transpile converts modern JavaScript (ES2020+) to ES2015 compatible code that can be executed by the goja runtime. It handles async/await, arrow functions, destructuring, template literals, and other modern syntax.

Types

type AgentClient

type AgentClient interface {
	Name() string
	Initialize(ctx context.Context) error
	RefreshTools(ctx context.Context) error
	Tools() []Tool
	CallTool(ctx context.Context, name string, arguments map[string]any) (*ToolCallResult, error)
	IsInitialized() bool
	ServerInfo() ServerInfo
}

AgentClient is the interface for communicating with MCP agents.

type AutoscalePolicy

type AutoscalePolicy struct {
	Min            int           // Minimum healthy replica count (>= 0; 0 only when IdleToZero).
	Max            int           // Upper bound on replica count (>= 1).
	TargetInFlight int           // Per-replica in-flight request the scaler holds the median at or below.
	ScaleUpAfter   time.Duration // Window median must exceed target for at least this long.
	ScaleDownAfter time.Duration // Window median must be below the target for at least this long.
	WarmPool       int           // Extra replicas kept above the load-derived target.
	IdleToZero     bool          // When true, Min may be 0; zero-scale reaps happen after ScaleDownAfter of no traffic.
}

AutoscalePolicy controls reactive autoscaling for a single ReplicaSet. Values are a snapshot; use Autoscaler.UpdatePolicy to swap in a new one without restarting the scaler loop.

type AutoscaleStatus

type AutoscaleStatus struct {
	Min             int        `json:"min"`
	Max             int        `json:"max"`
	Current         int        `json:"current"`
	Target          int        `json:"target"`
	TargetInFlight  int        `json:"targetInFlight"`
	MedianInFlight  int64      `json:"medianInFlight"`
	LastScaleUpAt   *time.Time `json:"lastScaleUpAt,omitempty"`
	LastScaleDownAt *time.Time `json:"lastScaleDownAt,omitempty"`
	LastDecision    string     `json:"lastDecision"`
	WarmPool        int        `json:"warmPool,omitempty"`
	IdleToZero      bool       `json:"idleToZero,omitempty"`
}

AutoscaleStatus is the serialisable snapshot included in MCPServerStatus when a server has autoscale configured. Fields mirror the spec in new_feature.md § "Observability surface".

type Autoscaler

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

Autoscaler runs the scale-up / scale-down decision loop for one ReplicaSet. The ReplicaSet and Spawner are both injected so the decision logic can be tested against in-memory fakes.

func NewAutoscaler

func NewAutoscaler(name string, set *ReplicaSet, spawner Spawner, policy AutoscalePolicy, logger *slog.Logger) *Autoscaler

NewAutoscaler builds an Autoscaler bound to a ReplicaSet and Spawner. The policy is applied immediately; subsequent UpdatePolicy calls swap it atomically. The initial rolling window is max(30s, ScaleUpAfter/2).

func (*Autoscaler) Name

func (a *Autoscaler) Name() string

Name returns the logical server name this scaler manages.

func (*Autoscaler) Policy

func (a *Autoscaler) Policy() AutoscalePolicy

Policy returns the current policy snapshot.

func (*Autoscaler) Set

func (a *Autoscaler) Set() *ReplicaSet

Set returns the managed ReplicaSet.

func (*Autoscaler) Status

func (a *Autoscaler) Status() AutoscaleStatus

Status returns a snapshot of scaler state for the /api/stack/health payload. Returns zeroed timestamps until the corresponding action has occurred.

func (*Autoscaler) Tick

func (a *Autoscaler) Tick(ctx context.Context, now time.Time) (Decision, error)

Tick runs one evaluation cycle. Safe to call concurrently with tool dispatch. Returns the decision and any spawn/reap error. Errors are also logged at WARN so operators see them in the structured log stream.

func (*Autoscaler) TriggerColdStart

func (a *Autoscaler) TriggerColdStart(ctx context.Context) error

TriggerColdStart spawns the first replica synchronously. Used by HandleToolsCall when a tool call arrives while the set is at zero replicas under an idle-to-zero policy. Returns nil once at least one replica has been added (including concurrently by another caller that won the race). Holds a.spawnMu so a racing periodic Tick cannot spawn in parallel.

func (*Autoscaler) UpdatePolicy

func (a *Autoscaler) UpdatePolicy(p AutoscalePolicy)

UpdatePolicy swaps the active policy atomically and resizes the rolling window to match the new ScaleUpAfter. Called by the reload handler on policy-only changes so the next tick applies the new shape.

type Capabilities

type Capabilities struct {
	Tools     *ToolsCapability     `json:"tools,omitempty"`
	Resources *ResourcesCapability `json:"resources,omitempty"`
	Prompts   *PromptsCapability   `json:"prompts,omitempty"`
}

Capabilities describes what the server/client can do.

type Client

type Client struct {
	RPCClient
	// contains filtered or unexported fields
}

Client communicates with a downstream MCP server.

func NewClient

func NewClient(name, endpoint string) *Client

NewClient creates a new MCP client for a downstream agent.

func (*Client) Endpoint

func (c *Client) Endpoint() string

Endpoint returns the agent endpoint.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping checks if the agent is reachable.

func (*Client) SetPingTimeout

func (c *Client) SetPingTimeout(d time.Duration)

SetPingTimeout overrides the per-ping deadline used by Ping. Zero restores the default (DefaultPingTimeout).

type ClientBase

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

ClientBase provides shared state and accessor methods for all AgentClient implementations. Embed this struct to get Tools(), IsInitialized(), ServerInfo(), and SetToolWhitelist().

The embedded tool list stores every tool the downstream server advertises (post include/exclude for OpenAPI, raw otherwise). The whitelist filter is applied at read time by Tools() so operators can widen the whitelist beyond the currently-exposed subset without losing the superset.

func (*ClientBase) AllTools

func (b *ClientBase) AllTools() []Tool

AllTools returns every tool the downstream server advertises, ignoring any configured whitelist. Used by the management UI so operators can see the full selectable set regardless of the currently-applied curation.

func (*ClientBase) IsInitialized

func (b *ClientBase) IsInitialized() bool

IsInitialized returns whether the client has been initialized.

func (*ClientBase) ServerInfo

func (b *ClientBase) ServerInfo() ServerInfo

ServerInfo returns the server information.

func (*ClientBase) SetInitialized

func (b *ClientBase) SetInitialized(info ServerInfo)

SetInitialized marks the client as initialized with the given server info.

func (*ClientBase) SetToolWhitelist

func (b *ClientBase) SetToolWhitelist(tools []string)

SetToolWhitelist sets the list of allowed tool names. Only tools in this list will be returned by Tools() and RefreshTools(). An empty or nil list means all tools are allowed.

func (*ClientBase) SetTools

func (b *ClientBase) SetTools(tools []Tool)

SetTools updates the cached tools. The full set is retained; the whitelist filter is applied on read by Tools().

func (*ClientBase) Tools

func (b *ClientBase) Tools() []Tool

Tools returns the cached tool list filtered by the whitelist, if any. This is what the router exposes to LLM clients.

type ClientInfo

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

ClientInfo contains information about the MCP client.

type CodeMode

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

CodeMode orchestrates search and execute operations for code mode. When active, it replaces individual tool definitions with two meta-tools (search and execute) that allow LLM agents to discover and call tools via JavaScript code in a sandboxed goja runtime.

func NewCodeMode

func NewCodeMode(timeout time.Duration) *CodeMode

NewCodeMode creates a new CodeMode instance with the given execution timeout.

func (*CodeMode) HandleCall

func (cm *CodeMode) HandleCall(ctx context.Context, params ToolCallParams, caller ToolCaller, allTools []Tool) (*ToolCallResult, error)

HandleCall handles a code mode tool call with the full tool set.

func (*CodeMode) HandleCallWithScope

func (cm *CodeMode) HandleCallWithScope(ctx context.Context, params ToolCallParams, caller ToolCaller, allowedTools []Tool) (*ToolCallResult, error)

HandleCallWithScope handles a code mode tool call with a scoped tool set. The allowedTools parameter controls which tools are available in the sandbox.

func (*CodeMode) IsMetaTool

func (cm *CodeMode) IsMetaTool(name string) bool

IsMetaTool returns true if the tool name is a code mode meta-tool.

func (*CodeMode) SetLogger

func (cm *CodeMode) SetLogger(logger *slog.Logger)

SetLogger sets the logger for code mode operations.

func (*CodeMode) ToolsList

func (cm *CodeMode) ToolsList() *ToolsListResult

ToolsList returns the two meta-tools (search and execute).

type Content

type Content struct {
	Type string `json:"type"`
	Text string `json:"text,omitempty"`
}

Content represents content in a tool response.

func NewTextContent

func NewTextContent(text string) Content

NewTextContent creates a text content item.

type Decision

type Decision int

Decision is the coarse outcome of a scaler tick.

const (
	DecisionNoop      Decision = iota // No action taken (includes cooldown-gated)
	DecisionScaleUp                   // Spawned one or more replicas this tick
	DecisionScaleDown                 // Reaped one replica this tick
)

func (Decision) String

func (d Decision) String() string

String returns the log-friendly label for a decision.

type ExecuteResult

type ExecuteResult struct {
	Value   string   // Return value (JSON-encoded)
	Console []string // Captured console.log/warn/error output
}

ExecuteResult contains the output of a sandbox execution.

type FetchConfig

type FetchConfig struct {
	// HTTPSOnly rejects plain http:// URLs when true (default: true).
	HTTPSOnly bool
	// MaxResponseBytes caps the response body size. Default: 1MB.
	MaxResponseBytes int64
	// RequestTimeout is the per-request timeout. Default: 10s.
	RequestTimeout time.Duration
	// AllowPrivateNetworks disables the SSRF IP blocklist. For testing only.
	AllowPrivateNetworks bool
}

FetchConfig holds operator-configurable settings for the sandboxed fetch client.

func DefaultFetchConfig

func DefaultFetchConfig() FetchConfig

DefaultFetchConfig returns a FetchConfig with secure defaults.

type FormatSavingsRecorder

type FormatSavingsRecorder interface {
	// RecordFormatSavings records token counts before and after format conversion.
	// originalTokens is the token count of the original JSON content.
	// formattedTokens is the token count of the converted content (TOON/CSV).
	RecordFormatSavings(serverName string, originalTokens, formattedTokens int)
}

FormatSavingsRecorder receives format savings observations. Used by the gateway to report token savings from format conversion without coupling to the metrics package directly. Normal token usage tracking is handled separately by the ToolCallObserver.

type Gateway

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

Gateway aggregates multiple MCP servers into a single endpoint.

func NewGateway

func NewGateway() *Gateway

NewGateway creates a new MCP gateway.

func (*Gateway) Autoscalers

func (g *Gateway) Autoscalers() []*Autoscaler

Autoscalers returns a snapshot slice of every registered autoscaler, sorted by server name for deterministic iteration in the tick loop.

func (*Gateway) BuildAgentClient

func (g *Gateway) BuildAgentClient(ctx context.Context, cfg MCPServerConfig) (AgentClient, error)

BuildAgentClient creates, connects, and initializes an AgentClient from a single MCPServerConfig. It does NOT touch serverMeta, pins, health, or the router — callers compose that separately. Exported so Spawner implementations in pkg/controller can reuse the transport switch rather than duplicating it.

func (*Gateway) CallTool

func (g *Gateway) CallTool(ctx context.Context, name string, arguments map[string]any) (*ToolCallResult, error)

CallTool implements the ToolCaller interface, allowing components to call tools through the gateway without a direct reference to the router.

func (*Gateway) Close

func (g *Gateway) Close()

Close stops the cleanup goroutine and closes all agent client connections.

func (*Gateway) CodeModeStatus

func (g *Gateway) CodeModeStatus() string

CodeModeStatus returns the code mode status string ("off" or "on").

func (*Gateway) GetAutoscaler

func (g *Gateway) GetAutoscaler(serverName string) *Autoscaler

GetAutoscaler returns the autoscaler registered for serverName, or nil if the server is not autoscaled.

func (*Gateway) GetHealthStatus

func (g *Gateway) GetHealthStatus(name string) *HealthStatus

GetHealthStatus returns the health status for a named MCP server. Returns nil if no health data is available.

func (*Gateway) HandleInitialize

func (g *Gateway) HandleInitialize(params InitializeParams) (*InitializeResult, *Session, error)

HandleInitialize handles the initialize request. It creates a new session and returns both the result and the session so callers can use the session ID.

func (*Gateway) HandlePromptsGet

func (g *Gateway) HandlePromptsGet(params PromptsGetParams) (*PromptsGetResult, error)

HandlePromptsGet returns a specific prompt with argument substitution.

func (*Gateway) HandlePromptsList

func (g *Gateway) HandlePromptsList() (*PromptsListResult, error)

HandlePromptsList returns all active prompts as MCP Prompts.

func (*Gateway) HandleResourcesList

func (g *Gateway) HandleResourcesList() (*ResourcesListResult, error)

HandleResourcesList returns prompts as MCP Resources.

func (*Gateway) HandleResourcesRead

func (g *Gateway) HandleResourcesRead(params ResourcesReadParams) (*ResourcesReadResult, error)

HandleResourcesRead returns the content of a prompt resource.

func (*Gateway) HandleToolsCall

func (g *Gateway) HandleToolsCall(ctx context.Context, params ToolCallParams) (*ToolCallResult, error)

HandleToolsCall routes a tool call to the appropriate MCP server. When code mode is active and the tool is a meta-tool, delegates to code mode.

func (*Gateway) HandleToolsList

func (g *Gateway) HandleToolsList() (*ToolsListResult, error)

HandleToolsList returns all aggregated tools. When code mode is active, returns the two meta-tools instead.

func (*Gateway) RefreshAllTools

func (g *Gateway) RefreshAllTools(ctx context.Context) error

RefreshAllTools refreshes tools from all registered MCP servers.

func (*Gateway) RegisterAutoscaler

func (g *Gateway) RegisterAutoscaler(ctx context.Context, template MCPServerConfig, policy string, spawner Spawner, autoscale AutoscalePolicy) error

RegisterAutoscaler registers an autoscaled replica set for an MCP server. The Spawner owns replica provisioning; the gateway only stores metadata and wires the scaler into the router. One synchronous Tick is executed before returning so Min (and WarmPool) replicas are available before the caller's first tool call — except when IdleToZero=true and Min=0, in which case the first tool call triggers a cold-start spawn instead.

func (*Gateway) RegisterMCPReplicaSet

func (g *Gateway) RegisterMCPReplicaSet(ctx context.Context, name, policy string, cfgs []MCPServerConfig) error

RegisterMCPReplicaSet initializes one AgentClient per config and registers them as a single replica set under the given server name. All configs must be for the same logical server (same Name, same transport, same tool list); only the per-replica runtime handles (ContainerID / Endpoint) should differ. For len(cfgs) == 1 this is byte-identical to the old single-client path.

Partial-startup tolerance: if some replicas fail to initialize, the server is still registered with the successful ones. The call only returns an error when every replica failed, or when the single-replica case fails (in which case the caller sees the same error shape as before).

func (*Gateway) RegisterMCPServer

func (g *Gateway) RegisterMCPServer(ctx context.Context, cfg MCPServerConfig) error

RegisterMCPServer registers and initializes a single-replica MCP server. Equivalent to RegisterMCPReplicaSet with one config and round-robin policy.

func (*Gateway) ReplicaStatuses

func (g *Gateway) ReplicaStatuses(serverName string) []ReplicaStatus

ReplicaStatuses returns per-replica status for the named server, ordered by replica id. Returns nil if the server is not registered.

func (*Gateway) ResetServerPins

func (g *Gateway) ResetServerPins(serverName string) error

ResetServerPins clears the stored pin record for serverName, if the wired SchemaVerifier also implements PinResetter. Called before re-registering a modified server during hot reload so the next VerifyOrPin re-pins from scratch rather than flagging config-driven tool changes as drift.

func (*Gateway) RestartMCPServer

func (g *Gateway) RestartMCPServer(ctx context.Context, name string) error

RestartMCPServer restarts an individual MCP server by name. It tears down the existing connection, optionally restarts the container (for stdio transport), and re-registers the server using its stored config.

func (*Gateway) Router

func (g *Gateway) Router() *Router

Router returns the tool router.

func (*Gateway) ServerInfo

func (g *Gateway) ServerInfo() ServerInfo

ServerInfo returns the gateway server info.

func (*Gateway) SessionCount

func (g *Gateway) SessionCount() int

SessionCount returns the number of active sessions.

func (*Gateway) Sessions

func (g *Gateway) Sessions() *SessionManager

Sessions returns the session manager.

func (*Gateway) SetCodeMode

func (g *Gateway) SetCodeMode(timeout time.Duration)

SetCodeMode enables code mode with the given timeout. When code mode is active, tools/list returns meta-tools instead of individual tools.

func (*Gateway) SetDefaultOutputFormat

func (g *Gateway) SetDefaultOutputFormat(format string)

SetDefaultOutputFormat sets the gateway-level default output format.

func (*Gateway) SetDockerClient

func (g *Gateway) SetDockerClient(cli dockerclient.DockerClient)

SetDockerClient sets the Docker client for stdio transport.

func (*Gateway) SetFormatSavingsRecorder

func (g *Gateway) SetFormatSavingsRecorder(recorder FormatSavingsRecorder)

SetFormatSavingsRecorder sets the recorder for format savings metrics.

func (*Gateway) SetLogger

func (g *Gateway) SetLogger(logger *slog.Logger)

SetLogger sets the logger for gateway operations. If nil is passed, logging is disabled (default).

func (*Gateway) SetMaxToolResultBytes

func (g *Gateway) SetMaxToolResultBytes(n int)

SetMaxToolResultBytes sets the maximum tool result size in bytes before truncation. When set to 0, the default of 65536 (64KB) is used.

func (*Gateway) SetSchemaVerifier

func (g *Gateway) SetSchemaVerifier(sv SchemaVerifier, action string)

SetSchemaVerifier wires in a SchemaVerifier for TOFU schema pinning. action must be "warn" (default) or "block".

func (*Gateway) SetServerMeta

func (g *Gateway) SetServerMeta(cfg MCPServerConfig)

SetServerMeta stores metadata for an MCP server without connecting to it. This is used by tests and by internal registration paths that manage their own client connections.

func (*Gateway) SetTokenCounter

func (g *Gateway) SetTokenCounter(counter token.Counter)

SetTokenCounter sets the token counter used for format savings calculation.

func (*Gateway) SetToolCallObserver

func (g *Gateway) SetToolCallObserver(obs ToolCallObserver)

SetToolCallObserver sets an observer that is notified after every tool call. Used to collect token usage metrics without coupling the gateway to a metrics package.

func (*Gateway) SetVersion

func (g *Gateway) SetVersion(version string)

SetVersion sets the gateway version string.

func (*Gateway) StartAutoscaler

func (g *Gateway) StartAutoscaler(ctx context.Context, interval time.Duration)

StartAutoscaler launches a background goroutine that ticks every registered autoscaler on the given interval. Cancelling ctx stops the loop. Safe to call alongside StartHealthMonitor and StartCleanup.

func (*Gateway) StartCleanup

func (g *Gateway) StartCleanup(ctx context.Context)

StartCleanup starts periodic session cleanup. Call Close() to stop.

func (*Gateway) StartHealthMonitor

func (g *Gateway) StartHealthMonitor(ctx context.Context, interval time.Duration)

StartHealthMonitor starts periodic health checking for all registered MCP servers. It runs alongside StartCleanup and stops when the gateway context is cancelled.

func (*Gateway) Status

func (g *Gateway) Status() []MCPServerStatus

Status returns status of all registered MCP servers. Note: This only returns actual MCP servers, not A2A adapters or other clients added directly to the router.

func (*Gateway) UnblockServer

func (g *Gateway) UnblockServer(serverName string)

UnblockServer clears the block on a server that was blocked due to schema drift. Called by the approve flow after the user accepts the updated tool definitions.

func (*Gateway) UnregisterMCPServer

func (g *Gateway) UnregisterMCPServer(name string)

UnregisterMCPServer removes an MCP server from the gateway.

type Handler

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

Handler provides HTTP handlers for the MCP gateway.

func NewHandler

func NewHandler(gateway *Gateway) *Handler

NewHandler creates a new MCP HTTP handler.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles MCP requests at /mcp.

type HealthStatus

type HealthStatus struct {
	Healthy     bool      // Whether the server is responding to pings
	LastCheck   time.Time // When the last health check ran
	LastHealthy time.Time // When the server was last seen healthy
	Error       string    // Error message if unhealthy (empty when healthy)
}

HealthStatus tracks the health state of a downstream MCP server.

type InitializeParams

type InitializeParams struct {
	ProtocolVersion string       `json:"protocolVersion"`
	ClientInfo      ClientInfo   `json:"clientInfo"`
	Capabilities    Capabilities `json:"capabilities"`
}

InitializeParams contains parameters for the initialize request.

type InitializeResult

type InitializeResult struct {
	ProtocolVersion string       `json:"protocolVersion"`
	ServerInfo      ServerInfo   `json:"serverInfo"`
	Capabilities    Capabilities `json:"capabilities"`
	Instructions    string       `json:"instructions,omitempty"`
}

InitializeResult is the response to initialize.

type InputSchemaObject

type InputSchemaObject struct {
	Type       string              `json:"type"`
	Properties map[string]Property `json:"properties,omitempty"`
	Required   []string            `json:"required,omitempty"`
}

InputSchemaObject is a helper for building simple input schemas. Use this when creating tools programmatically (e.g., A2A skill adapters). For MCP tools received from servers, use json.RawMessage directly to preserve the full JSON Schema without loss.

type MCPPrompt

type MCPPrompt struct {
	Name        string           `json:"name"`
	Description string           `json:"description,omitempty"`
	Arguments   []PromptArgument `json:"arguments,omitempty"`
}

MCPPrompt represents a prompt in the MCP prompts/list response.

type MCPResource

type MCPResource struct {
	URI         string `json:"uri"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	MimeType    string `json:"mimeType,omitempty"`
}

MCPResource represents a resource in the resources/list response.

type MCPServerConfig

type MCPServerConfig struct {
	Name              string
	Transport         Transport
	Endpoint          string               // For HTTP/SSE transport
	ContainerID       string               // For Docker Stdio transport
	External          bool                 // True for external URL servers (no container)
	LocalProcess      bool                 // True for local process servers (no container)
	SSH               bool                 // True for SSH servers (remote process over SSH)
	OpenAPI           bool                 // True for OpenAPI-based servers
	Command           []string             // For local process or SSH transport
	WorkDir           string               // For local process transport
	Env               map[string]string    // For local process or SSH transport
	SSHHost           string               // SSH hostname (for SSH servers)
	SSHUser           string               // SSH username (for SSH servers)
	SSHPort           int                  // SSH port (for SSH servers, 0 = default 22)
	SSHIdentityFile   string               // SSH identity file path (for SSH servers)
	SSHKnownHostsFile string               // SSH known_hosts file path; enables StrictHostKeyChecking=yes
	SSHJumpHost       string               // SSH jump/bastion host ([user@]host[:port])
	OpenAPIConfig     *OpenAPIClientConfig // OpenAPI configuration (for OpenAPI servers)
	Tools             []string             // Tool whitelist (empty = all tools)
	OutputFormat      string               // Output format: "json", "toon", "csv", "text"
	PinSchemas        *bool                // Override gateway schema pinning (nil = inherit gateway default)

	// ReadyTimeout overrides the HTTP/SSE readiness wait. Zero uses DefaultReadyTimeout.
	// Applies only to HTTP and SSE transports; stdio and other paths ignore it.
	ReadyTimeout time.Duration

	// PingTimeout overrides the per-ping deadline used by the health monitor.
	// Zero uses DefaultPingTimeout. Useful for slow upstreams (e.g. HTTP servers
	// with many tools) where the 5s default can flake under autoscale spawn load.
	PingTimeout time.Duration

	// CleanupOnReadyFailure runs when waitForHTTPServer returns ErrReadyTimeout.
	// Callers that manage the underlying container populate this with a closure
	// that stops and removes it, so a retry starts from a clean slate. nil means
	// "no cleanup" (e.g. external servers, tests).
	CleanupOnReadyFailure func(ctx context.Context) error
}

MCPServerConfig contains configuration for connecting to an MCP server.

type MCPServerStatus

type MCPServerStatus struct {
	Name         string     `json:"name"`
	Transport    Transport  `json:"transport"`
	Endpoint     string     `json:"endpoint,omitempty"`
	ContainerID  string     `json:"containerId,omitempty"`
	Initialized  bool       `json:"initialized"`
	ToolCount    int        `json:"toolCount"`
	Tools        []string   `json:"tools"`
	External     bool       `json:"external"`               // True for external URL servers
	LocalProcess bool       `json:"localProcess"`           // True for local process servers
	SSH          bool       `json:"ssh"`                    // True for SSH servers
	SSHHost      string     `json:"sshHost,omitempty"`      // SSH hostname
	OpenAPI      bool       `json:"openapi"`                // True for OpenAPI servers
	OpenAPISpec  string     `json:"openapiSpec,omitempty"`  // OpenAPI spec location
	OutputFormat string     `json:"outputFormat,omitempty"` // Configured output format (empty = json default)
	Healthy      *bool      `json:"healthy,omitempty"`      // Health check result (nil if not yet checked)
	LastCheck    *time.Time `json:"lastCheck,omitempty"`    // When last health check ran
	HealthError  string     `json:"healthError,omitempty"`  // Error message if unhealthy

	// ToolWhitelist is the tools: field from the stack YAML for this server.
	// Empty (nil) means no whitelist is configured and the server is exposing
	// every tool it advertises. The UI uses this to distinguish "curated" from
	// "full-list" without needing to diff tools against a hidden pre-filter
	// set that the gateway doesn't retain.
	ToolWhitelist []string `json:"toolWhitelist,omitempty"`

	Replicas []ReplicaStatus `json:"replicas,omitempty"` // Per-replica status; always populated

	// Autoscale is non-nil only for servers with an autoscale block in
	// their stack YAML. Reports current min/max/target/median and the
	// last scaler decision so operators can reason about scale events.
	Autoscale *AutoscaleStatus `json:"autoscale,omitempty"`
}

MCPServerStatus returns status information about registered MCP servers.

type OpenAPIClient

type OpenAPIClient struct {
	ClientBase
	// contains filtered or unexported fields
}

OpenAPIClient implements AgentClient by transforming OpenAPI operations to MCP tools. It parses an OpenAPI specification and converts each operation into an MCP tool, proxying tool calls to HTTP requests against the target API.

func NewOpenAPIClient

func NewOpenAPIClient(name string, cfg *OpenAPIClientConfig) (*OpenAPIClient, error)

NewOpenAPIClient creates an OpenAPI-based MCP client.

func (*OpenAPIClient) CallTool

func (c *OpenAPIClient) CallTool(ctx context.Context, name string, args map[string]any) (*ToolCallResult, error)

CallTool executes an OpenAPI operation.

func (*OpenAPIClient) Initialize

func (c *OpenAPIClient) Initialize(ctx context.Context) error

Initialize loads and parses the OpenAPI spec.

func (*OpenAPIClient) Name

func (c *OpenAPIClient) Name() string

Name returns the client name.

func (*OpenAPIClient) Ping

func (c *OpenAPIClient) Ping(ctx context.Context) error

Ping checks if the OpenAPI backend is reachable by making a HEAD request to the base URL.

func (*OpenAPIClient) RefreshTools

func (c *OpenAPIClient) RefreshTools(ctx context.Context) error

RefreshTools builds MCP tools from OpenAPI operations. OpenAPIClient applies config-time include/exclude filters here. The runtime whitelist is applied at read time by ClientBase.Tools(), so the full post-include/exclude set is cached to let the UI widen the whitelist.

func (*OpenAPIClient) SetLogger

func (c *OpenAPIClient) SetLogger(logger *slog.Logger)

SetLogger sets the logger for this client.

func (*OpenAPIClient) SetPingTimeout

func (c *OpenAPIClient) SetPingTimeout(d time.Duration)

SetPingTimeout overrides the per-ping deadline used by Ping. Zero restores the default (DefaultPingTimeout).

type OpenAPIClientConfig

type OpenAPIClientConfig struct {
	Spec       string   // URL or local file path to OpenAPI spec
	BaseURL    string   // Override server URL from spec
	AuthType   string   // "bearer", "header", "query", "oauth2", or "basic"
	AuthToken  string   // Resolved bearer token (from env)
	AuthHeader string   // Header name for header-based auth
	AuthValue  string   // Resolved header value (from env)
	Include    []string // Operation IDs to include
	Exclude    []string // Operation IDs to exclude
	NoExpand   bool     // If true, skip environment variable expansion in spec file

	// Query param auth fields
	AuthQueryParam string // Query parameter name for type: query
	AuthQueryValue string // Resolved query parameter value (from env)

	// OAuth2 client credentials fields
	OAuth2ClientID     string   // Resolved OAuth2 client ID (from env)
	OAuth2ClientSecret string   // Resolved OAuth2 client secret (from env)
	OAuth2TokenURL     string   // OAuth2 token endpoint URL
	OAuth2Scopes       []string // OAuth2 scopes to request

	// Basic auth fields
	BasicUsername string // Resolved username (from env)
	BasicPassword string // Resolved password (from env)

	// TLS/mTLS fields
	TLSCertFile           string // Client certificate file path
	TLSKeyFile            string // Client private key file path
	TLSCAFile             string // Custom CA certificate file path
	TLSInsecureSkipVerify bool   // Skip server certificate verification
}

OpenAPIClientConfig contains configuration for an OpenAPI-backed MCP client.

type OpenAPIOperation

type OpenAPIOperation struct {
	Method       string
	Path         string
	PathParams   []string // Parameter names in path order (always required)
	QueryParams  map[string]*openapi3.Parameter
	HeaderParams map[string]*openapi3.Parameter
	RequestBody  *openapi3.RequestBodyRef
}

OpenAPIOperation holds parsed OpenAPI operation details for execution.

type PinResetter

type PinResetter interface {
	// ResetServerPins deletes the pin record for serverName so the next
	// VerifyOrPin call treats it as a first-use pin.
	ResetServerPins(serverName string) error
}

PinResetter is an optional extension of SchemaVerifier for clearing stored pin records. Implementations that support this (e.g. pins.GatewayAdapter) satisfy this interface. It is checked via type assertion, not embedded in SchemaVerifier, so existing implementations remain compatible.

type Pingable

type Pingable interface {
	Ping(ctx context.Context) error
}

Pingable is an optional interface for AgentClients that support health checks. The health monitor uses type assertion to check if a client implements this.

type ProcessClient

type ProcessClient struct {
	RPCClient
	// contains filtered or unexported fields
}

ProcessClient communicates with an MCP server via a local process stdin/stdout.

func NewProcessClient

func NewProcessClient(name string, command []string, workDir string, env map[string]string) *ProcessClient

NewProcessClient creates a new process-based MCP client. The command is executed with the given working directory and environment. Environment variables are merged with the current process environment.

func (*ProcessClient) Close

func (c *ProcessClient) Close() error

Close terminates the process gracefully. Sends SIGTERM, waits up to 5 seconds, then sends SIGKILL if still running.

func (*ProcessClient) Connect

func (c *ProcessClient) Connect(ctx context.Context) error

Connect starts the process and attaches to its stdin/stdout.

func (*ProcessClient) PID

func (c *ProcessClient) PID() int

PID returns the operating-system process id of the running child. Returns 0 when the process has not been started (or has exited and been cleared).

func (*ProcessClient) Ping

func (c *ProcessClient) Ping(ctx context.Context) error

Ping checks if the process is alive by verifying it's still running and sending a JSON-RPC ping.

func (*ProcessClient) Reconnect

func (c *ProcessClient) Reconnect(ctx context.Context) error

Reconnect terminates the existing process and starts a new one, including the MCP handshake and tool refresh. Thread-safe: concurrent callers will block until reconnection completes.

func (*ProcessClient) SetPingTimeout

func (c *ProcessClient) SetPingTimeout(d time.Duration)

SetPingTimeout overrides the per-ping deadline used by Ping. Zero restores the default (DefaultPingTimeout).

type PromptArgument

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

PromptArgument describes a prompt parameter.

type PromptArgumentData

type PromptArgumentData struct {
	Name        string
	Description string
	Required    bool
	Default     string
}

PromptArgumentData describes a prompt argument with default value support.

type PromptData

type PromptData struct {
	Name        string
	Description string
	Content     string
	Arguments   []PromptArgumentData
}

PromptData contains prompt information used by the MCP protocol layer.

type PromptMessage

type PromptMessage struct {
	Role    string  `json:"role"` // "user" or "assistant"
	Content Content `json:"content"`
}

PromptMessage represents a message in a prompts/get response.

type PromptProvider

type PromptProvider interface {
	ListPromptData() []PromptData
	GetPromptData(name string) (*PromptData, error)
}

PromptProvider is an optional interface for AgentClients that manage prompts. The gateway uses type assertion to detect prompt-capable clients and serve the MCP prompts/* and resources/* protocol methods.

type PromptsCapability

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

PromptsCapability indicates prompts support.

type PromptsGetParams

type PromptsGetParams struct {
	Name      string            `json:"name"`
	Arguments map[string]string `json:"arguments,omitempty"`
}

PromptsGetParams contains parameters for prompts/get.

type PromptsGetResult

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

PromptsGetResult is the response to prompts/get.

type PromptsListResult

type PromptsListResult struct {
	Prompts []MCPPrompt `json:"prompts"`
}

PromptsListResult is the response to prompts/list.

type Property

type Property struct {
	Type        string   `json:"type"`
	Description string   `json:"description,omitempty"`
	Enum        []string `json:"enum,omitempty"`
	Default     any      `json:"default,omitempty"`
}

Property describes a single property in an input schema.

type RPCClient

type RPCClient struct {
	ClientBase
	// contains filtered or unexported fields
}

RPCClient provides shared JSON-RPC protocol methods for MCP transport clients. It embeds ClientBase for state management and delegates I/O to a transporter.

Embedding hierarchy: ConcreteClient -> RPCClient -> ClientBase

Each concrete client (Client, StdioClient, ProcessClient) embeds RPCClient and implements transporter, passing itself to initRPCClient. This allows the shared protocol methods to dispatch to transport-specific I/O.

OpenAPIClient is separate — it embeds ClientBase directly since it does not use JSON-RPC at all.

func (*RPCClient) CallTool

func (r *RPCClient) CallTool(ctx context.Context, name string, arguments map[string]any) (*ToolCallResult, error)

CallTool invokes a tool on the downstream agent.

func (*RPCClient) Initialize

func (r *RPCClient) Initialize(ctx context.Context) error

Initialize performs the MCP initialize handshake. If the transport implements connector, Connect() is called first.

func (*RPCClient) Name

func (r *RPCClient) Name() string

Name returns the agent name.

func (*RPCClient) RefreshTools

func (r *RPCClient) RefreshTools(ctx context.Context) error

RefreshTools fetches the current tool list from the agent. If a tool whitelist has been set, only tools matching the whitelist are stored.

func (*RPCClient) SetLogger

func (r *RPCClient) SetLogger(logger *slog.Logger)

SetLogger sets the logger for this client.

type Reconnectable

type Reconnectable interface {
	Reconnect(ctx context.Context) error
}

Reconnectable is an optional interface for AgentClients that support reconnection after connection failures (e.g., container restart, process crash). The health monitor uses type assertion to trigger reconnection on unhealthy clients.

type Replica

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

Replica is a single member of a ReplicaSet. It wraps one AgentClient (the concrete transport — ProcessClient, StdioClient, Client, etc.) and tracks liveness and in-flight request count for dispatch decisions.

func (*Replica) Client

func (r *Replica) Client() AgentClient

Client returns the underlying AgentClient.

func (*Replica) DecInFlight

func (r *Replica) DecInFlight()

DecInFlight decrements the in-flight request count.

func (*Replica) Healthy

func (r *Replica) Healthy() bool

Healthy reports whether this replica is eligible for dispatch.

func (*Replica) ID

func (r *Replica) ID() int

ID returns the zero-indexed replica id within its ReplicaSet.

func (*Replica) InFlight

func (r *Replica) InFlight() int64

InFlight returns the current in-flight request count.

func (*Replica) IncInFlight

func (r *Replica) IncInFlight()

IncInFlight increments the in-flight request count.

func (*Replica) MarkStarted

func (r *Replica) MarkStarted(now time.Time)

MarkStarted records the current time as the replica's start time. Called from NewReplicaSet and from the reconnect path so uptime reflects the lifetime of the currently-running backing process.

func (*Replica) Restart

func (r *Replica) Restart() *backoffState

Restart returns the replica's restart-backoff state. Never nil.

func (*Replica) SetHealthy

func (r *Replica) SetHealthy(h bool)

SetHealthy marks this replica healthy or unhealthy.

func (*Replica) StartedAt

func (r *Replica) StartedAt() time.Time

StartedAt returns the time this replica was initialized or most recently restarted. Zero value means the replica has not yet started.

type ReplicaSet

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

ReplicaSet is a pool of AgentClient replicas for a single logical MCP server. Dispatch is determined by the set's policy. A single-replica set behaves identically to a direct AgentClient (its Pick always returns that one replica when healthy).

func NewReplicaSet

func NewReplicaSet(name, policy string, clients []AgentClient) *ReplicaSet

NewReplicaSet builds a ReplicaSet from an ordered slice of AgentClients. The first client becomes replica-0, and so on. All replicas start healthy. An unknown policy falls back to round-robin. The id counter is seeded to len(clients) so dynamic adds never collide with static ids.

func (*ReplicaSet) AddReplica

func (s *ReplicaSet) AddReplica(client AgentClient) int

AddReplica appends a new replica with a monotonically increasing id and marks it healthy. Returns the new replica's id. Ids are never reused so handles stored by observers (health monitor, status endpoints) remain stable across scale events.

func (*ReplicaSet) CachedTools

func (s *ReplicaSet) CachedTools() []Tool

CachedTools returns a copy of the cached tool surface. Returns an empty slice when the cache has not been primed.

func (*ReplicaSet) Client

func (s *ReplicaSet) Client() AgentClient

Client is a convenience that calls Pick and returns the chosen replica's AgentClient. Returns nil if no replica is pickable.

func (*ReplicaSet) HealthyCount

func (s *ReplicaSet) HealthyCount() int

HealthyCount returns the number of replicas currently marked healthy.

func (*ReplicaSet) MedianInFlight

func (s *ReplicaSet) MedianInFlight() float64

MedianInFlight returns the median of in-flight counters across currently healthy replicas. Returns 0 when no replica is healthy. Returns float64 for precision in small-scale clusters where one request can tilt the mean noticeably.

func (*ReplicaSet) Name

func (s *ReplicaSet) Name() string

Name returns the logical server name.

func (*ReplicaSet) Pick

func (s *ReplicaSet) Pick() (*Replica, error)

Pick chooses a healthy replica according to the set's policy. Returns ErrNoHealthyReplicas if every replica is currently marked unhealthy.

func (*ReplicaSet) Policy

func (s *ReplicaSet) Policy() string

Policy returns the dispatch policy in effect.

func (*ReplicaSet) ReinsertReplica

func (s *ReplicaSet) ReinsertReplica(r *Replica)

ReinsertReplica puts a previously-removed replica back into the set without minting a new id. Used by the autoscaler when a drain fails so the in-flight counters and restart state the caller accumulated while the replica was detached are preserved. Idempotent: if a replica with the same id is already present, this is a no-op.

func (*ReplicaSet) RemoveReplica

func (s *ReplicaSet) RemoveReplica(id int) (*Replica, error)

RemoveReplica removes the replica with the given id and returns it so the caller can close its client. Returns an error if the id is not present. The caller is responsible for policy checks (min floor, warm pool, etc.); this method only enforces that the replica exists.

func (*ReplicaSet) Replicas

func (s *ReplicaSet) Replicas() []*Replica

Replicas returns a snapshot slice of the replicas. Callers may iterate the snapshot safely; the underlying *Replica values are shared.

func (*ReplicaSet) SetToolCache

func (s *ReplicaSet) SetToolCache(tools []Tool)

SetToolCache replaces the tool-definition cache. Callers set this after every successful refresh so Router.AggregatedTools can fall back to the cached surface when every replica is currently reaped.

func (*ReplicaSet) Size

func (s *ReplicaSet) Size() int

Size returns the number of replicas in the set.

type ReplicaStatus

type ReplicaStatus struct {
	ReplicaID       int        `json:"replicaId"`
	State           string     `json:"state"` // "healthy" | "unhealthy" | "restarting"
	Healthy         bool       `json:"healthy"`
	InFlight        int64      `json:"inFlight"`
	StartedAt       time.Time  `json:"startedAt,omitempty"`
	LastCheck       *time.Time `json:"lastCheck,omitempty"`
	LastHealthy     *time.Time `json:"lastHealthy,omitempty"`
	LastError       string     `json:"lastError,omitempty"`
	RestartAttempts uint32     `json:"restartAttempts,omitempty"`
	NextRetryAt     *time.Time `json:"nextRetryAt,omitempty"`
	PID             int        `json:"pid,omitempty"`
	ContainerID     string     `json:"containerId,omitempty"`
}

ReplicaStatus reports the live state of a single replica within a ReplicaSet. Uptime is derived from StartedAt at read time by the consumer.

type ResourceContents

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

ResourceContents represents the content of a resource.

type ResourcesCapability

type ResourcesCapability struct {
	Subscribe   bool `json:"subscribe,omitempty"`
	ListChanged bool `json:"listChanged,omitempty"`
}

ResourcesCapability indicates resources support.

type ResourcesListResult

type ResourcesListResult struct {
	Resources []MCPResource `json:"resources"`
}

ResourcesListResult is the response to resources/list.

type ResourcesReadParams

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

ResourcesReadParams contains parameters for resources/read.

type ResourcesReadResult

type ResourcesReadResult struct {
	Contents []ResourceContents `json:"contents"`
}

ResourcesReadResult is the response to resources/read.

type Router

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

Router routes tool calls to the appropriate agent.

Internally the Router keys on server name and stores a *ReplicaSet per name. A single-client registration (via AddClient) is wrapped in a single-replica round-robin set so callers outside this package observe the same behavior as before replicas existed.

func NewRouter

func NewRouter() *Router

NewRouter creates a new tool router.

func (*Router) AddClient

func (r *Router) AddClient(client AgentClient)

AddClient adds an agent client to the router as a single-replica set. Preserves the pre-replicas API so existing callers keep working unchanged.

func (*Router) AddReplicaSet

func (r *Router) AddReplicaSet(set *ReplicaSet)

AddReplicaSet registers a replica set under its logical server name. Replaces any existing set with the same name.

func (*Router) AggregatedTools

func (r *Router) AggregatedTools() []Tool

AggregatedTools returns all tools from all agents with prefixed names.

func (*Router) Clients

func (r *Router) Clients() []AgentClient

Clients returns one representative AgentClient per registered agent, sorted by agent name. Each representative is chosen via the set's policy, so a single-replica set returns its only client. Skips sets with no currently-healthy replica.

func (*Router) GetClient

func (r *Router) GetClient(name string) AgentClient

GetClient returns one client for the named agent, chosen by the set's dispatch policy. Returns nil if the agent is not registered or no replica is currently healthy.

func (*Router) GetReplicaSet

func (r *Router) GetReplicaSet(name string) *ReplicaSet

GetReplicaSet returns the replica set for the named agent, or nil if the agent is not registered. Useful for callers that need per-replica access (health monitor, status reporting).

func (*Router) RefreshTools

func (r *Router) RefreshTools()

RefreshTools updates the tool registry from all agents.

func (*Router) RemoveClient

func (r *Router) RemoveClient(name string)

RemoveClient removes an agent (replica set) and its tools from the router.

func (*Router) ReplicaSets

func (r *Router) ReplicaSets() []*ReplicaSet

ReplicaSets returns all registered replica sets, sorted by agent name.

func (*Router) RouteToolCall

func (r *Router) RouteToolCall(prefixedName string) (AgentClient, string, error)

RouteToolCall routes a tool call to the appropriate agent. The concrete replica is chosen by the set's dispatch policy.

func (*Router) RouteToolCallReplica

func (r *Router) RouteToolCallReplica(prefixedName string) (*Replica, string, error)

RouteToolCallReplica behaves like RouteToolCall but returns the chosen replica itself. Callers that need the replica id (for per-replica logging, tracing, and in-flight accounting) should use this variant.

type SSEServer

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

SSEServer handles legacy SSE connections at /sse for backward-compatibility negotiation. Clients using the deprecated HTTP+SSE transport receive a negotiation response directing them to use the Streamable HTTP transport at POST /mcp.

func NewSSEServer

func NewSSEServer(gateway *Gateway) *SSEServer

NewSSEServer creates a new SSE server.

func (*SSEServer) Close

func (s *SSEServer) Close()

Close is a no-op retained for interface compatibility.

func (*SSEServer) HandleMessage

func (s *SSEServer) HandleMessage(w http.ResponseWriter, r *http.Request)

HandleMessage returns 410 Gone for the legacy /message endpoint. Clients should use the Streamable HTTP transport at /mcp instead.

func (*SSEServer) ServeHTTP

func (s *SSEServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles GET /sse — sends a negotiation event directing the client to use the Streamable HTTP transport and closes the connection.

func (*SSEServer) SessionCount

func (s *SSEServer) SessionCount() int

SessionCount returns 0; session management has moved to StreamableHTTPServer.

type Sandbox

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

Sandbox executes JavaScript code in a goja runtime with MCP tool bindings.

func NewSandbox

func NewSandbox(timeout time.Duration) *Sandbox

NewSandbox creates a sandbox with the given execution timeout and default fetch config.

func NewSandboxWithConfig

func NewSandboxWithConfig(timeout time.Duration, fetchConfig FetchConfig) *Sandbox

NewSandboxWithConfig creates a sandbox with the given execution timeout and fetch config.

func (*Sandbox) Execute

func (s *Sandbox) Execute(ctx context.Context, code string, caller ToolCaller, allowedTools []Tool) (*ExecuteResult, error)

Execute runs JavaScript code in a fresh goja runtime with MCP tool bindings. The code is transpiled from modern JS to ES2015 before execution.

type SchemaDrift

type SchemaDrift struct {
	Name           string
	OldHash        string
	NewHash        string
	OldDescription string
	NewDescription string
}

SchemaDrift describes a single tool whose definition changed since it was pinned.

type SchemaVerifier

type SchemaVerifier interface {
	// VerifyOrPin pins tools on first use and verifies them on subsequent calls.
	// Returns the list of modified tools (empty = no drift) and any error.
	VerifyOrPin(serverName string, tools []Tool) ([]SchemaDrift, error)
}

SchemaVerifier performs TOFU schema pinning for MCP tool definitions. It is defined in the mcp package (rather than importing pkg/pins) to avoid an import cycle: pkg/pins already imports pkg/mcp for the Tool type. pkg/pins.GatewayAdapter implements this interface.

type SearchIndex

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

SearchIndex builds and queries a searchable catalog of MCP tools.

func NewSearchIndex

func NewSearchIndex(tools []Tool) *SearchIndex

NewSearchIndex creates a search index from the given tools.

func (*SearchIndex) Search

func (idx *SearchIndex) Search(query string) []Tool

Search returns tools matching the query string. It searches tool names, descriptions, and parameter names. Results are returned with full schemas.

func (*SearchIndex) ToolCount

func (idx *SearchIndex) ToolCount() int

ToolCount returns the number of indexed tools.

type ServerInfo

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

ServerInfo contains information about the MCP server.

type Session

type Session struct {
	ID          string
	ClientInfo  ClientInfo
	Initialized bool
	CreatedAt   time.Time
	LastSeen    time.Time
}

Session represents an MCP client session.

type SessionManager

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

SessionManager manages client sessions.

func NewSessionManager

func NewSessionManager() *SessionManager

NewSessionManager creates a new session manager.

func (*SessionManager) Cleanup

func (m *SessionManager) Cleanup(maxAge time.Duration) int

Cleanup removes stale sessions older than the given duration.

func (*SessionManager) Count

func (m *SessionManager) Count() int

Count returns the number of active sessions.

func (*SessionManager) Create

func (m *SessionManager) Create(clientInfo ClientInfo) *Session

Create creates a new session. If the session count exceeds maxSessions, the oldest session (by LastSeen) is evicted.

func (*SessionManager) Delete

func (m *SessionManager) Delete(id string)

Delete removes a session.

func (*SessionManager) Get

func (m *SessionManager) Get(id string) *Session

Get retrieves a session by ID.

func (*SessionManager) List

func (m *SessionManager) List() []*Session

List returns all sessions.

func (*SessionManager) Touch

func (m *SessionManager) Touch(id string)

Touch updates the last seen time for a session.

type Spawner

type Spawner interface {
	Spawn(ctx context.Context) (AgentClient, error)
	Reap(ctx context.Context, r *Replica) error
}

Spawner launches or reaps one replica for a named server. One implementation per transport class lives in pkg/controller. The Gateway constructs the right one at RegisterMCPReplicaSet time and hands it to NewAutoscaler.

Spawn MUST return a ready-to-serve AgentClient: Connect/Initialize/RefreshTools have completed before the returned value is added to the set, otherwise the first tool call routed to the new replica would fail. Reap is given the Replica (pre-removed from dispatch) and should close the underlying client and free any resources owned by the spawner.

type StdioClient

type StdioClient struct {
	RPCClient
	// contains filtered or unexported fields
}

StdioClient communicates with an MCP server via container stdin/stdout.

func NewStdioClient

func NewStdioClient(name, containerID string, cli dockerclient.DockerClient) *StdioClient

NewStdioClient creates a new stdio-based MCP client.

func (*StdioClient) Close

func (c *StdioClient) Close() error

Close closes the connection.

func (*StdioClient) Connect

func (c *StdioClient) Connect(ctx context.Context) error

Connect attaches to the container's stdin/stdout.

func (*StdioClient) ContainerID

func (c *StdioClient) ContainerID() string

ContainerID returns the docker container id this client was bound to.

func (*StdioClient) Ping

func (c *StdioClient) Ping(ctx context.Context) error

Ping checks if the container stdio connection is alive by sending a JSON-RPC ping.

func (*StdioClient) Reconnect

func (c *StdioClient) Reconnect(ctx context.Context) error

Reconnect closes the existing connection and re-establishes it, including the MCP handshake and tool refresh. Thread-safe: concurrent callers will block until reconnection completes.

func (*StdioClient) SetPingTimeout

func (c *StdioClient) SetPingTimeout(d time.Duration)

SetPingTimeout overrides the per-ping deadline used by Ping. Zero restores the default (DefaultPingTimeout).

type StreamableHTTPServer

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

StreamableHTTPServer implements the MCP Streamable HTTP transport (spec 2025-06-18). It handles POST, GET, and DELETE requests at a single /mcp endpoint.

func NewStreamableHTTPServer

func NewStreamableHTTPServer(gateway *Gateway, allowedOrigins []string) *StreamableHTTPServer

NewStreamableHTTPServer creates a new Streamable HTTP server.

func (*StreamableHTTPServer) Close

func (s *StreamableHTTPServer) Close()

Close tears down all active sessions and cancels their SSE streams.

func (*StreamableHTTPServer) ServeHTTP

func (s *StreamableHTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP routes /mcp requests based on HTTP method.

func (*StreamableHTTPServer) SessionCount

func (s *StreamableHTTPServer) SessionCount() int

SessionCount returns the number of active Streamable HTTP sessions.

func (*StreamableHTTPServer) SessionIDs

func (s *StreamableHTTPServer) SessionIDs() []string

SessionIDs returns the IDs of all active sessions.

func (*StreamableHTTPServer) SetAllowedOrigins

func (s *StreamableHTTPServer) SetAllowedOrigins(origins []string)

SetAllowedOrigins updates the list of allowed origins for DNS rebinding protection.

type StreamableSession

type StreamableSession struct {
	ID string
	// contains filtered or unexported fields
}

StreamableSession represents an active Streamable HTTP session.

type Tool

type Tool struct {
	Name        string          `json:"name"`
	Title       string          `json:"title,omitempty"`
	Description string          `json:"description,omitempty"`
	InputSchema json.RawMessage `json:"inputSchema"`
}

Tool represents an MCP tool definition.

func ExecuteTool

func ExecuteTool() Tool

ExecuteTool returns the Tool definition for the execute meta-tool.

func SearchTool

func SearchTool() Tool

SearchTool returns the Tool definition for the search meta-tool.

type ToolCallObserver

type ToolCallObserver interface {
	// ObserveToolCall is called after a tool call completes.
	// serverName is the MCP server that handled the call.
	// replicaID is the zero-indexed replica within that server's set, or -1
	// when the caller did not dispatch through a ReplicaSet.
	// arguments are the tool call arguments (input).
	// result is the tool call response (output). May be nil on error.
	ObserveToolCall(serverName string, replicaID int, arguments map[string]any, result *ToolCallResult)
}

ToolCallObserver receives notifications after tool calls complete. Used by the metrics system to count tokens without coupling the gateway to the metrics package directly.

type ToolCallParams

type ToolCallParams struct {
	Name      string         `json:"name"`
	Arguments map[string]any `json:"arguments,omitempty"`
}

ToolCallParams contains parameters for tools/call.

type ToolCallResult

type ToolCallResult struct {
	Content []Content `json:"content"`
	IsError bool      `json:"isError,omitempty"`
}

ToolCallResult is the response to tools/call.

type ToolCaller

type ToolCaller interface {
	CallTool(ctx context.Context, name string, arguments map[string]any) (*ToolCallResult, error)
}

ToolCaller allows calling tools across the gateway's aggregated servers. This interface decouples the registry from the gateway to avoid circular dependencies. The gateway implements this interface and passes it to components that need to call tools without holding a direct reference to the gateway or router.

type ToolsCapability

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

ToolsCapability indicates tools support.

type ToolsListResult

type ToolsListResult struct {
	Tools      []Tool  `json:"tools"`
	NextCursor *string `json:"nextCursor,omitempty"`
}

ToolsListResult is the response to tools/list.

type Transport

type Transport string

Transport represents the type of transport for an MCP connection.

const (
	TransportHTTP  Transport = "http"
	TransportStdio Transport = "stdio"
	TransportSSE   Transport = "sse"
)

Jump to

Keyboard shortcuts

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