Documentation
¶
Overview ¶
Package mcpserver provides MCP (Model Context Protocol) server management functionality.
This package enables the registration, configuration, and lifecycle management of MCP servers within the muster ecosystem. It supports both static configuration through YAML files and dynamic management through API operations.
MCP Server Types ¶
Currently supported MCP server types:
- **Stdio**: Execute MCP servers as local processes with configurable command lines
- **Streamable-HTTP**: Connect to external MCP servers via HTTP transport
- **SSE**: Connect to external MCP servers via Server-Sent Events transport
Configuration Structure ¶
MCP servers are defined using the MCPServer CRD or YAML configuration files. Each server definition includes metadata, type-specific configuration, and operational settings.
Basic configuration structure:
apiVersion: muster.giantswarm.io/v1alpha1
kind: MCPServer
metadata:
name: example-server
namespace: default
spec:
description: Example MCP server for demonstration
toolPrefix: example
type: stdio
autoStart: true
command: npx
args:
- "@modelcontextprotocol/server-filesystem"
- "/workspace"
env:
DEBUG: "1"
For remote servers:
spec:
type: streamable-http
url: "https://api.example.com/mcp"
timeout: 30
headers:
Authorization: "Bearer token"
Static Configuration ¶
MCP servers can be defined in YAML files for static configuration. These files are typically placed in the muster configuration directory and loaded at startup.
Static configuration example:
# Stdio server example
---
apiVersion: muster.giantswarm.io/v1alpha1
kind: MCPServer
metadata:
name: filesystem-tools
spec:
description: File system operations
toolPrefix: fs
type: stdio
autoStart: true
command: npx
args: ["@modelcontextprotocol/server-filesystem", "/workspace"]
# Remote server example
---
apiVersion: muster.giantswarm.io/v1alpha1
kind: MCPServer
metadata:
name: remote-api
spec:
description: Remote API tools
toolPrefix: api
type: streamable-http
url: "https://api.example.com/mcp"
timeout: 60
headers:
Authorization: "Bearer token"
Dynamic Management ¶
MCP servers can also be created, updated, and deleted dynamically through the muster API. This enables runtime configuration changes and programmatic server management.
API operations include:
- Create: Register new MCP server definitions
- Update: Modify existing server configurations
- Delete: Remove server definitions
- List: Retrieve all configured servers
- Get: Fetch specific server details
- Validate: Check server configuration validity
Lifecycle Management ¶
The package handles the complete lifecycle of MCP servers:
- **Registration**: Adding server definitions to the system
- **Validation**: Ensuring configuration correctness
- **Instantiation**: Creating service instances
- **Startup**: Initializing server processes or connections
- **Monitoring**: Tracking server health and status
- **Shutdown**: Graceful termination of server instances
Integration Points ¶
This package integrates with several muster components:
- **Aggregator**: Registers tools provided by MCP servers
- **Service Registry**: Manages server lifecycle as services
- **Configuration System**: Loads static server definitions
- **API Layer**: Exposes management operations as tools
- **Orchestrator**: Coordinates server startup and dependencies
Index ¶
- Constants
- type Adapter
- func (a *Adapter) Close() error
- func (a *Adapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
- func (a *Adapter) GetMCPServer(name string) (*api.MCPServerInfo, error)
- func (a *Adapter) GetTools() []api.ToolMetadata
- func (a *Adapter) ListMCPServers() []api.MCPServerInfo
- func (a *Adapter) Register()
- type AuthInfo
- type AuthRequiredError
- type CredentialsAdapter
- type DynamicAuthClient
- func (c *DynamicAuthClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (c *DynamicAuthClient) Close() error
- func (c *DynamicAuthClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
- func (c *DynamicAuthClient) Initialize(ctx context.Context) error
- func (c *DynamicAuthClient) ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
- func (c *DynamicAuthClient) ListResources(ctx context.Context) ([]mcp.Resource, error)
- func (c *DynamicAuthClient) ListTools(ctx context.Context) ([]mcp.Tool, error)
- func (c *DynamicAuthClient) Ping(ctx context.Context) error
- func (c *DynamicAuthClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- type MCPClient
- type MCPClientConfig
- type McpDiscreteStatusUpdate
- type McpUpdateFunc
- type SSEClient
- func (c *SSEClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (c *SSEClient) Close() error
- func (c *SSEClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
- func (c *SSEClient) Initialize(ctx context.Context) error
- func (c *SSEClient) ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
- func (c *SSEClient) ListResources(ctx context.Context) ([]mcp.Resource, error)
- func (c *SSEClient) ListTools(ctx context.Context) ([]mcp.Tool, error)
- func (c *SSEClient) Ping(ctx context.Context) error
- func (c *SSEClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- type StdioClient
- func (c *StdioClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (c *StdioClient) Close() error
- func (c *StdioClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
- func (c *StdioClient) GetStderr() (io.Reader, bool)
- func (c *StdioClient) Initialize(ctx context.Context) error
- func (c *StdioClient) ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
- func (c *StdioClient) ListResources(ctx context.Context) ([]mcp.Resource, error)
- func (c *StdioClient) ListTools(ctx context.Context) ([]mcp.Tool, error)
- func (c *StdioClient) Ping(ctx context.Context) error
- func (c *StdioClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- type StreamableHTTPClient
- func (c *StreamableHTTPClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
- func (c *StreamableHTTPClient) Close() error
- func (c *StreamableHTTPClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
- func (c *StreamableHTTPClient) Initialize(ctx context.Context) error
- func (c *StreamableHTTPClient) ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
- func (c *StreamableHTTPClient) ListResources(ctx context.Context) ([]mcp.Resource, error)
- func (c *StreamableHTTPClient) ListTools(ctx context.Context) ([]mcp.Tool, error)
- func (c *StreamableHTTPClient) Ping(ctx context.Context) error
- func (c *StreamableHTTPClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
- type TokenProvider
- type TokenProviderFunc
Constants ¶
const DefaultClientIDKey = "client-id"
DefaultClientIDKey is the default key for client ID in the secret.
const DefaultClientSecretKey = "client-secret"
DefaultClientSecretKey is the default key for client secret in the secret.
const DefaultStdioInitTimeout = 10 * time.Second
DefaultStdioInitTimeout is the default timeout for stdio client initialization. This covers the time needed to start the subprocess and complete the MCP handshake.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter provides MCP server management functionality using the unified client
func NewAdapterWithClient ¶
func NewAdapterWithClient(musterClient client.MusterClient, namespace string) *Adapter
NewAdapterWithClient creates a new adapter with a specific client (for testing)
func (*Adapter) ExecuteTool ¶
func (a *Adapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
ExecuteTool executes a tool by name
func (*Adapter) GetMCPServer ¶
func (a *Adapter) GetMCPServer(name string) (*api.MCPServerInfo, error)
GetMCPServer returns information about a specific MCP server
func (*Adapter) GetTools ¶
func (a *Adapter) GetTools() []api.ToolMetadata
GetTools returns all tools this provider offers
func (*Adapter) ListMCPServers ¶
func (a *Adapter) ListMCPServers() []api.MCPServerInfo
ListMCPServers returns all MCP server definitions
type AuthInfo ¶
type AuthInfo struct {
// Issuer is the OAuth issuer URL (from WWW-Authenticate realm)
Issuer string
// Scope is the OAuth scope required by the server
Scope string
// ResourceMetadataURL is the URL to fetch OAuth metadata (MCP-specific)
ResourceMetadataURL string
}
AuthInfo contains OAuth authentication information extracted from a 401 response during MCP server initialization.
type AuthRequiredError ¶
type AuthRequiredError struct {
// URL is the endpoint that returned the 401
URL string
// AuthInfo contains the OAuth parameters extracted from the 401 response
AuthInfo AuthInfo
// AuthChallenge contains the parsed WWW-Authenticate header information
// from pkg/oauth for structured auth challenge handling
AuthChallenge *pkgoauth.AuthChallenge
// Err is the underlying error
Err error
}
AuthRequiredError is returned when an MCP server requires OAuth authentication before the protocol handshake can complete. This error contains the information needed to initiate the OAuth flow.
func CheckForAuthRequiredError ¶
func CheckForAuthRequiredError(err error, url string) *AuthRequiredError
CheckForAuthRequiredError examines an error to determine if it's a 401 authentication required error. If so, it returns an AuthRequiredError with parsed OAuth parameters. This is a shared helper used by SSEClient and StreamableHTTPClient.
The function uses the pkg/oauth utilities for structured 401 detection, leveraging ParseWWWAuthenticateFromError for proper header parsing.
func (*AuthRequiredError) Error ¶
func (e *AuthRequiredError) Error() string
Error implements the error interface
func (*AuthRequiredError) GetIssuer ¶
func (e *AuthRequiredError) GetIssuer() string
GetIssuer returns the OAuth issuer URL from the error. It prefers AuthChallenge if available, falls back to AuthInfo.
func (*AuthRequiredError) GetResourceMetadataURL ¶
func (e *AuthRequiredError) GetResourceMetadataURL() string
GetResourceMetadataURL returns the resource metadata URL from the error.
func (*AuthRequiredError) GetScope ¶
func (e *AuthRequiredError) GetScope() string
GetScope returns the OAuth scope from the error.
func (*AuthRequiredError) HasValidChallenge ¶
func (e *AuthRequiredError) HasValidChallenge() bool
HasValidChallenge returns true if the error contains valid auth challenge information.
func (*AuthRequiredError) Unwrap ¶
func (e *AuthRequiredError) Unwrap() error
Unwrap returns the underlying error
type CredentialsAdapter ¶
type CredentialsAdapter struct {
// contains filtered or unexported fields
}
CredentialsAdapter implements the SecretCredentialsHandler interface for loading OAuth client credentials from Kubernetes secrets.
func NewCredentialsAdapter ¶
func NewCredentialsAdapter(k8sClient client.Client) *CredentialsAdapter
NewCredentialsAdapter creates a new credentials adapter.
Args:
- k8sClient: The Kubernetes client for reading secrets
Returns:
- *CredentialsAdapter: The adapter instance
func (*CredentialsAdapter) LoadClientCredentials ¶
func (a *CredentialsAdapter) LoadClientCredentials( ctx context.Context, secretRef *api.ClientCredentialsSecretRef, defaultNamespace string, ) (*api.ClientCredentials, error)
LoadClientCredentials loads OAuth client credentials from a Kubernetes secret.
The secret should contain:
- clientIdKey: The OAuth client ID (defaults to "client-id")
- clientSecretKey: The OAuth client secret (defaults to "client-secret")
Args:
- ctx: Context for Kubernetes API calls
- secretRef: Reference to the secret containing credentials
- defaultNamespace: Namespace to use if not specified in secretRef
Returns:
- *api.ClientCredentials: The loaded credentials
- error: Error if the secret cannot be found or is missing required keys
func (*CredentialsAdapter) Register ¶
func (a *CredentialsAdapter) Register()
Register registers the adapter with the API.
type DynamicAuthClient ¶
type DynamicAuthClient struct {
// contains filtered or unexported fields
}
DynamicAuthClient implements the MCPClient interface using StreamableHTTP transport with dynamic token injection. Instead of static headers, it uses a TokenProvider that's called on each HTTP request to get the current access token.
This enables automatic token refresh for long-running sessions: - The TokenProvider can check if the token is expiring and refresh it - All HTTP requests will use the latest token automatically - No client recreation needed when tokens are refreshed
This implements Issue #214: Automatic token refresh for MCP server session connections.
func NewDynamicAuthClient ¶
func NewDynamicAuthClient(url string, tokenProvider TokenProvider) *DynamicAuthClient
NewDynamicAuthClient creates a new StreamableHTTP-based MCP client with dynamic token injection. The TokenProvider is called on each HTTP request to get the current access token.
Args:
- url: The MCP server URL
- tokenProvider: Provider for OAuth access tokens (called on each request)
Returns a new DynamicAuthClient ready for initialization.
func (*DynamicAuthClient) CallTool ¶
func (c *DynamicAuthClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallTool executes a specific tool and returns the result
func (*DynamicAuthClient) Close ¶
func (c *DynamicAuthClient) Close() error
Close cleanly shuts down the client connection
func (*DynamicAuthClient) GetPrompt ¶
func (c *DynamicAuthClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
GetPrompt retrieves a specific prompt
func (*DynamicAuthClient) Initialize ¶
func (c *DynamicAuthClient) Initialize(ctx context.Context) error
Initialize establishes the connection and performs protocol handshake. The TokenProvider is used to dynamically inject the Authorization header.
func (*DynamicAuthClient) ListPrompts ¶
ListPrompts returns all available prompts from the server
func (*DynamicAuthClient) ListResources ¶
ListResources returns all available resources from the server
func (*DynamicAuthClient) Ping ¶
func (c *DynamicAuthClient) Ping(ctx context.Context) error
Ping checks if the server is responsive
func (*DynamicAuthClient) ReadResource ¶
func (c *DynamicAuthClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
ReadResource retrieves a specific resource
type MCPClient ¶
type MCPClient interface {
// Initialize establishes the connection and performs protocol handshake
Initialize(ctx context.Context) error
// Close cleanly shuts down the client connection
Close() error
// ListTools returns all available tools from the server
ListTools(ctx context.Context) ([]mcp.Tool, error)
// CallTool executes a specific tool and returns the result
CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
// ListResources returns all available resources from the server
ListResources(ctx context.Context) ([]mcp.Resource, error)
// ReadResource retrieves a specific resource
ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
// ListPrompts returns all available prompts from the server
ListPrompts(ctx context.Context) ([]mcp.Prompt, error)
// GetPrompt retrieves a specific prompt
GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
// Ping checks if the server is responsive
Ping(ctx context.Context) error
}
MCPClient defines the interface for MCP client implementations. All transport types (stdio, SSE, streamable-http) implement this interface, enabling polymorphic usage and easier testing with mocks.
func NewMCPClientFromType ¶
func NewMCPClientFromType(serverType api.MCPServerType, config MCPClientConfig) (MCPClient, error)
NewMCPClientFromType creates the appropriate MCP client based on the server type. This factory function simplifies client creation by encapsulating the logic for choosing the correct client implementation.
Supported types:
- "stdio": Creates a StdioClient for local subprocess communication
- "streamable-http": Creates a StreamableHTTPClient for HTTP-based servers
- "sse": Creates an SSEClient for Server-Sent Events communication
If config.HTTPClient is provided (e.g., for Teleport TLS authentication), it will be used instead of the default HTTP client for remote server types.
Returns an error if the server type is not recognized.
type MCPClientConfig ¶
type MCPClientConfig struct {
// Command is the executable path for stdio servers
Command string
// Args are the command line arguments for stdio servers
Args []string
// Env contains environment variables for stdio servers
Env map[string]string
// URL is the endpoint for remote servers (streamable-http, sse)
URL string
// Headers are HTTP headers for remote servers
Headers map[string]string
// HTTPClient is a custom HTTP client to use for remote servers.
// When set, this client is used instead of the default.
// Used for Teleport authentication with custom TLS certificates.
HTTPClient *http.Client
}
MCPClientConfig contains configuration for creating an MCP client. This provides a unified configuration structure for all client types.
type McpDiscreteStatusUpdate ¶
type McpDiscreteStatusUpdate struct {
Name string // The unique label of the MCP server instance
ProcessStatus string // A string indicating the process status, e.g., "ProcessInitializing", "ProcessStarting", "ProcessRunning", "ProcessExitedWithError"
ProcessErr error // The actual Go error object if the process failed or exited with an error
}
McpDiscreteStatusUpdate is used to report discrete status changes from a running MCP process. It focuses on the state, not verbose logs.
type McpUpdateFunc ¶
type McpUpdateFunc func(update McpDiscreteStatusUpdate)
McpUpdateFunc is a callback function type for receiving McpDiscreteStatusUpdate messages.
type SSEClient ¶
type SSEClient struct {
// contains filtered or unexported fields
}
SSEClient implements the MCPClient interface using SSE transport. It connects to remote MCP servers using Server-Sent Events for communication.
func NewSSEClientWithHeaders ¶
NewSSEClientWithHeaders creates a new SSE-based MCP client with custom headers
func (*SSEClient) CallTool ¶
func (c *SSEClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallTool executes a specific tool and returns the result
func (*SSEClient) GetPrompt ¶
func (c *SSEClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
GetPrompt retrieves a specific prompt
func (*SSEClient) Initialize ¶
Initialize establishes the connection and performs protocol handshake
func (*SSEClient) ListPrompts ¶
ListPrompts returns all available prompts from the server
func (*SSEClient) ListResources ¶
ListResources returns all available resources from the server
func (*SSEClient) ReadResource ¶
ReadResource retrieves a specific resource
type StdioClient ¶
type StdioClient struct {
// contains filtered or unexported fields
}
StdioClient implements the MCPClient interface using stdio transport. It manages a local subprocess that communicates via stdin/stdout.
func NewStdioClientWithEnv ¶
func NewStdioClientWithEnv(command string, args []string, env map[string]string) *StdioClient
NewStdioClientWithEnv creates a new stdio-based MCP client with environment variables
func (*StdioClient) CallTool ¶
func (c *StdioClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallTool executes a specific tool and returns the result
func (*StdioClient) Close ¶
func (c *StdioClient) Close() error
Close cleanly shuts down the client connection
func (*StdioClient) GetPrompt ¶
func (c *StdioClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
GetPrompt retrieves a specific prompt
func (*StdioClient) GetStderr ¶
func (c *StdioClient) GetStderr() (io.Reader, bool)
GetStderr returns a reader for the stderr output of the subprocess
func (*StdioClient) Initialize ¶
func (c *StdioClient) Initialize(ctx context.Context) error
Initialize establishes the connection and performs protocol handshake
func (*StdioClient) ListPrompts ¶
ListPrompts returns all available prompts from the server
func (*StdioClient) ListResources ¶
ListResources returns all available resources from the server
func (*StdioClient) Ping ¶
func (c *StdioClient) Ping(ctx context.Context) error
Ping checks if the server is responsive
func (*StdioClient) ReadResource ¶
func (c *StdioClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
ReadResource retrieves a specific resource
type StreamableHTTPClient ¶
type StreamableHTTPClient struct {
// contains filtered or unexported fields
}
StreamableHTTPClient implements the MCPClient interface using StreamableHTTP transport. It connects to remote MCP servers using HTTP with streaming support.
func NewStreamableHTTPClientWithHTTPClient ¶
func NewStreamableHTTPClientWithHTTPClient(url string, headers map[string]string, httpClient *http.Client) *StreamableHTTPClient
NewStreamableHTTPClientWithHTTPClient creates a new StreamableHTTP-based MCP client with a custom HTTP client. This is useful for Teleport authentication where the HTTP client needs custom TLS certificates.
func NewStreamableHTTPClientWithHeaders ¶
func NewStreamableHTTPClientWithHeaders(url string, headers map[string]string) *StreamableHTTPClient
NewStreamableHTTPClientWithHeaders creates a new StreamableHTTP-based MCP client with custom headers
func (*StreamableHTTPClient) CallTool ¶
func (c *StreamableHTTPClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*mcp.CallToolResult, error)
CallTool executes a specific tool and returns the result
func (*StreamableHTTPClient) Close ¶
func (c *StreamableHTTPClient) Close() error
Close cleanly shuts down the client connection
func (*StreamableHTTPClient) GetPrompt ¶
func (c *StreamableHTTPClient) GetPrompt(ctx context.Context, name string, args map[string]interface{}) (*mcp.GetPromptResult, error)
GetPrompt retrieves a specific prompt
func (*StreamableHTTPClient) Initialize ¶
func (c *StreamableHTTPClient) Initialize(ctx context.Context) error
Initialize establishes the connection and performs protocol handshake
func (*StreamableHTTPClient) ListPrompts ¶
ListPrompts returns all available prompts from the server
func (*StreamableHTTPClient) ListResources ¶
ListResources returns all available resources from the server
func (*StreamableHTTPClient) Ping ¶
func (c *StreamableHTTPClient) Ping(ctx context.Context) error
Ping checks if the server is responsive
func (*StreamableHTTPClient) ReadResource ¶
func (c *StreamableHTTPClient) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
ReadResource retrieves a specific resource
type TokenProvider ¶
type TokenProvider interface {
// GetAccessToken returns the current access token for the given context.
// Returns an empty string if no token is available.
// The implementation may refresh the token if it's expiring.
GetAccessToken(ctx context.Context) string
}
TokenProvider is an interface for dynamically providing OAuth access tokens. Implementations should return the current valid access token, potentially refreshing it if needed. This enables automatic token refresh without recreating MCP client connections.
This interface is a key part of the dynamic token injection pattern (Issue #214): - Instead of creating clients with static Authorization headers - Clients use a TokenProvider that's called on each HTTP request - The TokenProvider can return refreshed tokens transparently
type TokenProviderFunc ¶
TokenProviderFunc is a function type that implements TokenProvider. This allows using simple functions as TokenProviders.
func (TokenProviderFunc) GetAccessToken ¶
func (f TokenProviderFunc) GetAccessToken(ctx context.Context) string
GetAccessToken implements TokenProvider.