Documentation
¶
Overview ¶
Package aggregator provides the MCP aggregator server implementation.
SSO Authentication Mechanisms ¶
Muster supports two Single Sign-On (SSO) mechanisms for authenticating to downstream MCP servers:
## SSO Token Forwarding (explicit opt-in)
When muster itself is protected by OAuth (via oauth_server configuration), muster can forward its own ID token to downstream MCP servers. The downstream server must be configured to trust muster's OAuth client ID in its TrustedAudiences.
Flow:
- User authenticates TO muster via OAuth (Google, Dex, etc.)
- Muster receives and stores the user's ID token
- User accesses server with forwardToken: true
- Muster injects ID token as Authorization: Bearer header
- Downstream server validates token, trusts muster's client ID
Configuration: Requires `auth.forwardToken: true` in MCPServer spec.
## SSO Token Exchange (RFC 8693)
When clusters have separate Identity Providers, muster can exchange its local token for one valid on the remote cluster's IdP (e.g., Dex). This enables cross-cluster SSO without requiring shared trust.
Flow:
- User authenticates TO muster via OAuth
- User accesses server with tokenExchange configuration
- Muster exchanges its token at the remote IdP's token endpoint
- Remote IdP issues a new token valid for the remote cluster
- Muster uses the exchanged token for downstream requests
Configuration: Requires `auth.tokenExchange` configuration in MCPServer spec.
Package aggregator provides MCP (Model Context Protocol) server aggregation functionality for the muster system.
The aggregator package acts as a central hub that collects and exposes tools, resources, and prompts from multiple backend MCP servers through a single unified interface. It implements intelligent name collision resolution, security filtering, automatic server lifecycle management, and seamless integration with the muster service architecture.
Architecture Overview ¶
The aggregator follows a layered architecture with clear separation of concerns:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ MCP Clients │ │ Core Tools │ │ Workflow │
│ (External) │ │ (Internal) │ │ Adapter │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
│
┌─────────────────┐
│ AggregatorServer│
│ (Core MCP) │
└─────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ SSE Transport │ │ Stdio Transport │ │ HTTP Transport │
│ (:8080) │ │ (CLI Mode) │ │ (Streaming) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Core Components ¶
## AggregatorManager
The AggregatorManager is the main entry point and coordinates all aggregator functionality. It manages the complete lifecycle, from server startup to graceful shutdown, and provides automatic MCP server registration based on service health status.
Key responsibilities:
- Server lifecycle management (start/stop coordination)
- Event-driven MCP server registration/deregistration
- Integration with the muster service architecture
- Periodic retry mechanism for failed registrations
- Service monitoring and health reporting
Usage:
config := AggregatorConfig{
Port: 8080,
Host: "localhost",
Transport: "sse",
Yolo: false,
MusterPrefix: "x",
}
manager := NewAggregatorManager(config, orchestratorAPI, serviceRegistry)
err := manager.Start(ctx)
defer manager.Stop(ctx)
## AggregatorServer
The AggregatorServer implements the core MCP server functionality, aggregating capabilities from multiple backend servers and exposing them through various transports. It provides real-time capability updates and maintains synchronization with backend servers.
Features:
- Multi-transport support (SSE, stdio, streamable-http)
- Dynamic capability discovery and updates
- Core tool integration (workflow, config management)
- Thread-safe concurrent operations
- Intelligent request routing to backend servers
## ServerRegistry
The ServerRegistry manages the collection of registered MCP servers and their cached capabilities. It provides thread-safe access to server information and maintains bidirectional name mappings for routing requests to the correct backend servers.
Features:
- Thread-safe server registration/deregistration
- Capability caching for performance optimization
- Server health tracking and connection status
- Efficient bulk operations for capability retrieval
- Update notifications for dynamic capability changes
## EventHandler
The EventHandler bridges the gap between the muster service orchestrator and the aggregator by automatically registering/deregistering MCP servers based on their health status. It ensures that only healthy, running services are exposed through the aggregator.
Event-driven behavior:
- Running + Healthy → Automatic registration
- Stopped/Failed/Unhealthy → Automatic deregistration
- Resilient to temporary failures
- Asynchronous processing for responsiveness
## NameTracker
The NameTracker implements intelligent name collision resolution through a consistent prefixing scheme. It maintains bidirectional mappings between exposed (prefixed) names and their original server/name combinations.
Naming scheme:
{muster_prefix}_{server_prefix}_{original_name}
Examples:
- Original: "list_files" from "github" server
- Exposed: "x_github_list_files" (with muster prefix "x")
- With custom prefix: "x_gh_list_files" (server prefix "gh")
Transport Protocols ¶
## Server-Sent Events (SSE)
SSE transport provides real-time communication over HTTP with automatic reconnection and keep-alive support. Ideal for web-based integrations and real-time applications.
Endpoints: - http://localhost:8080/sse (SSE stream) - http://localhost:8080/message (message posting)
## Standard I/O (stdio)
Stdio transport enables CLI integration by communicating over standard input/output. Perfect for command-line tools and shell integrations.
## Streamable HTTP
Streamable HTTP provides HTTP-based streaming protocol support with full bidirectional communication. This is the default transport for maximum compatibility.
Security Model ¶
## Denylist System
The aggregator implements a "secure by default" approach with a comprehensive denylist of potentially destructive tools. This prevents accidental execution of dangerous operations in production environments.
Categories of blocked operations:
- Kubernetes resource modification (kubectl apply, delete, patch)
- Cluster API lifecycle operations (create/delete clusters)
- Helm package management (install, uninstall, upgrade)
- Flux GitOps operations (reconcile, suspend, resume)
- System maintenance operations (cleanup, incident creation)
## Yolo Mode
The --yolo flag disables the security denylist for development environments where destructive operations may be needed. This should never be used in production.
config.Yolo = true // Disables all security restrictions
Integration with Muster Architecture ¶
## Central API Pattern
The aggregator follows the central API pattern for inter-package communication:
- Receives service state events through api.OrchestratorAPI
- Queries service information via api.ServiceRegistryHandler
- Publishes tool update events via api.PublishToolUpdateEvent
- Integrates with workflow manager through api interfaces
## Tool Update Events
The aggregator publishes ToolUpdateEvent notifications when its capability set changes, ensuring system-wide consistency with dependent components like ServiceClass and Capability managers.
Event flow: Backend server change → Registry update → Capability refresh → Event publication
## Workflow Integration
When configured with a config directory, the aggregator automatically integrates with the workflow system to expose workflow definitions as executable tools.
Performance Considerations ¶
## Capability Caching
Backend server capabilities are cached in memory to avoid repeated network calls. Caches are updated automatically when servers are registered/deregistered or when explicit refresh operations are performed.
## Batch Operations
The aggregator uses batch operations where possible to minimize the number of MCP protocol messages and improve performance with multiple backend servers.
## Background Processing
All registry updates and event processing happen asynchronously in background goroutines to ensure that the main request handling remains responsive.
Error Handling and Resilience ¶
## Graceful Degradation
The aggregator continues operating even when individual backend servers become unavailable. Healthy servers remain accessible while unhealthy servers are automatically deregistered.
## Retry Mechanisms
A periodic retry mechanism attempts to register servers that are healthy but not yet registered, providing resilience against temporary registration failures.
## Connection Management
Backend server connections are managed automatically with proper cleanup during deregistration and graceful shutdown procedures.
Monitoring and Observability ¶
## Service Data
The aggregator provides comprehensive service monitoring data including:
- Tool/resource/prompt counts and status
- Server connectivity statistics
- Security filtering statistics (blocked tools)
- Transport endpoint information
- Event handler status
## Logging
Structured logging provides visibility into:
- Server registration/deregistration events
- Capability update operations
- Security filtering actions
- Error conditions and recovery
Thread Safety ¶
All public APIs are thread-safe and can be called concurrently. Internal state is protected by appropriate synchronization mechanisms (mutexes, channels, etc.). The package is designed for high-concurrency environments.
Configuration ¶
The AggregatorConfig structure provides comprehensive configuration options:
type AggregatorConfig struct {
Port int // Server port (default: 8080)
Host string // Bind address (default: localhost)
Transport string // Protocol: "sse", "stdio", "streamable-http"
Yolo bool // Disable security denylist (development only)
ConfigDir string // Directory for workflow definitions
MusterPrefix string // Global prefix for all tools (default: "x")
}
Example: Complete Setup ¶
// Create configuration
config := AggregatorConfig{
Port: 8080,
Host: "localhost",
Transport: "sse",
Yolo: false,
ConfigDir: "/etc/muster/workflows",
MusterPrefix: "x",
}
// Initialize dependencies through central API
orchestratorAPI := api.GetOrchestrator()
serviceRegistry := api.GetServiceRegistry()
// Create and start aggregator
manager := NewAggregatorManager(config, orchestratorAPI, serviceRegistry)
if err := manager.Start(ctx); err != nil {
log.Fatal("Failed to start aggregator:", err)
}
defer manager.Stop(ctx)
// Access aggregator endpoint
endpoint := manager.GetEndpoint()
fmt.Printf("Aggregator running at: %s\n", endpoint)
The aggregator package is the cornerstone of muster's MCP integration, providing a robust, secure, and scalable foundation for tool aggregation and distribution.
Index ¶
- Constants
- func GenerateSessionID() (string, error)
- func IsValidUUIDv4(s string) bool
- func ShouldUseTokenExchange(serverInfo *ServerInfo) bool
- func ShouldUseTokenForwarding(serverInfo *ServerInfo) bool
- func ValidateSessionID(sessionID string) error
- func ValidateSessionIDStrict(sessionID string) error
- type AggregatorConfig
- type AggregatorManager
- func (am *AggregatorManager) GetAggregatorServer() *AggregatorServer
- func (am *AggregatorManager) GetEndpoint() string
- func (am *AggregatorManager) GetEventHandler() *EventHandler
- func (am *AggregatorManager) GetServiceData() map[string]interface{}
- func (am *AggregatorManager) ManualRefresh(ctx context.Context) error
- func (am *AggregatorManager) RegisterServerPendingAuth(serverName, url, toolPrefix string, authInfo *AuthInfo) error
- func (am *AggregatorManager) RegisterServerPendingAuthWithConfig(serverName, url, toolPrefix string, authInfo *AuthInfo, ...) error
- func (am *AggregatorManager) Start(ctx context.Context) error
- func (am *AggregatorManager) Stop(ctx context.Context) error
- func (am *AggregatorManager) UpgradeServerAfterAuth(ctx context.Context, serverName string, client MCPClient) error
- func (am *AggregatorManager) UpgradeSessionConnection(ctx context.Context, sessionID, serverName string, token oauth.RedactedToken) error
- type AggregatorServer
- func (a *AggregatorServer) CallToolInternal(ctx context.Context, toolName string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (a *AggregatorServer) DeregisterServer(name string) error
- func (a *AggregatorServer) GetAvailableTools() []string
- func (a *AggregatorServer) GetEndpoint() string
- func (a *AggregatorServer) GetPrompt(ctx context.Context, name string, args map[string]string) (*mcp.GetPromptResult, error)
- func (a *AggregatorServer) GetPrompts() []mcp.Prompt
- func (a *AggregatorServer) GetPromptsForSession(sessionID string) []mcp.Prompt
- func (a *AggregatorServer) GetRegistry() *ServerRegistry
- func (a *AggregatorServer) GetResources() []mcp.Resource
- func (a *AggregatorServer) GetResourcesForSession(sessionID string) []mcp.Resource
- func (a *AggregatorServer) GetSessionRegistry() *SessionRegistry
- func (a *AggregatorServer) GetTools() []mcp.Tool
- func (a *AggregatorServer) GetToolsForSession(sessionID string) []mcp.Tool
- func (a *AggregatorServer) GetToolsWithStatus() []ToolWithStatus
- func (a *AggregatorServer) IsToolAvailable(toolName string) bool
- func (a *AggregatorServer) IsYoloMode() bool
- func (a *AggregatorServer) ListPromptsForContext(ctx context.Context) []mcp.Prompt
- func (a *AggregatorServer) ListResourcesForContext(ctx context.Context) []mcp.Resource
- func (a *AggregatorServer) ListServersRequiringAuth(ctx context.Context) []api.ServerAuthInfo
- func (a *AggregatorServer) ListToolsForContext(ctx context.Context) []mcp.Tool
- func (a *AggregatorServer) NotifySessionPromptsChanged(sessionID string)
- func (a *AggregatorServer) NotifySessionResourcesChanged(sessionID string)
- func (a *AggregatorServer) NotifySessionToolsChanged(sessionID string)
- func (a *AggregatorServer) OnToolsUpdated(event api.ToolUpdateEvent)
- func (a *AggregatorServer) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- func (a *AggregatorServer) RegisterServer(ctx context.Context, name string, client MCPClient, toolPrefix string) error
- func (a *AggregatorServer) Start(ctx context.Context) error
- func (a *AggregatorServer) Stop(ctx context.Context) error
- func (a *AggregatorServer) ToggleToolBlock(toolName string) error
- func (a *AggregatorServer) UpdateCapabilities()
- type AuthInfo
- type AuthMetrics
- func (m *AuthMetrics) GetServerMetrics(serverName string) (AuthServerMetricView, bool)
- func (m *AuthMetrics) GetSummary() AuthMetricsSummary
- func (m *AuthMetrics) RecordLoginAttempt(serverName, sessionID string)
- func (m *AuthMetrics) RecordLoginFailure(serverName, sessionID, reason string)
- func (m *AuthMetrics) RecordLoginSuccess(serverName, sessionID string)
- func (m *AuthMetrics) RecordLogoutAttempt(serverName, sessionID string)
- func (m *AuthMetrics) RecordLogoutSuccess(serverName, sessionID string)
- func (m *AuthMetrics) RecordRateLimitBlock(serverName, sessionID string)
- type AuthMetricsSummary
- type AuthRateLimiter
- type AuthRateLimiterConfig
- type AuthServerMetricView
- type AuthStatus
- type AuthToolProvider
- type ConnectionAlreadyEstablishedError
- type ConnectionNotFoundError
- type ConnectionStatus
- type EventHandler
- type EventType
- type InvalidSessionIDError
- type MCPClient
- type NameTracker
- func (nt *NameTracker) GetExposedPromptName(serverName, promptName string) string
- func (nt *NameTracker) GetExposedResourceURI(serverName, resourceURI string) string
- func (nt *NameTracker) GetExposedToolName(serverName, toolName string) string
- func (nt *NameTracker) RebuildMappings(servers map[string]*ServerInfo)
- func (nt *NameTracker) ResolveName(exposedName string) (serverName, originalName string, itemType string, err error)
- func (nt *NameTracker) SetServerPrefix(serverName, prefix string)
- type OAuthProxyConfig
- type OAuthServerConfig
- type ProtectedResourceMetadata
- type RegistrationEvent
- type ServerInfo
- func (s *ServerInfo) GetNamespace() string
- func (s *ServerInfo) IsConnected() bool
- func (s *ServerInfo) SetConnected(connected bool)
- func (s *ServerInfo) UpdatePrompts(prompts []mcp.Prompt)
- func (s *ServerInfo) UpdateResources(resources []mcp.Resource)
- func (s *ServerInfo) UpdateTools(tools []mcp.Tool)
- type ServerRegistry
- func (r *ServerRegistry) Deregister(name string) error
- func (r *ServerRegistry) GetAllPrompts() []mcp.Prompt
- func (r *ServerRegistry) GetAllPromptsForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Prompt
- func (r *ServerRegistry) GetAllResources() []mcp.Resource
- func (r *ServerRegistry) GetAllResourcesForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Resource
- func (r *ServerRegistry) GetAllServers() map[string]*ServerInfo
- func (r *ServerRegistry) GetAllTools() []mcp.Tool
- func (r *ServerRegistry) GetAllToolsForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Tool
- func (r *ServerRegistry) GetClient(name string) (MCPClient, error)
- func (r *ServerRegistry) GetOAuthServers() []*ServerInfo
- func (r *ServerRegistry) GetServerInfo(name string) (*ServerInfo, bool)
- func (r *ServerRegistry) GetUpdateChannel() <-chan struct{}
- func (r *ServerRegistry) IsOAuthServer(serverName string) bool
- func (r *ServerRegistry) Register(ctx context.Context, name string, client MCPClient, toolPrefix string) error
- func (r *ServerRegistry) RegisterPendingAuth(name, url, toolPrefix string, authInfo *AuthInfo) error
- func (r *ServerRegistry) RegisterPendingAuthWithConfig(name, url, toolPrefix string, authInfo *AuthInfo, ...) error
- func (r *ServerRegistry) ResolvePromptName(exposedName string) (serverName, originalName string, err error)
- func (r *ServerRegistry) ResolveResourceName(exposedURI string) (serverName, originalURI string, err error)
- func (r *ServerRegistry) ResolveToolName(exposedName string) (serverName, originalName string, err error)
- func (r *ServerRegistry) UpgradeToConnected(ctx context.Context, name string, client MCPClient) error
- type ServerStatus
- type SessionConnection
- func (sc *SessionConnection) GetAuthStatus() AuthStatus
- func (sc *SessionConnection) GetConnectedAt() time.Time
- func (sc *SessionConnection) GetLastError() string
- func (sc *SessionConnection) GetPrompts() []mcp.Prompt
- func (sc *SessionConnection) GetResources() []mcp.Resource
- func (sc *SessionConnection) GetStatus() ConnectionStatus
- func (sc *SessionConnection) GetTools() []mcp.Tool
- func (sc *SessionConnection) IsTokenExpired(margin time.Duration) bool
- func (sc *SessionConnection) SetAuthStatus(status AuthStatus)
- func (sc *SessionConnection) SetAuthStatusWithError(status AuthStatus, errMsg string)
- func (sc *SessionConnection) SetTokenExpiresAt(t time.Time)
- func (sc *SessionConnection) UpdatePrompts(prompts []mcp.Prompt)
- func (sc *SessionConnection) UpdateResources(resources []mcp.Resource)
- func (sc *SessionConnection) UpdateTools(tools []mcp.Tool)
- type SessionConnectionResult
- type SessionIdentityMismatchError
- type SessionLimitExceededError
- type SessionNotFoundError
- type SessionRegistry
- func (sr *SessionRegistry) Count() int
- func (sr *SessionRegistry) CreateSessionForSubject(subject string) (*SessionState, error)
- func (sr *SessionRegistry) DeleteSession(sessionID string)
- func (sr *SessionRegistry) EndSSOInit(sessionID string)
- func (sr *SessionRegistry) GetAllSessions() map[string]*SessionState
- func (sr *SessionRegistry) GetAuthStatus(sessionID, serverName string) (AuthStatus, bool)
- func (sr *SessionRegistry) GetConnection(sessionID, serverName string) (*SessionConnection, bool)
- func (sr *SessionRegistry) GetOrCreateSession(sessionID string) *SessionState
- func (sr *SessionRegistry) GetOrCreateSessionWithError(sessionID string) (*SessionState, error)
- func (sr *SessionRegistry) GetSession(sessionID string) (*SessionState, bool)
- func (sr *SessionRegistry) HasSSOFailed(sessionID, serverName string) bool
- func (sr *SessionRegistry) IsSSOInitInProgress(sessionID string) bool
- func (sr *SessionRegistry) MarkSSOFailed(sessionID, serverName string)
- func (sr *SessionRegistry) RemoveServerFromAllSessions(serverName string) int
- func (sr *SessionRegistry) SetAuthStatus(sessionID, serverName string, status AuthStatus)
- func (sr *SessionRegistry) SetAuthStatusWithError(sessionID, serverName string, status AuthStatus, errMsg string)
- func (sr *SessionRegistry) SetConnection(sessionID, serverName string, conn *SessionConnection)
- func (sr *SessionRegistry) SetOnSessionRemoved(fn func(sessionID string))
- func (sr *SessionRegistry) SetPendingAuth(sessionID, serverName string)
- func (sr *SessionRegistry) StartSSOInit(sessionID string)
- func (sr *SessionRegistry) Stop()
- func (sr *SessionRegistry) UpgradeConnection(sessionID, serverName string, client MCPClient, tokenKey *oauth.TokenKey) error
- func (sr *SessionRegistry) ValidateSessionIdentity(sessionID, subject string) error
- type SessionState
- func (s *SessionState) CloseAllConnections()
- func (s *SessionState) GetAllConnections() map[string]*SessionConnection
- func (s *SessionState) GetConnectedServers() []string
- func (s *SessionState) GetConnection(serverName string) (*SessionConnection, bool)
- func (s *SessionState) GetPendingAuthServers() []string
- func (s *SessionState) RemoveConnection(serverName string)
- func (s *SessionState) SetConnection(serverName string, conn *SessionConnection)
- func (s *SessionState) UpdateActivity()
- func (s *SessionState) UpgradeConnection(serverName string, client MCPClient, tokenKey *oauth.TokenKey) error
- type TeleportClientResult
- type ToolWithStatus
Constants ¶
const ( // MaxSessionIDLength is the maximum allowed length for session IDs. // This prevents memory exhaustion attacks using extremely long session IDs. MaxSessionIDLength = 256 // DefaultMaxSessions is the default maximum number of concurrent sessions. // This provides DoS protection by limiting session creation. DefaultMaxSessions = 10000 )
Session ID validation constants.
const AuthStatusResourceURI = "auth://status"
AuthStatusResourceURI is the URI for the auth status MCP resource. This resource provides real-time authentication status for all MCP servers.
const DefaultSessionTimeout = 30 * time.Minute
DefaultSessionTimeout is the default timeout for idle session cleanup.
Variables ¶
This section is empty.
Functions ¶
func GenerateSessionID ¶ added in v0.1.27
GenerateSessionID creates a new cryptographically random UUID v4 session ID. Uses crypto/rand for secure random data per RFC 4122 Section 4.4.
func IsValidUUIDv4 ¶ added in v0.1.27
IsValidUUIDv4 checks if a string is a valid UUID v4 format.
func ShouldUseTokenExchange ¶
func ShouldUseTokenExchange(serverInfo *ServerInfo) bool
ShouldUseTokenExchange checks if RFC 8693 token exchange should be used for a server. Token exchange is enabled when:
- AuthConfig.TokenExchange is not nil
- AuthConfig.TokenExchange.Enabled is true
- Required fields (DexTokenEndpoint, ConnectorID) are set
Token exchange takes precedence over token forwarding if both are configured.
func ShouldUseTokenForwarding ¶
func ShouldUseTokenForwarding(serverInfo *ServerInfo) bool
ShouldUseTokenForwarding checks if token forwarding should be used for a server. Token forwarding is enabled when:
- AuthConfig.ForwardToken is true (forwardToken implies OAuth-based auth)
- OR: AuthConfig.Type is "oauth" and ForwardToken is true
Setting forwardToken: true implicitly enables OAuth authentication since token forwarding only makes sense in an OAuth context.
func ValidateSessionID ¶
ValidateSessionID checks if a session ID is valid.
A valid session ID must be:
- Non-empty
- Not longer than MaxSessionIDLength (256 bytes)
Returns an error describing the validation failure, or nil if valid.
func ValidateSessionIDStrict ¶ added in v0.1.27
ValidateSessionIDStrict checks if a session ID is a valid server-issued UUID v4. Returns an error if the session ID is empty, too long, or not in UUID v4 format.
Types ¶
type AggregatorConfig ¶
type AggregatorConfig struct {
// Port specifies the port number to listen on for the aggregated MCP endpoint
Port int
// Host specifies the host address to bind to (default: localhost)
Host string
// Transport defines the protocol to use for MCP communication.
// Supported values: "sse", "streamable-http", "stdio"
Transport string
// Yolo disables the security denylist for destructive tools.
// When true, all tools are allowed regardless of their destructive nature.
// This should only be enabled in development environments.
Yolo bool
// ConfigDir is the user configuration directory for workflows and other configs.
// This is used to load workflow definitions and make them available as tools.
ConfigDir string
// MusterPrefix is the global prefix applied to all aggregated tools.
// This helps distinguish muster tools from other MCP tools in mixed environments.
// Default value is "x".
MusterPrefix string
// Version is the muster server version to report in the MCP protocol handshake.
// This should be set to the build version during application initialization.
// Defaults to "dev" if not specified.
Version string
// OAuth configuration for remote MCP server authentication (client role)
OAuth OAuthProxyConfig
// OAuthServer configuration for protecting the Muster Server (resource server role)
OAuthServer OAuthServerConfig
// Debug enables debug logging
Debug bool
}
AggregatorConfig holds configuration args for the aggregator. This structure defines how the aggregator should behave and what endpoints it should expose.
type AggregatorManager ¶
type AggregatorManager struct {
// contains filtered or unexported fields
}
AggregatorManager provides a high-level interface for managing the aggregator server and coordinating automatic MCP server registration based on service health status.
The manager combines the aggregator server with event handling to provide:
- Automatic registration of healthy MCP servers
- Event-driven updates when service states change
- Periodic retry mechanisms for failed registrations
- Centralized lifecycle management
- OAuth proxy for remote MCP server authentication
It acts as the primary entry point for the aggregator functionality and integrates with the muster service architecture through the central API pattern.
func NewAggregatorManager ¶
func NewAggregatorManager(config AggregatorConfig, orchestratorAPI api.OrchestratorAPI, serviceRegistry api.ServiceRegistryHandler, errorCallback func(err error)) *AggregatorManager
NewAggregatorManager creates a new aggregator manager with the specified configuration.
The manager requires access to the orchestrator API for receiving service state events and the service registry for querying service information. These dependencies are provided through the central API pattern to maintain loose coupling.
Args:
- config: Configuration for the aggregator server behavior
- orchestratorAPI: Interface for receiving service lifecycle events
- serviceRegistry: Interface for querying service information
Returns a configured but not yet started aggregator manager.
func (*AggregatorManager) GetAggregatorServer ¶
func (am *AggregatorManager) GetAggregatorServer() *AggregatorServer
GetAggregatorServer returns the underlying aggregator server instance.
This method provides access to advanced aggregator operations that are not exposed through the manager interface. It should be used carefully and primarily for testing or debugging purposes.
Returns nil if the server is not initialized.
func (*AggregatorManager) GetEndpoint ¶
func (am *AggregatorManager) GetEndpoint() string
GetEndpoint returns the aggregator's MCP endpoint URL.
The endpoint format depends on the configured transport:
- SSE: http://host:port/sse
- Streamable HTTP: http://host:port/mcp
- Stdio: "stdio"
Returns an empty string if the aggregator server is not available.
func (*AggregatorManager) GetEventHandler ¶
func (am *AggregatorManager) GetEventHandler() *EventHandler
GetEventHandler returns the event handler instance.
This method is primarily intended for testing and debugging purposes to inspect the state of the event handling system.
Returns nil if the event handler is not initialized.
func (*AggregatorManager) GetServiceData ¶
func (am *AggregatorManager) GetServiceData() map[string]interface{}
GetServiceData returns comprehensive service monitoring data.
This method provides detailed information about the aggregator's current state, including configuration, connection status, tool/resource/prompt counts, and server statistics. The data is suitable for monitoring dashboards and health checks.
Returns a map containing various metrics and status information.
func (*AggregatorManager) ManualRefresh ¶
func (am *AggregatorManager) ManualRefresh(ctx context.Context) error
ManualRefresh manually triggers a re-synchronization of all healthy MCP servers.
This method can be useful for debugging or when you need to force a refresh of the server registrations outside of the normal event-driven flow. It performs the same operation as the initial sync during startup.
Args:
- ctx: Context for the refresh operation
Returns an error if the refresh operation fails.
func (*AggregatorManager) RegisterServerPendingAuth ¶
func (am *AggregatorManager) RegisterServerPendingAuth(serverName, url, toolPrefix string, authInfo *AuthInfo) error
RegisterServerPendingAuth registers a server that requires authentication. This creates a placeholder with a synthetic auth tool that users can call to initiate the OAuth flow.
Args:
- serverName: Unique name of the server
- url: The server endpoint URL
- toolPrefix: Server-specific prefix for tools
- authInfo: OAuth information from the 401 response
Returns an error if registration fails.
func (*AggregatorManager) RegisterServerPendingAuthWithConfig ¶
func (am *AggregatorManager) RegisterServerPendingAuthWithConfig(serverName, url, toolPrefix string, authInfo *AuthInfo, authConfig *api.MCPServerAuth) error
RegisterServerPendingAuthWithConfig registers a server that requires authentication with auth config. This is an extended version that also accepts auth config for SSO token forwarding.
Args:
- serverName: Unique name of the server
- url: The server endpoint URL
- toolPrefix: Server-specific prefix for tools
- authInfo: OAuth information from the 401 response
- authConfig: Auth configuration for token forwarding (may be nil)
Returns an error if registration fails.
func (*AggregatorManager) Start ¶
func (am *AggregatorManager) Start(ctx context.Context) error
Start initializes and starts the aggregator manager.
This method performs the following initialization sequence:
- Starts the underlying aggregator server
- Validates that required APIs are available
- Performs initial sync of healthy MCP servers
- Sets up event handling for automatic updates
- Starts periodic retry mechanism for failed registrations
The method is idempotent - calling it multiple times has no additional effect. Returns an error if any component fails to start.
func (*AggregatorManager) Stop ¶
func (am *AggregatorManager) Stop(ctx context.Context) error
Stop gracefully shuts down the aggregator manager.
This method stops all components in reverse order of startup:
- Cancels the context to signal shutdown to all goroutines
- Stops the event handler
- Stops the OAuth manager
- Stops the aggregator server
- Waits for all background operations to complete
The method is idempotent and can be called multiple times safely.
func (*AggregatorManager) UpgradeServerAfterAuth ¶
func (am *AggregatorManager) UpgradeServerAfterAuth(ctx context.Context, serverName string, client MCPClient) error
UpgradeServerAfterAuth upgrades a pending auth server to connected status after successful OAuth authentication. This is called when the OAuth callback is received and a token is available.
Note: This method upgrades the global server state. For session-scoped tool visibility, use UpgradeSessionConnection instead.
Args:
- ctx: Context for the operation
- serverName: Name of the server to upgrade
- client: The newly authenticated MCP client
Returns an error if upgrade fails.
func (*AggregatorManager) UpgradeSessionConnection ¶
func (am *AggregatorManager) UpgradeSessionConnection(ctx context.Context, sessionID, serverName string, token oauth.RedactedToken) error
UpgradeSessionConnection upgrades a session's connection to an OAuth server after successful authentication. This creates a session-specific MCP client with the user's token and fetches their available tools.
This implements session-scoped tool visibility as described in ADR-006.
Args:
- ctx: Context for the operation
- sessionID: The session to upgrade
- serverName: The server the session authenticated with
- token: The OAuth access token (wrapped in RedactedToken for safety)
Returns an error if the upgrade fails.
type AggregatorServer ¶
type AggregatorServer struct {
// contains filtered or unexported fields
}
AggregatorServer implements a comprehensive MCP server that aggregates multiple backend MCP servers.
The AggregatorServer is the core component responsible for:
- Collecting and exposing tools, resources, and prompts from multiple backend servers
- Managing multiple transport protocols (SSE, stdio, streamable-http)
- Integrating core muster tools alongside external MCP servers
- Providing intelligent name collision resolution
- Implementing security filtering through the denylist system
- Real-time capability updates when backend servers change
- Session-scoped tool visibility for OAuth-protected servers
Architecture: The server maintains a registry of backend MCP servers and dynamically updates its exposed capabilities as servers are registered/deregistered. It supports multiple transport protocols simultaneously and provides both external MCP compatibility and internal tool calling capabilities.
Session-Scoped Tool Visibility: For OAuth-protected servers, each user session maintains its own view of available tools based on which servers they have authenticated with. This is implemented via the SessionRegistry which tracks per-session connections and capabilities.
Thread Safety: All public methods are thread-safe and can be called concurrently. Internal state is protected by appropriate synchronization mechanisms.
func NewAggregatorServer ¶
func NewAggregatorServer(aggConfig AggregatorConfig, errorCallback func(error)) *AggregatorServer
NewAggregatorServer creates a new aggregator server with the specified configuration.
This constructor initializes all necessary components but does not start any servers. The returned server must be started with the Start method before it can handle requests.
The server is configured with:
- A server registry using the specified muster prefix
- A session registry for per-session state management (OAuth)
- Active item managers for tracking capabilities
- Default transport settings based on configuration
Args:
- aggConfig: Configuration args defining server behavior, transport, and security settings
Returns a configured but unstarted aggregator server ready for initialization.
func (*AggregatorServer) CallToolInternal ¶
func (a *AggregatorServer) CallToolInternal(ctx context.Context, toolName string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallToolInternal provides internal tool calling capability for muster components.
This method allows internal muster components to execute tools through the aggregator without going through the external MCP protocol. It supports both:
- Tools from registered backend servers (resolved through the registry)
- Core tools from muster components (called directly through providers)
The method performs intelligent tool resolution:
- First attempts to resolve the tool through the server registry
- If not found, checks if it's a core tool by name pattern
- Routes the call to the appropriate handler based on tool type
This internal calling mechanism is essential for:
- Inter-component communication within muster
- Workflow execution that needs to call other tools
- Administrative operations that require tool access
Args:
- ctx: Context for the tool execution
- toolName: Name of the tool to execute (may be prefixed)
- args: Arguments to pass to the tool as key-value pairs
Returns the tool execution result or an error if the tool cannot be found or executed.
func (*AggregatorServer) DeregisterServer ¶
func (a *AggregatorServer) DeregisterServer(name string) error
DeregisterServer removes a backend MCP server from the aggregator.
This method cleanly removes a backend server from the aggregator, which will cause all tools, resources, and prompts from that server to become unavailable. The backend client connection is closed as part of the deregistration process.
Additionally, this method cleans up any stale session connections for the server. This is critical for handling MCPServer renames, where the old server is deleted and a new one is created. Without this cleanup, session connections stored under the old server name would persist and cause stale auth status displays.
Args:
- name: Unique identifier of the server to remove
Returns an error if the server is not found or deregistration fails.
func (*AggregatorServer) GetAvailableTools ¶
func (a *AggregatorServer) GetAvailableTools() []string
GetAvailableTools implements the ToolAvailabilityChecker interface.
This method returns a comprehensive list of all tools currently available through the aggregator, including both external tools from backend servers and core tools from muster components. The returned list represents the complete tool inventory that can be used by workflows, capabilities, and other muster components.
The aggregation process:
- Collects all tools from registered backend servers via the registry
- Collects all core tools from muster component providers
- Combines both lists into a unified tool inventory
- Returns tool names (with appropriate prefixing applied)
This method is used by:
- Workflow manager for populating available tool lists
- Service class manager for tool validation
- Administrative interfaces for tool discovery
Returns a slice of tool names representing all available tools.
func (*AggregatorServer) GetEndpoint ¶
func (a *AggregatorServer) GetEndpoint() string
GetEndpoint returns the aggregator's primary endpoint URL based on the configured transport.
The endpoint format varies by transport type:
- SSE: http://host:port/sse (Server-Sent Events endpoint)
- Streamable HTTP: http://host:port/mcp (default HTTP streaming path)
- Stdio: "stdio" (indicates standard I/O communication)
This endpoint can be used by MCP clients to connect to the aggregator and access all aggregated capabilities from backend servers.
Returns the endpoint URL as a string, or "stdio" for standard I/O transport.
func (*AggregatorServer) GetPrompt ¶
func (a *AggregatorServer) GetPrompt(ctx context.Context, name string, args map[string]string) (*mcp.GetPromptResult, error)
GetPrompt executes a prompt with the provided arguments. This resolves the prompt name to its origin server and retrieves the prompt.
func (*AggregatorServer) GetPrompts ¶
func (a *AggregatorServer) GetPrompts() []mcp.Prompt
GetPrompts returns all available prompts from all sources with intelligent name prefixing.
This method aggregates prompts from all registered backend servers, applying smart prefixing similar to tools to avoid name conflicts. The prefixing ensures that prompts from different servers can coexist without naming collisions.
Returns a slice of MCP prompts ready for client consumption.
func (*AggregatorServer) GetPromptsForSession ¶
func (a *AggregatorServer) GetPromptsForSession(sessionID string) []mcp.Prompt
GetPromptsForSession returns a session-specific view of all available prompts.
Similar to GetToolsForSession, this returns prompts based on session authentication state.
func (*AggregatorServer) GetRegistry ¶
func (a *AggregatorServer) GetRegistry() *ServerRegistry
GetRegistry returns the server registry for direct access to backend server information.
This method provides access to the underlying registry for advanced operations such as inspecting server status, accessing raw capabilities, or performing administrative tasks. It should be used carefully to avoid disrupting the aggregator's normal operation.
Returns the ServerRegistry instance managing all backend servers.
func (*AggregatorServer) GetResources ¶
func (a *AggregatorServer) GetResources() []mcp.Resource
GetResources returns all available resources from all registered backend servers.
This method aggregates resources from all connected backend servers, applying appropriate URI prefixing to avoid conflicts. Resources maintain their original functionality while being properly namespaced within the aggregated environment.
Returns a slice of MCP resources ready for client access.
func (*AggregatorServer) GetResourcesForSession ¶
func (a *AggregatorServer) GetResourcesForSession(sessionID string) []mcp.Resource
GetResourcesForSession returns a session-specific view of all available resources.
Similar to GetToolsForSession, this returns resources based on session authentication state.
func (*AggregatorServer) GetSessionRegistry ¶
func (a *AggregatorServer) GetSessionRegistry() *SessionRegistry
GetSessionRegistry returns the session registry for per-session state management.
This method provides access to the session registry for managing per-session connections to OAuth-protected servers. It is used for session-scoped tool visibility and connection management.
Returns the SessionRegistry instance managing per-session state.
func (*AggregatorServer) GetTools ¶
func (a *AggregatorServer) GetTools() []mcp.Tool
GetTools returns all available tools from all sources with intelligent name prefixing.
This method aggregates tools from all registered backend servers, applying smart prefixing to avoid name conflicts. The prefixing is only applied when conflicts would otherwise occur, following the pattern: {muster_prefix}_{server_prefix}_{original_name}
Note: This returns the global tool view. For session-specific tool visibility, use GetToolsForSession instead.
Returns a slice of MCP tools ready for client consumption.
func (*AggregatorServer) GetToolsForSession ¶
func (a *AggregatorServer) GetToolsForSession(sessionID string) []mcp.Tool
GetToolsForSession returns a session-specific view of all available tools.
This method computes the tool view based on the session's authentication state:
- Global tools from servers that don't require authentication
- Tools from OAuth servers where the session has authenticated
- Synthetic auth tools for OAuth servers the session hasn't authenticated with
This implements per-session tool visibility as described in ADR-006.
Args:
- sessionID: The session to compute the tool view for
Returns a slice of MCP tools specific to this session.
func (*AggregatorServer) GetToolsWithStatus ¶
func (a *AggregatorServer) GetToolsWithStatus() []ToolWithStatus
GetToolsWithStatus returns all available tools along with their security blocking status.
This method provides enhanced tool information that includes whether each tool is blocked by the security denylist. The blocking status depends on:
- The tool's classification as destructive in the denylist
- The current yolo mode setting (yolo=true allows all tools)
The tool names are resolved to their original names (before prefixing) for accurate denylist checking, ensuring consistent security behavior regardless of how tools are exposed.
Returns a slice of ToolWithStatus containing both tool definitions and security status.
func (*AggregatorServer) IsToolAvailable ¶
func (a *AggregatorServer) IsToolAvailable(toolName string) bool
IsToolAvailable implements the ToolAvailabilityChecker interface.
This method determines whether a specific tool is available through the aggregator, checking both external backend servers (via the registry) and core muster tools (via name pattern matching). It provides a unified way for other components to verify tool availability before attempting to use them.
The check process:
- Attempts to resolve the tool through the server registry
- If not found, checks if it matches core tool naming patterns
- Returns true if found in either location
This method is used by:
- Workflow manager for validating workflow step tools
- Service class manager for tool availability validation
Args:
- toolName: Name of the tool to check (may be prefixed)
Returns true if the tool is available, false otherwise.
func (*AggregatorServer) IsYoloMode ¶
func (a *AggregatorServer) IsYoloMode() bool
IsYoloMode returns whether yolo mode is currently enabled.
Yolo mode disables the security denylist, allowing all tools to be executed regardless of their destructive potential. This mode should only be enabled in development or testing environments where the risk is acceptable.
Returns true if yolo mode is enabled, false if security filtering is active.
func (*AggregatorServer) ListPromptsForContext ¶
func (a *AggregatorServer) ListPromptsForContext(ctx context.Context) []mcp.Prompt
ListPromptsForContext returns all available prompts for the current session context. This is used by the metatools package to provide session-scoped prompt visibility.
func (*AggregatorServer) ListResourcesForContext ¶
func (a *AggregatorServer) ListResourcesForContext(ctx context.Context) []mcp.Resource
ListResourcesForContext returns all available resources for the current session context. This is used by the metatools package to provide session-scoped resource visibility.
func (*AggregatorServer) ListServersRequiringAuth ¶
func (a *AggregatorServer) ListServersRequiringAuth(ctx context.Context) []api.ServerAuthInfo
ListServersRequiringAuth returns a list of servers that require authentication for the current session. This enables the list_tools meta-tool to inform users about servers that are available but require authentication before their tools become visible.
The method checks each registered server and returns those that:
- Have StatusAuthRequired status
- The session has not yet authenticated to
This is part of the server-side meta-tools migration (Issue #343) to provide better visibility into which servers need authentication.
func (*AggregatorServer) ListToolsForContext ¶
func (a *AggregatorServer) ListToolsForContext(ctx context.Context) []mcp.Tool
ListToolsForContext returns all available tools for the current session context. This is used by the metatools package to provide session-scoped tool visibility.
The method extracts the session ID from the context and returns tools appropriate for that session's authentication state. This includes:
- MCP server tools (prefixed with x_<server>_)
- Core muster tools (prefixed with core_) from internal providers
The core tools are collected from workflow, service, config, serviceclass, mcpserver, events, and auth providers.
func (*AggregatorServer) NotifySessionPromptsChanged ¶
func (a *AggregatorServer) NotifySessionPromptsChanged(sessionID string)
NotifySessionPromptsChanged sends a prompts/list_changed notification to a specific session.
func (*AggregatorServer) NotifySessionResourcesChanged ¶
func (a *AggregatorServer) NotifySessionResourcesChanged(sessionID string)
NotifySessionResourcesChanged sends a resources/list_changed notification to a specific session.
func (*AggregatorServer) NotifySessionToolsChanged ¶
func (a *AggregatorServer) NotifySessionToolsChanged(sessionID string)
NotifySessionToolsChanged sends a tools/list_changed notification to a specific session.
This method is used to notify a specific session that their tool list has changed, typically after they complete OAuth authentication with a new server. This implements targeted notifications as described in ADR-006, avoiding broadcast to all sessions.
Args:
- sessionID: The session to notify
func (*AggregatorServer) OnToolsUpdated ¶
func (a *AggregatorServer) OnToolsUpdated(event api.ToolUpdateEvent)
OnToolsUpdated implements the ToolUpdateSubscriber interface for handling tool change events.
This method responds to tool update events from other muster components, particularly the workflow manager, to maintain synchronization of the aggregator's exposed capabilities with the current tool landscape.
Event Processing:
- Filters events to focus on workflow-related tool changes
- Triggers capability refresh for workflow tool updates
- Uses asynchronous processing with a small delay to avoid mutex conflicts
- Logs all received events for debugging and monitoring
The asynchronous processing pattern ensures that:
- The event publisher (workflow manager) doesn't block waiting for aggregator updates
- Mutex conflicts are avoided by allowing the publisher to complete first
- Capability updates happen promptly but safely
Args:
- event: Tool update event containing change information, tool lists, and metadata
The method processes events selectively, focusing on workflow manager events that indicate changes to workflow-based tools.
func (*AggregatorServer) ReadResource ¶
func (a *AggregatorServer) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
ReadResource retrieves the contents of a resource by URI. This resolves the resource URI to its origin server and reads the content.
func (*AggregatorServer) RegisterServer ¶
func (a *AggregatorServer) RegisterServer(ctx context.Context, name string, client MCPClient, toolPrefix string) error
RegisterServer registers a new backend MCP server with the aggregator.
This method adds a backend MCP server to the aggregator's registry, making its tools, resources, and prompts available through the aggregated interface. The registration process includes client initialization and capability discovery.
Args:
- ctx: Context for the registration operation and capability queries
- name: Unique identifier for the server within the aggregator
- client: MCP client interface for communicating with the backend server
- toolPrefix: Server-specific prefix for name collision resolution
Returns an error if registration fails due to naming conflicts, client issues, or communication problems with the backend server.
func (*AggregatorServer) Start ¶
func (a *AggregatorServer) Start(ctx context.Context) error
Start initializes and starts the aggregator server with all configured transports.
This method performs a comprehensive startup sequence:
- Creates and configures the core MCP server with full capabilities
- Initializes workflow adapter if config directory is provided
- Starts background monitoring of registry updates
- Subscribes to tool update events from other muster components
- Performs initial capability discovery and registration
- Starts the appropriate transport server(s) based on configuration
Transport Support:
- SSE: Server-Sent Events with HTTP endpoints (/sse, /message)
- Stdio: Standard input/output for CLI integration
- Streamable HTTP: HTTP-based streaming protocol (default)
The method is idempotent for the same context - calling it multiple times with the same context will return an error indicating the server is already started.
Args:
- ctx: Context for controlling the server lifecycle and coordinating shutdown
Returns an error if startup fails at any stage, or nil on successful startup.
func (*AggregatorServer) Stop ¶
func (a *AggregatorServer) Stop(ctx context.Context) error
Stop gracefully shuts down the aggregator server and all its components.
This method performs a coordinated shutdown sequence:
- Cancels the context to signal shutdown to all background routines
- Shuts down all transport servers with a timeout
- Waits for background routines to complete
- Deregisters all backend servers to clean up connections
- Resets internal state to allow for restart
The shutdown process includes:
- Graceful shutdown of HTTP-based transports with a 5-second timeout
- Automatic shutdown of stdio transport via context cancellation
- Cleanup of all registered backend MCP servers
- Synchronization with background monitoring routines
The method is idempotent - calling it multiple times is safe and will not cause errors or duplicate cleanup operations.
Args:
- ctx: Context for controlling the shutdown timeout and operations
Returns an error if shutdown encounters issues, though cleanup continues regardless.
func (*AggregatorServer) ToggleToolBlock ¶
func (a *AggregatorServer) ToggleToolBlock(toolName string) error
ToggleToolBlock toggles the blocked status of a specific tool (placeholder implementation).
This method is intended to provide runtime control over individual tool blocking, allowing administrators to override the default denylist behavior for specific tools. Currently, this functionality is not fully implemented and returns an error.
Future Enhancement: The full implementation would maintain a runtime override list that could selectively enable or disable specific tools regardless of the global yolo setting.
Args:
- toolName: Name of the tool to toggle blocking status for
Returns an error indicating the feature is not yet implemented.
func (*AggregatorServer) UpdateCapabilities ¶
func (a *AggregatorServer) UpdateCapabilities()
UpdateCapabilities provides public access to capability updates for external components.
This method exposes the internal updateCapabilities functionality to allow other muster components (particularly the workflow manager) to trigger capability refreshes when they detect changes in their tool inventory.
The method is thread-safe and can be called concurrently without causing issues. It performs the same comprehensive capability update as the internal method, including cleanup of obsolete items and addition of new capabilities.
Use Cases:
- Workflow manager triggering updates when workflow definitions change
- Administrative tools forcing capability refresh
- Integration testing scenarios requiring capability synchronization
This is a lightweight wrapper around the internal updateCapabilities method.
type AuthInfo ¶
AuthInfo is an alias to the mcpserver AuthInfo type for OAuth authentication. It contains OAuth authentication information extracted from a 401 response. See mcpserver.AuthInfo for detailed field documentation.
type AuthMetrics ¶
type AuthMetrics struct {
// contains filtered or unexported fields
}
AuthMetrics tracks authentication-related metrics for monitoring and alerting.
This provides visibility into authentication patterns, failures, and potential abuse. Metrics are tracked per-server to enable targeted alerting and debugging.
func NewAuthMetrics ¶
func NewAuthMetrics() *AuthMetrics
NewAuthMetrics creates a new AuthMetrics instance.
func (*AuthMetrics) GetServerMetrics ¶
func (m *AuthMetrics) GetServerMetrics(serverName string) (AuthServerMetricView, bool)
GetServerMetrics returns metrics for a specific server.
func (*AuthMetrics) GetSummary ¶
func (m *AuthMetrics) GetSummary() AuthMetricsSummary
GetSummary returns a summary of all authentication metrics.
func (*AuthMetrics) RecordLoginAttempt ¶
func (m *AuthMetrics) RecordLoginAttempt(serverName, sessionID string)
RecordLoginAttempt records an authentication login attempt.
Args:
- serverName: Name of the server being authenticated to
- sessionID: The session making the attempt (for logging, truncated)
func (*AuthMetrics) RecordLoginFailure ¶
func (m *AuthMetrics) RecordLoginFailure(serverName, sessionID, reason string)
RecordLoginFailure records a failed authentication attempt.
Args:
- serverName: Name of the server where authentication failed
- sessionID: The session that failed (for logging, truncated)
- reason: The reason for the failure
func (*AuthMetrics) RecordLoginSuccess ¶
func (m *AuthMetrics) RecordLoginSuccess(serverName, sessionID string)
RecordLoginSuccess records a successful authentication.
Args:
- serverName: Name of the server authenticated to
- sessionID: The session that authenticated (for logging, truncated)
func (*AuthMetrics) RecordLogoutAttempt ¶
func (m *AuthMetrics) RecordLogoutAttempt(serverName, sessionID string)
RecordLogoutAttempt records a logout attempt.
Args:
- serverName: Name of the server being logged out from
- sessionID: The session making the attempt (for logging, truncated)
func (*AuthMetrics) RecordLogoutSuccess ¶
func (m *AuthMetrics) RecordLogoutSuccess(serverName, sessionID string)
RecordLogoutSuccess records a successful logout.
Args:
- serverName: Name of the server logged out from
- sessionID: The session that logged out (for logging, truncated)
func (*AuthMetrics) RecordRateLimitBlock ¶
func (m *AuthMetrics) RecordRateLimitBlock(serverName, sessionID string)
RecordRateLimitBlock records when a session was rate limited.
Args:
- serverName: Name of the server the session was trying to authenticate to
- sessionID: The session that was blocked (for logging, truncated)
type AuthMetricsSummary ¶
type AuthMetricsSummary struct {
TotalLoginAttempts int64 `json:"total_login_attempts"`
TotalLoginSuccesses int64 `json:"total_login_successes"`
TotalLoginFailures int64 `json:"total_login_failures"`
TotalRateLimitBlocks int64 `json:"total_rate_limit_blocks"`
TotalLogoutAttempts int64 `json:"total_logout_attempts"`
TotalLogoutSuccesses int64 `json:"total_logout_successes"`
PerServerMetrics []AuthServerMetricView `json:"per_server_metrics"`
}
AuthMetricsSummary provides a summary of authentication metrics.
type AuthRateLimiter ¶
type AuthRateLimiter struct {
// contains filtered or unexported fields
}
AuthRateLimiter provides per-session rate limiting for authentication operations. This prevents OAuth flow abuse by limiting the number of auth attempts per session.
Rate limiting is implemented using a sliding window approach:
- Each session can make at most MaxAuthAttempts auth attempts within the time window
- Attempts are tracked per session, not globally
- Old attempts are automatically cleaned up via a background goroutine
Callers MUST call Stop() when done to prevent goroutine leaks.
func NewAuthRateLimiter ¶
func NewAuthRateLimiter(config AuthRateLimiterConfig) *AuthRateLimiter
NewAuthRateLimiter creates a new rate limiter with the given configuration. It starts a background goroutine that periodically calls Cleanup() to remove stale entries. Callers MUST call Stop() when done to prevent goroutine leaks.
func (*AuthRateLimiter) Allow ¶
func (rl *AuthRateLimiter) Allow(sessionID, serverName string) bool
Allow checks if an auth attempt is allowed for the given session. If allowed, the attempt is recorded and true is returned. If rate limited, false is returned and the attempt is NOT recorded.
Args:
- sessionID: The session making the auth attempt
- serverName: The server being authenticated to (for logging)
Returns true if the attempt is allowed, false if rate limited.
func (*AuthRateLimiter) Cleanup ¶
func (rl *AuthRateLimiter) Cleanup()
Cleanup removes stale entries from the rate limiter. This is called periodically by the background cleanup goroutine.
func (*AuthRateLimiter) RemainingAttempts ¶
func (rl *AuthRateLimiter) RemainingAttempts(sessionID string) int
RemainingAttempts returns the number of remaining auth attempts for a session.
func (*AuthRateLimiter) Reset ¶
func (rl *AuthRateLimiter) Reset(sessionID string)
Reset clears all rate limiting state for a session. This can be called after successful authentication to reset the counter.
func (*AuthRateLimiter) Stop ¶ added in v0.1.34
func (rl *AuthRateLimiter) Stop()
Stop terminates the background cleanup goroutine. It is safe to call Stop multiple times.
type AuthRateLimiterConfig ¶
type AuthRateLimiterConfig struct {
// MaxAttempts is the maximum number of auth attempts per session within the window.
// Default: 10 attempts
MaxAttempts int
// Window is the time window for rate limiting.
// Default: 1 minute
Window time.Duration
}
AuthRateLimiterConfig holds configuration for the rate limiter.
func DefaultAuthRateLimiterConfig ¶
func DefaultAuthRateLimiterConfig() AuthRateLimiterConfig
DefaultAuthRateLimiterConfig returns the default rate limiter configuration.
type AuthServerMetricView ¶
type AuthServerMetricView struct {
ServerName string `json:"server_name"`
LoginAttempts int64 `json:"login_attempts"`
LoginSuccesses int64 `json:"login_successes"`
LoginFailures int64 `json:"login_failures"`
RateLimitBlocks int64 `json:"rate_limit_blocks"`
LogoutAttempts int64 `json:"logout_attempts"`
LogoutSuccesses int64 `json:"logout_successes"`
LastAttemptAt time.Time `json:"last_attempt_at,omitempty"`
LastSuccessAt time.Time `json:"last_success_at,omitempty"`
LastFailureAt time.Time `json:"last_failure_at,omitempty"`
}
AuthServerMetricView is a read-only view of server-specific auth metrics.
type AuthStatus ¶
type AuthStatus string
AuthStatus represents the authentication status of a session to a server. This is per-user session state tracked in the Session Registry (not in CRD).
This separation allows:
- Multiple users to have different auth states for the same server
- The CRD to reflect infrastructure state only (State: Running/Connected/Failed/etc.)
- Proper multi-tenant support without auth state race conditions
const ( // AuthStatusAuthenticated indicates the user has successfully authenticated. AuthStatusAuthenticated AuthStatus = "authenticated" // AuthStatusAuthRequired indicates authentication is required to access the server. AuthStatusAuthRequired AuthStatus = "auth_required" // AuthStatusTokenExpired indicates the user's token has expired and re-authentication is needed. AuthStatusTokenExpired AuthStatus = "token_expired" // AuthStatusUnknown indicates the authentication status cannot be determined. AuthStatusUnknown AuthStatus = "unknown" )
type AuthToolProvider ¶
type AuthToolProvider struct {
// contains filtered or unexported fields
}
AuthToolProvider provides core authentication tools for the aggregator. These tools allow users to authenticate to OAuth-protected MCP servers through `core_auth_login` and `core_auth_logout` commands.
This implements ADR-008: Authentication is a muster platform concern, not an MCP server concern. Instead of synthetic per-server authenticate tools, we use core tools that take a server parameter.
func NewAuthToolProvider ¶
func NewAuthToolProvider(aggregator *AggregatorServer) *AuthToolProvider
NewAuthToolProvider creates a new authentication tool provider.
func (*AuthToolProvider) ExecuteTool ¶
func (p *AuthToolProvider) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
ExecuteTool executes an authentication tool by name.
type ConnectionAlreadyEstablishedError ¶
type ConnectionAlreadyEstablishedError struct {
ServerName string
}
ConnectionAlreadyEstablishedError is returned when attempting to upgrade a connection that is already in connected state.
func (*ConnectionAlreadyEstablishedError) Error ¶
func (e *ConnectionAlreadyEstablishedError) Error() string
type ConnectionNotFoundError ¶
type ConnectionNotFoundError struct {
ServerName string
}
ConnectionNotFoundError is returned when a connection is not found.
func (*ConnectionNotFoundError) Error ¶
func (e *ConnectionNotFoundError) Error() string
type ConnectionStatus ¶
type ConnectionStatus string
ConnectionStatus represents the connection status of a session to a server. This is per-user session state, NOT infrastructure state (which is in MCPServer CRD State).
const ( // StatusSessionConnected indicates the session is connected to the server. StatusSessionConnected ConnectionStatus = "connected" // StatusSessionDisconnected indicates the session is not connected to the server. StatusSessionDisconnected ConnectionStatus = "disconnected" // StatusSessionPendingAuth indicates the session is waiting for authentication. StatusSessionPendingAuth ConnectionStatus = "pending_auth" // StatusSessionFailed indicates the session failed to connect to the server. StatusSessionFailed ConnectionStatus = "failed" )
type EventHandler ¶
type EventHandler struct {
// contains filtered or unexported fields
}
EventHandler manages automatic MCP server registration based on service lifecycle events.
The event handler bridges the gap between the muster service orchestrator and the aggregator by listening for service state changes and automatically registering or deregistering MCP servers as they become healthy or unhealthy.
Key responsibilities:
- Subscribe to orchestrator service state changes
- Filter events to only process MCP service changes
- Automatically register healthy running MCP servers
- Automatically deregister unhealthy or stopped MCP servers
- Skip global registration for SSO-based servers (handled at session level)
- Maintain separation of concerns through callback functions
The handler operates asynchronously and is designed to be resilient to temporary failures in the registration process.
func NewEventHandler ¶
func NewEventHandler( orchestratorAPI api.OrchestratorAPI, registerFunc func(context.Context, string) error, deregisterFunc func(string) error, isServerAuthRequired func(string) bool, isServerSSOBased func(string) bool, ) *EventHandler
NewEventHandler creates a new event handler with the specified dependencies and callbacks.
The event handler uses callback functions to maintain loose coupling with the aggregator manager. This design allows the handler to focus solely on event processing while delegating the actual registration logic to the caller.
Args:
- orchestratorAPI: Interface for subscribing to service state changes
- registerFunc: Callback function to register a server by name
- deregisterFunc: Callback function to deregister a server by name
- isServerAuthRequired: Optional callback to check if server is in auth_required state
- isServerSSOBased: Optional callback to check if server uses SSO token forwarding/exchange
Returns a configured but not yet started event handler.
func (*EventHandler) IsRunning ¶
func (eh *EventHandler) IsRunning() bool
IsRunning returns whether the event handler is currently active.
This method is thread-safe and can be used to check the handler's status for monitoring or debugging purposes.
Returns true if the event handler is currently processing events.
func (*EventHandler) Start ¶
func (eh *EventHandler) Start(ctx context.Context) error
Start begins listening for orchestrator events and processing them asynchronously.
This method subscribes to service state change events from the orchestrator and starts a background goroutine to process them. The method is idempotent - calling it multiple times has no additional effect.
The event processing continues until the provided context is cancelled or the Stop method is called.
Args:
- ctx: Context for controlling the event handler lifecycle
Returns nil on successful startup. The method does not wait for event processing to complete, as that happens asynchronously.
func (*EventHandler) Stop ¶
func (eh *EventHandler) Stop() error
Stop gracefully shuts down the event handler and waits for cleanup to complete.
This method cancels the event processing context and waits for the background goroutine to finish processing any in-flight events. The method is idempotent and can be called multiple times safely.
Returns nil after successful shutdown.
type EventType ¶
type EventType int
EventType represents the type of registration event. This enumeration defines the possible state changes for server registration.
type InvalidSessionIDError ¶
type InvalidSessionIDError struct {
Reason string
}
InvalidSessionIDError is returned when a session ID fails validation.
func (*InvalidSessionIDError) Error ¶
func (e *InvalidSessionIDError) Error() string
type MCPClient ¶
type MCPClient interface {
// Initialize establishes the connection and performs protocol handshake.
// This must be called before any other operations on the client.
// Returns an error if the handshake fails or connection cannot be established.
Initialize(ctx context.Context) error
// Close cleanly shuts down the client connection.
// This should be called when the client is no longer needed
// to ensure proper cleanup of resources.
Close() error
// ListTools returns all available tools from the server.
// This is used to discover what capabilities the server provides.
ListTools(ctx context.Context) ([]mcp.Tool, error)
// CallTool executes a specific tool and returns the result.
// The name arg should match one of the tools returned by ListTools.
// The args arg contains the tool-specific arguments as key-value pairs.
CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
// ListResources returns all available resources from the server.
// Resources are data sources that can be read by the client.
ListResources(ctx context.Context) ([]mcp.Resource, error)
// ReadResource retrieves a specific resource by its URI.
// The URI should match one of the resources returned by ListResources.
ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
// ListPrompts returns all available prompts from the server.
// Prompts are templates or structured text that can be retrieved and used.
ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
// GetPrompt retrieves a specific prompt with optional arguments.
// The name should match one of the prompts returned by ListPrompts.
// Args can be used to customize the prompt content.
GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
// Ping checks if the server is responsive.
// This is used for health checking and connection validation.
Ping(ctx context.Context) error
}
MCPClient defines the interface for MCP client operations. This interface abstracts the underlying MCP client implementation and will be implemented by the client in the mcpserver package. It provides all necessary operations for interacting with MCP servers including initialization, tool execution, and resource/prompt access.
type NameTracker ¶
type NameTracker struct {
// contains filtered or unexported fields
}
NameTracker manages intelligent name prefixing and resolution for MCP capabilities.
The name tracker solves the problem of name collisions when multiple MCP servers provide tools, prompts, or resources with the same names. It implements a consistent prefixing scheme and maintains bidirectional mappings between exposed (prefixed) names and their original server/name combinations.
Naming scheme:
{muster_prefix}_{server_prefix}_{original_name}
For example:
- Original tool: "list_files" from server "github"
- Server prefix: "gh" (configured) or "github" (default)
- Exposed name: "x_gh_list_files" (with muster prefix "x")
The tracker is thread-safe and supports concurrent operations.
func NewNameTracker ¶
func NewNameTracker(musterPrefix string) *NameTracker
NewNameTracker creates a new name tracker with the specified global prefix.
The muster prefix is applied to all exposed capabilities to distinguish them from other MCP tools in mixed environments. If no prefix is provided, "x" is used as the default.
Args:
- musterPrefix: Global prefix for all aggregated capabilities (defaults to "x")
Returns a new name tracker ready for use.
func (*NameTracker) GetExposedPromptName ¶
func (nt *NameTracker) GetExposedPromptName(serverName, promptName string) string
GetExposedPromptName returns the fully prefixed name for a prompt.
This method applies both server-specific and muster prefixes to create a globally unique prompt name. It also maintains the internal mapping for later resolution.
The naming pattern is: {muster_prefix}_{server_prefix}_{original_name}
Args:
- serverName: Name of the server providing the prompt
- promptName: Original prompt name from the server
Returns the exposed prompt name that clients will see.
func (*NameTracker) GetExposedResourceURI ¶
func (nt *NameTracker) GetExposedResourceURI(serverName, resourceURI string) string
GetExposedResourceURI returns the fully prefixed URI for a resource.
This method handles resource URI prefixing with special consideration for URIs that already contain schemes (like http:// or file://). Such URIs are left unchanged to preserve their functionality.
For simple resource identifiers, the standard prefixing pattern is applied.
Args:
- serverName: Name of the server providing the resource
- resourceURI: Original resource URI from the server
Returns the exposed resource URI that clients will see.
func (*NameTracker) GetExposedToolName ¶
func (nt *NameTracker) GetExposedToolName(serverName, toolName string) string
GetExposedToolName returns the fully prefixed name for a tool.
This method applies both server-specific and muster prefixes to create a globally unique tool name. It also maintains the internal mapping for later resolution.
The naming pattern is: {muster_prefix}_{server_prefix}_{original_name}
Args:
- serverName: Name of the server providing the tool
- toolName: Original tool name from the server
Returns the exposed tool name that clients will see.
func (*NameTracker) RebuildMappings ¶
func (nt *NameTracker) RebuildMappings(servers map[string]*ServerInfo)
RebuildMappings is a legacy method maintained for backward compatibility.
In the current implementation, name mappings are maintained automatically as capabilities are registered, so this method is no longer needed. It is kept to avoid breaking existing code that might call it.
Args:
- servers: Map of server information (unused in current implementation)
func (*NameTracker) ResolveName ¶
func (nt *NameTracker) ResolveName(exposedName string) (serverName, originalName string, itemType string, err error)
ResolveName resolves an exposed (prefixed) name back to its server and original name.
This method performs the reverse operation of the Get*Name methods, taking an exposed name and determining which server provided it and what the original name was before prefixing.
This is essential for routing requests to the correct backend server.
Args:
- exposedName: The prefixed name as seen by clients
Returns the server name, original name, item type, and nil error if successful. Returns empty strings and an error if the name cannot be resolved.
func (*NameTracker) SetServerPrefix ¶
func (nt *NameTracker) SetServerPrefix(serverName, prefix string)
SetServerPrefix configures the prefix to use for a specific server.
Server prefixes allow customization of how capabilities from different servers are distinguished. If no prefix is configured for a server, the server name itself is used as the prefix.
This method is thread-safe and can be called while the tracker is in use.
Args:
- serverName: Unique identifier of the server
- prefix: Prefix to use for this server's capabilities (uses server name if empty)
type OAuthProxyConfig ¶
type OAuthProxyConfig struct {
// Enabled controls whether OAuth proxy functionality is active.
Enabled bool
// PublicURL is the publicly accessible URL of the Muster Server.
// This is used to construct OAuth callback URLs.
PublicURL string
// ClientID is the OAuth client identifier (CIMD URL).
ClientID string
// CallbackPath is the path for the OAuth callback endpoint.
CallbackPath string
// CAFile is the path to a CA certificate file for verifying TLS connections.
// This is useful when connecting to OAuth servers with self-signed certificates.
CAFile string
}
OAuthProxyConfig holds OAuth proxy configuration for the aggregator.
type OAuthServerConfig ¶
type OAuthServerConfig struct {
// Enabled controls whether OAuth server protection is active.
Enabled bool
// Config holds the full OAuth server configuration.
// This is populated from the config.OAuthServerConfig during initialization.
Config interface{}
}
OAuthServerConfig holds OAuth server configuration for protecting the Muster Server. This is a simplified configuration that references the full config from the config package.
type ProtectedResourceMetadata ¶
type ProtectedResourceMetadata struct {
// Issuer is the authorization server URL
Issuer string
// Scope is the space-separated list of required scopes
Scope string
}
ProtectedResourceMetadata contains OAuth information discovered from the /.well-known/oauth-protected-resource endpoint.
type RegistrationEvent ¶
type RegistrationEvent struct {
// Type indicates whether this is a registration or deregistration event
Type EventType
// ServerName is the unique identifier of the server involved in the event
ServerName string
// Client is the MCP client associated with the server (may be nil for deregistration)
Client MCPClient
}
RegistrationEvent represents a server registration or deregistration event. These events are used internally to coordinate between different components when servers are added or removed from the aggregator.
type ServerInfo ¶
type ServerInfo struct {
// Name is the unique identifier for this server within the aggregator
Name string
// Namespace is the Kubernetes namespace for this server.
// This is used for event emission and resource references.
// Defaults to "default" if not specified.
Namespace string
// Client is the MCP client instance used to communicate with the server
Client MCPClient
// LastUpdate tracks when the server information was last refreshed
LastUpdate time.Time
// ToolPrefix is the configured prefix for tools from this server.
// This is used for name collision resolution.
ToolPrefix string
// URL is the server endpoint URL (for remote servers)
URL string
// Status indicates the server's connection/authentication status.
// Can be connected, disconnected, or auth_required.
Status ServerStatus
// AuthInfo contains OAuth information if authentication is required.
// This is populated when a 401 is received during initialization.
AuthInfo *AuthInfo
// AuthConfig contains the authentication configuration for this server.
// This is used to determine token forwarding behavior for SSO.
AuthConfig *api.MCPServerAuth
Tools []mcp.Tool // Cached list of available tools
Resources []mcp.Resource // Cached list of available resources
Prompts []mcp.Prompt // Cached list of available prompts
Connected bool // Current connection status (deprecated, use Status)
// contains filtered or unexported fields
}
ServerInfo contains information about a registered MCP server. This structure maintains both the connection details and cached capabilities for efficient access. It is thread-safe for concurrent access to cached data.
func (*ServerInfo) GetNamespace ¶
func (s *ServerInfo) GetNamespace() string
GetNamespace returns the namespace for this server. Returns "default" if the namespace is not set.
func (*ServerInfo) IsConnected ¶
func (s *ServerInfo) IsConnected() bool
IsConnected returns the current connection status. This method is thread-safe and can be called concurrently.
func (*ServerInfo) SetConnected ¶
func (s *ServerInfo) SetConnected(connected bool)
SetConnected safely updates the connection status. This is used to track whether the server is currently available for operations.
func (*ServerInfo) UpdatePrompts ¶
func (s *ServerInfo) UpdatePrompts(prompts []mcp.Prompt)
UpdatePrompts safely updates the server's cached prompt list. This method is thread-safe and should be used whenever the server's available prompts change.
func (*ServerInfo) UpdateResources ¶
func (s *ServerInfo) UpdateResources(resources []mcp.Resource)
UpdateResources safely updates the server's cached resource list. This method is thread-safe and should be used whenever the server's available resources change.
func (*ServerInfo) UpdateTools ¶
func (s *ServerInfo) UpdateTools(tools []mcp.Tool)
UpdateTools safely updates the server's cached tool list. This method is thread-safe and should be used whenever the server's available tools change.
type ServerRegistry ¶
type ServerRegistry struct {
// contains filtered or unexported fields
}
ServerRegistry manages the collection of registered MCP servers and their capabilities.
The registry maintains a thread-safe mapping of server names to their information, including cached capabilities (tools, resources, prompts) and connection status. It provides intelligent name resolution with prefixing to avoid conflicts between servers that might have tools with the same names.
Key responsibilities:
- Server lifecycle management (registration/deregistration)
- Capability caching for performance
- Name collision resolution through prefixing
- Thread-safe access to server information
- Update notifications for capability changes
func NewServerRegistry ¶
func NewServerRegistry(musterPrefix string) *ServerRegistry
NewServerRegistry creates a new server registry with the specified global prefix.
The registry uses the musterPrefix to ensure all exposed capabilities are prefixed appropriately to distinguish them from other MCP tools in the environment.
Args:
- musterPrefix: Global prefix applied to all aggregated capabilities (default: "x")
Returns a new, empty server registry ready for use.
func (*ServerRegistry) Deregister ¶
func (r *ServerRegistry) Deregister(name string) error
Deregister removes an MCP server from the registry and cleans up its resources.
This method safely removes a server from the registry, closes its client connection, and notifies subscribers of the change. All tools, resources, and prompts provided by the server will no longer be available through the aggregator.
The method is thread-safe and can be called concurrently.
Args:
- name: Unique identifier of the server to remove
Returns an error if the server is not found in the registry.
func (*ServerRegistry) GetAllPrompts ¶
func (r *ServerRegistry) GetAllPrompts() []mcp.Prompt
GetAllPrompts returns a consolidated list of all prompts from all connected servers.
This method aggregates prompts from all registered and connected servers, applying intelligent prefixing to avoid name conflicts. Only servers that are currently connected contribute their prompts to the result.
Returns a slice of MCP prompts ready for exposure through the aggregator.
func (*ServerRegistry) GetAllPromptsForSession ¶
func (r *ServerRegistry) GetAllPromptsForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Prompt
GetAllPromptsForSession returns a session-specific view of all available prompts.
Similar to GetAllToolsForSession, this returns prompts based on session authentication state.
func (*ServerRegistry) GetAllResources ¶
func (r *ServerRegistry) GetAllResources() []mcp.Resource
GetAllResources returns a consolidated list of all resources from all connected servers.
This method aggregates resources from all registered and connected servers, applying intelligent prefixing to resource URIs to avoid conflicts. Only servers that are currently connected contribute their resources to the result.
Returns a slice of MCP resources ready for exposure through the aggregator.
func (*ServerRegistry) GetAllResourcesForSession ¶
func (r *ServerRegistry) GetAllResourcesForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Resource
GetAllResourcesForSession returns a session-specific view of all available resources.
Similar to GetAllToolsForSession, this returns resources based on session authentication state.
func (*ServerRegistry) GetAllServers ¶
func (r *ServerRegistry) GetAllServers() map[string]*ServerInfo
GetAllServers returns a copy of all registered server information.
This method provides a snapshot of all servers currently registered with the registry, including both connected and disconnected servers. The returned map is a copy to prevent external modifications to the internal state.
Returns a map of server names to their corresponding ServerInfo structures.
func (*ServerRegistry) GetAllTools ¶
func (r *ServerRegistry) GetAllTools() []mcp.Tool
GetAllTools returns a consolidated list of all tools from all connected servers.
This method aggregates tools from all registered and connected servers, applying intelligent prefixing to avoid name conflicts. Only servers that are currently connected contribute their tools to the result.
Per ADR-008, servers in auth_required state do NOT contribute any tools. Users must use core_auth_login to authenticate before server tools become visible.
The returned tools have their names modified to include appropriate prefixes following the pattern: {muster_prefix}_{server_prefix}_{original_name}
Returns a slice of MCP tools ready for exposure through the aggregator.
func (*ServerRegistry) GetAllToolsForSession ¶
func (r *ServerRegistry) GetAllToolsForSession(sessionRegistry *SessionRegistry, sessionID string) []mcp.Tool
GetAllToolsForSession returns a session-specific view of all available tools.
The returned tool list is computed based on the session's authentication state:
- GlobalTools: Tools from servers that don't require authentication
- AuthenticatedServerTools: Tools from OAuth servers where the session has a valid connection
Per ADR-008, servers requiring authentication but not yet authenticated do NOT show any tools. Users must use core_auth_login to authenticate before server tools become visible.
This implements per-session tool visibility as described in ADR-006 and ADR-008.
Args:
- sessionRegistry: The session registry containing per-session state
- sessionID: The session to compute the tool view for
Returns a slice of MCP tools specific to this session.
func (*ServerRegistry) GetClient ¶
func (r *ServerRegistry) GetClient(name string) (MCPClient, error)
GetClient returns the MCP client for a specific registered server.
This method provides access to the underlying MCP client for direct communication with a specific server. The client can be used to execute tools, read resources, or retrieve prompts from the server.
Args:
- name: Unique identifier of the server
Returns the MCP client interface and nil error if successful. Returns nil client and an error if the server is not found or not connected.
func (*ServerRegistry) GetOAuthServers ¶
func (r *ServerRegistry) GetOAuthServers() []*ServerInfo
GetOAuthServers returns a list of servers that require OAuth authentication.
func (*ServerRegistry) GetServerInfo ¶
func (r *ServerRegistry) GetServerInfo(name string) (*ServerInfo, bool)
GetServerInfo returns detailed information about a specific registered server.
This method provides access to the complete ServerInfo structure for a given server, including its client, cached capabilities, and connection status.
Args:
- name: Unique identifier of the server
Returns the ServerInfo pointer and true if the server exists. Returns nil and false if the server is not found.
func (*ServerRegistry) GetUpdateChannel ¶
func (r *ServerRegistry) GetUpdateChannel() <-chan struct{}
GetUpdateChannel returns a read-only channel that receives notifications when the registry is updated.
Subscribers can use this channel to react to server registrations, deregistrations, or capability changes. The channel is buffered with a capacity of 1 to prevent blocking the registry operations.
Returns a receive-only channel for registry update notifications.
func (*ServerRegistry) IsOAuthServer ¶
func (r *ServerRegistry) IsOAuthServer(serverName string) bool
IsOAuthServer checks if a server requires OAuth authentication.
func (*ServerRegistry) Register ¶
func (r *ServerRegistry) Register(ctx context.Context, name string, client MCPClient, toolPrefix string) error
Register adds a new MCP server to the registry and initializes its capabilities.
This method performs the following operations:
- Validates that the server name is not already in use
- Initializes the MCP client if needed
- Queries the server for its initial capabilities
- Stores the server information and updates the name tracker
- Notifies subscribers of the registry update
The method is thread-safe and can be called concurrently.
Args:
- ctx: Context for initialization and capability queries
- name: Unique identifier for the server
- client: MCP client instance for communicating with the server
- toolPrefix: Server-specific prefix for tools (uses server name if empty)
Returns an error if the server name is already registered, client initialization fails, or the server cannot be reached.
func (*ServerRegistry) RegisterPendingAuth ¶
func (r *ServerRegistry) RegisterPendingAuth(name, url, toolPrefix string, authInfo *AuthInfo) error
RegisterPendingAuth registers a server that requires authentication before it can be fully connected. This creates a placeholder server entry with StatusAuthRequired. Per ADR-008, no synthetic authentication tools are created - users should use core_auth_login to authenticate.
Args:
- name: Unique identifier for the server
- url: The server endpoint URL
- toolPrefix: Server-specific prefix for tools
- authInfo: OAuth authentication information from the 401 response
Returns an error if the server name is already registered.
func (*ServerRegistry) RegisterPendingAuthWithConfig ¶
func (r *ServerRegistry) RegisterPendingAuthWithConfig(name, url, toolPrefix string, authInfo *AuthInfo, authConfig *api.MCPServerAuth) error
RegisterPendingAuthWithConfig registers a server that requires authentication with auth configuration. This is an extended version of RegisterPendingAuth that also accepts auth config for SSO token forwarding.
Args:
- name: Unique identifier for the server
- url: The server endpoint URL
- toolPrefix: Server-specific prefix for tools
- authInfo: OAuth authentication information from the 401 response
- authConfig: Auth configuration for token forwarding (may be nil)
Returns an error if the server name is already registered.
func (*ServerRegistry) ResolvePromptName ¶
func (r *ServerRegistry) ResolvePromptName(exposedName string) (serverName, originalName string, err error)
ResolvePromptName resolves an exposed (prefixed) prompt name back to its source server and original name.
This method is used when a prompt request is received to determine which server should handle the request and what the original prompt name was before prefixing.
Args:
- exposedName: The prefixed prompt name as seen by clients
Returns the server name, original prompt name, and nil error if resolution succeeds. Returns empty strings and an error if the name cannot be resolved or refers to a different item type.
func (*ServerRegistry) ResolveResourceName ¶
func (r *ServerRegistry) ResolveResourceName(exposedURI string) (serverName, originalURI string, err error)
ResolveResourceName resolves an exposed (prefixed) resource URI back to its source server and original URI.
This method is used when a resource read request is received to determine which server should handle the request and what the original resource URI was before prefixing.
Args:
- exposedURI: The prefixed resource URI as seen by clients
Returns the server name, original resource URI, and nil error if resolution succeeds. Returns empty strings and an error if the URI cannot be resolved or refers to a different item type.
func (*ServerRegistry) ResolveToolName ¶
func (r *ServerRegistry) ResolveToolName(exposedName string) (serverName, originalName string, err error)
ResolveToolName resolves an exposed (prefixed) tool name back to its source server and original name.
This method is used when a tool call is received to determine which server should handle the request and what the original tool name was before prefixing.
Args:
- exposedName: The prefixed tool name as seen by clients
Returns the server name, original tool name, and nil error if resolution succeeds. Returns empty strings and an error if the name cannot be resolved or refers to a different item type.
func (*ServerRegistry) UpgradeToConnected ¶
func (r *ServerRegistry) UpgradeToConnected(ctx context.Context, name string, client MCPClient) error
UpgradeToConnected upgrades a pending auth server to connected status after successful authentication. This replaces the synthetic auth tool with the server's actual tools.
Args:
- ctx: Context for capability queries
- name: Server name to upgrade
- client: The newly authenticated MCP client
Returns an error if the server is not found or is not in pending auth state.
type ServerStatus ¶
type ServerStatus string
ServerStatus represents the connection status of a server
const ( // StatusConnected indicates the server is connected and operational StatusConnected ServerStatus = "connected" // StatusDisconnected indicates the server is disconnected StatusDisconnected ServerStatus = "disconnected" // StatusAuthRequired indicates the server requires OAuth authentication // before it can complete the MCP protocol handshake StatusAuthRequired ServerStatus = "auth_required" // StatusUnreachable indicates the server endpoint cannot be reached. // This is distinct from auth_required - unreachable means network/connectivity failure. // // Related constants: // - api.StateUnreachable (internal/api/service.go) // - pkgoauth.ServerStatusUnreachable (pkg/oauth/types.go) StatusUnreachable ServerStatus = "unreachable" )
type SessionConnection ¶
type SessionConnection struct {
ServerName string
Status ConnectionStatus
AuthStatus AuthStatus // Per-user authentication status
Client MCPClient // Session-specific MCP client (with user's token)
TokenKey *oauth.TokenKey // Reference to the token in the token store
ConnectedAt time.Time // When the connection was established
TokenExpiresAt time.Time // When the SSO token expires (zero value = unknown/not SSO)
LastError string // Session-specific error (e.g., auth failures)
Tools []mcp.Tool
Resources []mcp.Resource
Prompts []mcp.Prompt
// contains filtered or unexported fields
}
SessionConnection represents a session's connection to a specific server.
For OAuth-protected servers, each session needs its own MCP client connection because:
- OAuth tokens are user-specific and may grant different permissions
- The remote MCP server may expose different tools based on user identity
- Connection state (ping, health) is per-user
This struct tracks per-user session state as defined in issue #292:
- Status (ConnectionStatus): Connected, Disconnected, PendingAuth, Failed
- AuthStatus: Authenticated, AuthRequired, TokenExpired
- Tools/Resources/Prompts: User-specific capabilities
- LastError: Session-specific errors (not infrastructure errors)
func (*SessionConnection) GetAuthStatus ¶
func (sc *SessionConnection) GetAuthStatus() AuthStatus
GetAuthStatus returns the authentication status for a session connection.
func (*SessionConnection) GetConnectedAt ¶
func (sc *SessionConnection) GetConnectedAt() time.Time
GetConnectedAt returns the timestamp when the connection was established. This provides thread-safe access to the ConnectedAt field.
func (*SessionConnection) GetLastError ¶
func (sc *SessionConnection) GetLastError() string
GetLastError returns the last error for this session connection.
func (*SessionConnection) GetPrompts ¶
func (sc *SessionConnection) GetPrompts() []mcp.Prompt
GetPrompts returns the cached prompts for a session connection.
func (*SessionConnection) GetResources ¶
func (sc *SessionConnection) GetResources() []mcp.Resource
GetResources returns the cached resources for a session connection.
func (*SessionConnection) GetStatus ¶
func (sc *SessionConnection) GetStatus() ConnectionStatus
GetStatus returns the connection status for a session connection. This provides thread-safe access to the Status field.
func (*SessionConnection) GetTools ¶
func (sc *SessionConnection) GetTools() []mcp.Tool
GetTools returns the cached tools for a session connection.
func (*SessionConnection) IsTokenExpired ¶ added in v0.1.33
func (sc *SessionConnection) IsTokenExpired(margin time.Duration) bool
IsTokenExpired returns true if the connection's SSO token is expired or will expire within the given margin. Returns false if no expiry time is set (e.g., non-SSO connections or unknown expiry).
func (*SessionConnection) SetAuthStatus ¶
func (sc *SessionConnection) SetAuthStatus(status AuthStatus)
SetAuthStatus updates the authentication status for a session connection.
func (*SessionConnection) SetAuthStatusWithError ¶
func (sc *SessionConnection) SetAuthStatusWithError(status AuthStatus, errMsg string)
SetAuthStatusWithError updates the auth status and records an error message. This is used when authentication fails (e.g., token expired, invalid credentials).
func (*SessionConnection) SetTokenExpiresAt ¶ added in v0.1.35
func (sc *SessionConnection) SetTokenExpiresAt(t time.Time)
SetTokenExpiresAt updates the token expiry time. This is called when a dynamic header function successfully re-exchanges a token, so that the re-init guard sees the updated expiry instead of the stale initial value.
func (*SessionConnection) UpdatePrompts ¶
func (sc *SessionConnection) UpdatePrompts(prompts []mcp.Prompt)
UpdatePrompts updates the cached prompts for a session connection.
func (*SessionConnection) UpdateResources ¶
func (sc *SessionConnection) UpdateResources(resources []mcp.Resource)
UpdateResources updates the cached resources for a session connection.
func (*SessionConnection) UpdateTools ¶
func (sc *SessionConnection) UpdateTools(tools []mcp.Tool)
UpdateTools updates the cached tools for a session connection.
type SessionConnectionResult ¶
type SessionConnectionResult struct {
// ServerName is the name of the server that was connected
ServerName string
// ToolCount is the number of tools available from the server
ToolCount int
// ResourceCount is the number of resources available from the server
ResourceCount int
// PromptCount is the number of prompts available from the server
PromptCount int
}
SessionConnectionResult contains the result of establishing a session connection. This is returned by establishSessionConnection and used by callers to format their specific result types (api.CallToolResult or mcp.CallToolResult).
func EstablishSessionConnectionWithTokenExchange ¶
func EstablishSessionConnectionWithTokenExchange( ctx context.Context, a *AggregatorServer, sessionID string, serverInfo *ServerInfo, musterIssuer string, ) (*SessionConnectionResult, error)
EstablishSessionConnectionWithTokenExchange attempts to establish a session connection using RFC 8693 Token Exchange for cross-cluster SSO. This is used when an MCPServer has tokenExchange configured.
The function:
- Gets the user's ID token from muster's OAuth session
- Extracts the user ID (sub claim) from the token
- Exchanges it for a token valid on the remote cluster's Dex
- If successful, establishes the session connection with the exchanged token
Args:
- ctx: Context for the operation
- a: The aggregator server instance
- sessionID: The session to register the connection with
- serverInfo: The server info containing URL and auth config
- musterIssuer: The issuer URL of muster's OAuth provider (used to get the ID token)
Returns:
- *SessionConnectionResult: The connection result if successful
- error: The error if connection failed
func EstablishSessionConnectionWithTokenForwarding ¶
func EstablishSessionConnectionWithTokenForwarding( ctx context.Context, a *AggregatorServer, sessionID string, serverInfo *ServerInfo, musterIssuer string, ) (*SessionConnectionResult, error)
EstablishSessionConnectionWithTokenForwarding attempts to establish a session connection using ID token forwarding for SSO. This is used when an MCPServer has forwardToken: true.
The function:
- Gets the user's ID token from muster's OAuth session
- Forwards it to the downstream MCP server
- If successful, establishes the session connection
Args:
- ctx: Context for the operation
- a: The aggregator server instance
- sessionID: The session to register the connection with
- serverInfo: The server info containing URL and auth config
- musterIssuer: The issuer URL of muster's OAuth provider (used to get the ID token)
Returns:
- *SessionConnectionResult: The connection result if successful
- error: The error if connection failed
func (*SessionConnectionResult) FormatAsAPIResult ¶
func (r *SessionConnectionResult) FormatAsAPIResult() *api.CallToolResult
FormatAsAPIResult formats the connection result as an api.CallToolResult. Used by AuthToolProvider.tryConnectWithToken.
func (*SessionConnectionResult) FormatAsMCPResult ¶
func (r *SessionConnectionResult) FormatAsMCPResult() *mcp.CallToolResult
FormatAsMCPResult formats the connection result as an mcp.CallToolResult. Used by AggregatorServer.tryConnectWithToken.
type SessionIdentityMismatchError ¶ added in v0.1.27
type SessionIdentityMismatchError struct {
SessionID string
ExpectedSubject string
ActualSubject string
}
SessionIdentityMismatchError is returned when a session's bound identity does not match the authenticated user's identity.
func (*SessionIdentityMismatchError) Error ¶ added in v0.1.27
func (e *SessionIdentityMismatchError) Error() string
type SessionLimitExceededError ¶
SessionLimitExceededError is returned when the maximum session limit is reached.
func (*SessionLimitExceededError) Error ¶
func (e *SessionLimitExceededError) Error() string
type SessionNotFoundError ¶
type SessionNotFoundError struct {
SessionID string
}
SessionNotFoundError is returned when a session is not found.
func (*SessionNotFoundError) Error ¶
func (e *SessionNotFoundError) Error() string
type SessionRegistry ¶
type SessionRegistry struct {
// contains filtered or unexported fields
}
SessionRegistry manages per-session state for OAuth-protected MCP servers.
The registry maintains a thread-safe mapping of session IDs to their state, including per-server connections, cached tools, and authentication status. This enables session-scoped tool visibility where each user only sees tools from servers they have authenticated with.
Key responsibilities:
- Session lifecycle management (creation, cleanup, timeout)
- Per-session connection tracking for OAuth-protected servers
- Session-specific tool caching
- Thread-safe access to session state
- DoS protection via session limits and validation
func NewSessionRegistry ¶
func NewSessionRegistry(sessionTimeout time.Duration) *SessionRegistry
NewSessionRegistry creates a new session registry with the specified timeout and default session limits.
The registry starts a background goroutine for periodic cleanup of idle sessions. Callers MUST call Stop() when done to prevent goroutine leaks.
Args:
- sessionTimeout: Duration after which idle sessions are cleaned up (default: 30 minutes)
Returns a new session registry ready for use.
func NewSessionRegistryWithLimits ¶
func NewSessionRegistryWithLimits(sessionTimeout time.Duration, maxSessions int) *SessionRegistry
NewSessionRegistryWithLimits creates a new session registry with custom limits.
This constructor allows fine-grained control over session limits for different deployment scenarios (e.g., higher limits for enterprise deployments).
Args:
- sessionTimeout: Duration after which idle sessions are cleaned up (default: 30 minutes)
- maxSessions: Maximum number of concurrent sessions (0 = unlimited, not recommended)
Returns a new session registry ready for use.
func (*SessionRegistry) Count ¶
func (sr *SessionRegistry) Count() int
Count returns the number of active sessions.
func (*SessionRegistry) CreateSessionForSubject ¶ added in v0.1.27
func (sr *SessionRegistry) CreateSessionForSubject(subject string) (*SessionState, error)
CreateSessionForSubject generates a new server-side session ID and binds it to the given subject (authenticated user identity). This is the primary entry point for server-side session creation.
Returns the new session state and session ID, or an error if generation fails or the session limit is exceeded.
func (*SessionRegistry) DeleteSession ¶
func (sr *SessionRegistry) DeleteSession(sessionID string)
DeleteSession removes a session and cleans up its connections.
This method closes all session-specific MCP client connections and removes the session state from the registry.
Args:
- sessionID: Unique identifier for the session to remove
func (*SessionRegistry) EndSSOInit ¶
func (sr *SessionRegistry) EndSSOInit(sessionID string)
EndSSOInit marks that SSO initialization has completed for a session. The session can now be cleaned up by timeout if it becomes idle.
func (*SessionRegistry) GetAllSessions ¶
func (sr *SessionRegistry) GetAllSessions() map[string]*SessionState
GetAllSessions returns all active sessions.
Returns a map of session IDs to session states. The returned map is a copy to prevent external modifications to the internal state.
func (*SessionRegistry) GetAuthStatus ¶
func (sr *SessionRegistry) GetAuthStatus(sessionID, serverName string) (AuthStatus, bool)
GetAuthStatus returns the authentication status for a session's connection to a server. This is per-user session state used to track if a user is authenticated, needs auth, etc.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
Returns the auth status and true if found, AuthStatusUnknown and false otherwise.
func (*SessionRegistry) GetConnection ¶
func (sr *SessionRegistry) GetConnection(sessionID, serverName string) (*SessionConnection, bool)
GetConnection returns a session's connection to a specific server.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
Returns the connection and true if found, nil and false otherwise.
func (*SessionRegistry) GetOrCreateSession ¶
func (sr *SessionRegistry) GetOrCreateSession(sessionID string) *SessionState
GetOrCreateSession returns the session state for a session ID, creating it if necessary.
This method is the primary entry point for session management. It ensures that a session always exists when needed and updates the last activity timestamp.
The method validates the session ID and enforces session limits:
- Empty or excessively long session IDs are rejected
- New sessions are rejected if the maximum session limit is reached
Args:
- sessionID: Unique identifier for the session
Returns the session state, or nil if validation fails or limits are exceeded. Callers should use GetOrCreateSessionWithError for detailed error information.
func (*SessionRegistry) GetOrCreateSessionWithError ¶
func (sr *SessionRegistry) GetOrCreateSessionWithError(sessionID string) (*SessionState, error)
GetOrCreateSessionWithError returns the session state for a session ID, creating it if necessary.
This method provides detailed error information for validation and limit failures.
Args:
- sessionID: Unique identifier for the session
Returns:
- The session state (nil on error)
- An error if validation fails or limits are exceeded
func (*SessionRegistry) GetSession ¶
func (sr *SessionRegistry) GetSession(sessionID string) (*SessionState, bool)
GetSession returns the session state for a session ID.
Args:
- sessionID: Unique identifier for the session
Returns the session state and true if found, nil and false otherwise. Invalid session IDs return nil and false.
func (*SessionRegistry) HasSSOFailed ¶
func (sr *SessionRegistry) HasSSOFailed(sessionID, serverName string) bool
HasSSOFailed checks if SSO authentication was attempted but failed for a server. Returns true if SSO was attempted and failed, false otherwise.
func (*SessionRegistry) IsSSOInitInProgress ¶
func (sr *SessionRegistry) IsSSOInitInProgress(sessionID string) bool
IsSSOInitInProgress checks if SSO initialization is in progress for a session.
func (*SessionRegistry) MarkSSOFailed ¶
func (sr *SessionRegistry) MarkSSOFailed(sessionID, serverName string)
MarkSSOFailed records that SSO authentication was attempted but failed for a server. This is called when proactive SSO (token forwarding) fails during session init. The failure is tracked so the UI can show "SSO failed" to explain why auth is required.
func (*SessionRegistry) RemoveServerFromAllSessions ¶
func (sr *SessionRegistry) RemoveServerFromAllSessions(serverName string) int
RemoveServerFromAllSessions removes connections to a specific server from all sessions. This is called when an MCPServer is deregistered (e.g., deleted or renamed) to clean up stale session connections that would otherwise persist until session timeout.
This fixes the issue where renamed MCPServers would show stale auth status because session connections were stored under the old server name and never cleaned up.
Args:
- serverName: The name of the server to remove from all sessions
Returns the number of connections that were removed.
func (*SessionRegistry) SetAuthStatus ¶
func (sr *SessionRegistry) SetAuthStatus(sessionID, serverName string, status AuthStatus)
SetAuthStatus updates the authentication status for a session's connection to a server.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
- status: New auth status
func (*SessionRegistry) SetAuthStatusWithError ¶
func (sr *SessionRegistry) SetAuthStatusWithError(sessionID, serverName string, status AuthStatus, errMsg string)
SetAuthStatusWithError updates the auth status and records an error for a session. This is used when authentication fails (e.g., token expired, invalid credentials).
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
- status: New auth status
- errMsg: Error message describing the failure
func (*SessionRegistry) SetConnection ¶
func (sr *SessionRegistry) SetConnection(sessionID, serverName string, conn *SessionConnection)
SetConnection sets a session's connection to a specific server.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
- conn: The connection to set
func (*SessionRegistry) SetOnSessionRemoved ¶ added in v0.1.34
func (sr *SessionRegistry) SetOnSessionRemoved(fn func(sessionID string))
SetOnSessionRemoved registers a callback that is invoked whenever a session is removed from the registry (via cleanup or DeleteSession). This must be called before sessions are created (typically right after construction).
func (*SessionRegistry) SetPendingAuth ¶
func (sr *SessionRegistry) SetPendingAuth(sessionID, serverName string)
SetPendingAuth marks a server as pending authentication for a session.
This creates a placeholder connection in pending_auth state that will be upgraded to connected once authentication succeeds.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
func (*SessionRegistry) StartSSOInit ¶
func (sr *SessionRegistry) StartSSOInit(sessionID string)
StartSSOInit marks that SSO initialization is starting for a session. While SSO init is in progress, the session will not be cleaned up by timeout. This prevents race conditions where sessions are cleaned up before SSO completes.
IMPORTANT: Callers MUST call EndSSOInit when SSO initialization completes, typically using defer. Failure to do so will prevent the session from ever being cleaned up.
func (*SessionRegistry) Stop ¶
func (sr *SessionRegistry) Stop()
Stop stops the session registry and cleans up all sessions.
This method closes all session-specific MCP client connections, invokes the onSessionRemoved callback for each session, and stops the background cleanup goroutine.
func (*SessionRegistry) UpgradeConnection ¶
func (sr *SessionRegistry) UpgradeConnection(sessionID, serverName string, client MCPClient, tokenKey *oauth.TokenKey) error
UpgradeConnection upgrades a session's connection from pending_auth to connected.
This is called after successful OAuth authentication to associate the authenticated MCP client with the session.
Args:
- sessionID: Unique identifier for the session
- serverName: Name of the server
- client: The authenticated MCP client
- tokenKey: Reference to the token in the token store
Returns an error if the session or connection is not found.
func (*SessionRegistry) ValidateSessionIdentity ¶ added in v0.1.27
func (sr *SessionRegistry) ValidateSessionIdentity(sessionID, subject string) error
ValidateSessionIdentity checks that the session's bound identity matches the given subject. Returns nil if the session has no bound identity (legacy/unbound) or if it matches. Returns a SessionIdentityMismatchError if the identities don't match.
type SessionState ¶
type SessionState struct {
SessionID string
CreatedAt time.Time
LastActivity time.Time
// Subject is the authenticated user identity (sub claim from OAuth token)
// bound to this session. Once set, subsequent requests must match this
// identity or the session will be rejected (403).
Subject string
// Per-server connection state for this session
// Maps server name to the session's connection to that server
Connections map[string]*SessionConnection
// SSOFailedServers tracks servers where proactive SSO authentication was
// attempted but failed (e.g., due to audience mismatch or token rejection).
// This helps the UI show "SSO failed" to explain why auth is still required.
SSOFailedServers map[string]bool
// SSOInitInProgress indicates that SSO initialization is currently in progress.
// While this is true, the session should not be cleaned up by the timeout cleanup.
// This prevents race conditions where sessions are cleaned up before SSO completes.
SSOInitInProgress bool
// contains filtered or unexported fields
}
SessionState holds per-session connection state.
Each session maintains its own view of available tools based on which OAuth-protected servers the user has authenticated with. This state includes connection tracking, cached capabilities, and activity timestamps.
func (*SessionState) CloseAllConnections ¶
func (s *SessionState) CloseAllConnections()
CloseAllConnections closes all MCP client connections for this session.
func (*SessionState) GetAllConnections ¶
func (s *SessionState) GetAllConnections() map[string]*SessionConnection
GetAllConnections returns a copy of all connections for this session. This is safe for iteration since it returns a copy of the map.
func (*SessionState) GetConnectedServers ¶
func (s *SessionState) GetConnectedServers() []string
GetConnectedServers returns the names of all servers the session is connected to.
func (*SessionState) GetConnection ¶
func (s *SessionState) GetConnection(serverName string) (*SessionConnection, bool)
GetConnection returns the session's connection to a specific server.
func (*SessionState) GetPendingAuthServers ¶
func (s *SessionState) GetPendingAuthServers() []string
GetPendingAuthServers returns the names of all servers awaiting authentication.
func (*SessionState) RemoveConnection ¶
func (s *SessionState) RemoveConnection(serverName string)
RemoveConnection removes the session's connection to a specific server. This is used when logging out from a server or when a connection becomes invalid.
func (*SessionState) SetConnection ¶
func (s *SessionState) SetConnection(serverName string, conn *SessionConnection)
SetConnection sets the session's connection to a specific server.
func (*SessionState) UpdateActivity ¶
func (s *SessionState) UpdateActivity()
UpdateActivity updates the last activity timestamp for the session.
func (*SessionState) UpgradeConnection ¶
func (s *SessionState) UpgradeConnection(serverName string, client MCPClient, tokenKey *oauth.TokenKey) error
UpgradeConnection upgrades a connection from pending_auth to connected.
This method validates the connection state before upgrading:
- The connection must exist
- The connection must be in pending_auth state (not already connected)
Returns an error if validation fails.
type TeleportClientResult ¶
type TeleportClientResult struct {
// Client is the HTTP client configured with Teleport mTLS certificates.
// Nil if Teleport is not configured or if there was an error.
Client *http.Client
// Configured indicates whether Teleport authentication was configured
// for this server. When true but Client is nil, Error will contain the reason.
Configured bool
// Error contains the error if Teleport was configured but client creation failed.
// This allows callers to distinguish between "not configured" and "configured but failed".
Error error
}
TeleportClientResult contains the result of getting a Teleport HTTP client. This provides explicit error handling for Teleport configuration issues.
type ToolWithStatus ¶
type ToolWithStatus struct {
// Tool contains the MCP tool definition
Tool mcp.Tool
// Blocked indicates whether this tool is blocked by the security denylist.
// Blocked tools cannot be executed unless the Yolo flag is enabled.
Blocked bool
}
ToolWithStatus represents a tool along with its security blocking status. This is used to provide visibility into which tools are available and which are blocked by the security denylist.