Documentation
¶
Overview ¶
Package config provides configuration loading, validation, and persistence for Vision MCP server registry.
Index ¶
- Constants
- Variables
- func DefaultConfigPath() string
- func DefaultEnvPath() string
- func DefaultInstructionsPath() string
- func ExpandEnvVars(input string) string
- func LoadEnvFile(path string) error
- func Save(cfg *Config, path string) error
- type AvailabilityProfile
- type CircuitBreakerConfig
- type Config
- type Duration
- type Instructions
- type RestartPolicy
- type RetryConfig
- type SecurityConfig
- type ServerConfig
- type ServerInstructions
- type SlotGroupConfig
- type SupervisionConfig
- type ToolInstructions
- type TransportType
Constants ¶
const ( // DefaultConfigDir is the XDG-compliant config directory DefaultConfigDir = ".config/vision" // DefaultConfigFile is the default filename DefaultConfigFile = "servers.yaml" // DefaultEnvFile is the default environment file (dot-prefixed per dotenv convention) DefaultEnvFile = ".env" )
Default paths
const ( PriorityHigh = "high" PriorityMedium = "medium" PriorityLow = "low" )
Priority levels for tool/server guidance
const ( MinPort = 6276 MaxPort = 6325 )
Port range allocated for Vision MCP servers.
The range is 6276–6325 (50 ports). It was originally 6276–6300 (25 ports) before slot groups existed; v1.1.1 doubled the range to give realistic deployments enough headroom for multiple slot groups (each group consumes count + 1 ports: slots + virtual group port).
const InstructionsFile = "instructions.yaml"
InstructionsFile is the default filename for tool instructions
Variables ¶
var ( // ErrConfigNotFound is returned when the config file doesn't exist ErrConfigNotFound = errors.New("config: file not found") // ErrConfigParse is returned when the config file can't be parsed ErrConfigParse = errors.New("config: parse error") )
var ( ErrInvalidPort = errors.New("config: port must be between 6276 and 6325") ErrDuplicatePort = errors.New("config: duplicate port assignment") ErrMissingCommand = errors.New("config: stdio transport requires 'command' field") ErrEmptyCommand = errors.New("config: command cannot be empty string") ErrMissingURL = errors.New("config: http/sse transport requires 'url' field") ErrConflictingConfig = errors.New("config: cannot specify both 'command' and 'url'") ErrInvalidTransport = errors.New("config: invalid transport type") ErrInvalidRestartPolicy = errors.New("config: invalid restart_policy (must be 'always', 'on-failure', or 'never')") ErrInvalidAvailabilityProfile = errors.New("config: invalid availability_profile") ErrInvalidHTTPURL = errors.New("config: http transport url must end with '/mcp'") ErrInvalidHealthCheckInterval = errors.New("config: health_check_interval must be >= 5s") ErrInvalidRequestTimeout = errors.New("config: request_timeout must be >= 1s") ErrInvalidRetryMaxAttempts = errors.New("config: retry.max_attempts must be >= 1") ErrInvalidRetryInitialDelay = errors.New("config: retry.initial_delay must be >= 1ms") ErrInvalidRetryMaxDelay = errors.New("config: retry.max_delay must be >= 1ms") ErrInvalidRetryDelayRange = errors.New("config: retry.max_delay must be >= retry.initial_delay") ErrInvalidCircuitFailureThreshold = errors.New("config: circuit_breaker.failure_threshold must be >= 1") ErrInvalidCircuitRecoveryTimeout = errors.New("config: circuit_breaker.recovery_timeout must be >= 1s") ErrInvalidMaxInFlightRequests = errors.New("config: max_in_flight_requests must be >= 0") )
Validation errors
var ( // ErrInstructionsNotFound is returned when the instructions file doesn't exist ErrInstructionsNotFound = errors.New("instructions: file not found") )
Functions ¶
func DefaultConfigPath ¶
func DefaultConfigPath() string
DefaultConfigPath returns the default config file path: ~/.config/vision/servers.yaml
func DefaultEnvPath ¶
func DefaultEnvPath() string
DefaultEnvPath returns the default env file path: ~/.config/vision/.env
func DefaultInstructionsPath ¶
func DefaultInstructionsPath() string
DefaultInstructionsPath returns the default instructions file path: ~/.config/vision/instructions.yaml
func ExpandEnvVars ¶
ExpandEnvVars expands environment variables in the format ${VAR} or ${VAR:-default}.
func LoadEnvFile ¶
LoadEnvFile loads environment variables from the given file into os.Environ. If path is empty, it uses DefaultEnvPath(). The file format is KEY=VALUE, one per line. Lines starting with # are comments. Returns nil if the file doesn't exist (env file is optional).
Types ¶
type AvailabilityProfile ¶
type AvailabilityProfile string
AvailabilityProfile defines opinionated resilience defaults for a server.
const ( // AvailabilityProfileNetworked applies stronger timeout/retry/circuit defaults // for servers whose tool calls depend on upstream network providers. AvailabilityProfileNetworked AvailabilityProfile = "networked" )
type CircuitBreakerConfig ¶
type CircuitBreakerConfig struct {
FailureThreshold int `yaml:"failure_threshold,omitempty" env:"FAILURE_THRESHOLD" env-default:"5"`
RecoveryTimeout Duration `yaml:"recovery_timeout,omitempty" env:"RECOVERY_TIMEOUT" env-default:"60s"`
}
CircuitBreakerConfig controls fast-fail behavior after repeated failures.
type Config ¶
type Config struct {
// Servers maps server names to their configurations.
Servers map[string]*ServerConfig `yaml:"servers"`
// SlotGroups declaratively define pools of identical servers that may be
// expanded into flat server entries at load time.
SlotGroups map[string]*SlotGroupConfig `yaml:"slot_groups,omitempty"`
// Security holds daemon-wide security settings for MCP endpoints.
Security SecurityConfig `yaml:"security"`
// Supervision holds global supervisor settings.
Supervision SupervisionConfig `yaml:"supervision"`
}
Config is the root configuration structure for Vision.
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a minimal default configuration.
func Load ¶
Load reads and parses a config file from the given path. If path is empty, it uses DefaultConfigPath(). Environment variables in the format ${VAR} or ${VAR:-default} are expanded. The env file (~/.config/vision/.env) is loaded first if it exists.
func LoadOrCreate ¶
LoadOrCreate loads a config file, creating a default one if it doesn't exist. This is useful for first-run scenarios.
func MustLoad ¶
MustLoad loads a config file, panicking on error. Useful for tests and initialization where errors should be fatal.
func ParseYAML ¶
ParseYAML parses a YAML string into a Config. Useful for testing or loading embedded configs.
func (*Config) ApplyDefaults ¶
func (c *Config) ApplyDefaults()
ApplyDefaults sets default values for all servers and supervision.
func (*Config) GetServer ¶
func (c *Config) GetServer(name string) *ServerConfig
GetServer returns a server config by name, or nil if not found.
func (*Config) NextAvailablePort ¶
NextAvailablePort returns the next unused port in the Vision range (MinPort-MaxPort). It checks against all ports currently assigned in the Config. Returns 0 and an error if all ports are exhausted.
func (*Config) ServerNames ¶
ServerNames returns a sorted list of server names.
type Duration ¶
Duration is a time.Duration that supports YAML unmarshaling from strings like "30s".
func (Duration) MarshalYAML ¶
MarshalYAML implements yaml.Marshaler for Duration.
func (*Duration) UnmarshalYAML ¶
UnmarshalYAML implements yaml.Unmarshaler for Duration.
type Instructions ¶
type Instructions struct {
// Servers maps server names to their instructions
Servers map[string]*ServerInstructions `yaml:"servers,omitempty" json:"servers,omitempty"`
// Tools maps tool names to their instructions (for cross-server tool guidance)
Tools map[string]*ToolInstructions `yaml:"tools,omitempty" json:"tools,omitempty"`
// GlobalGuidance is general guidance that applies to all tool selection
GlobalGuidance string `yaml:"global_guidance,omitempty" json:"global_guidance,omitempty"`
}
Instructions is the root structure for tool/server guidance configuration.
func LoadInstructions ¶
func LoadInstructions(path string) (*Instructions, error)
LoadInstructions reads and parses an instructions file from the given path. If path is empty, it uses DefaultInstructionsPath(). Returns an empty Instructions struct (not nil) if file doesn't exist.
func (*Instructions) GetServerInstructions ¶
func (i *Instructions) GetServerInstructions(name string) *ServerInstructions
GetServerInstructions returns instructions for a specific server, or nil if not found.
func (*Instructions) GetToolInstructions ¶
func (i *Instructions) GetToolInstructions(name string) *ToolInstructions
GetToolInstructions returns instructions for a specific tool, or nil if not found.
func (*Instructions) HasInstructions ¶
func (i *Instructions) HasInstructions() bool
HasInstructions returns true if any instructions are configured.
func (*Instructions) ServerNames ¶
func (i *Instructions) ServerNames() []string
ServerNames returns a sorted list of server names with instructions.
func (*Instructions) ToolNames ¶
func (i *Instructions) ToolNames() []string
ToolNames returns a sorted list of tool names with instructions.
type RestartPolicy ¶
type RestartPolicy string
RestartPolicy defines when a server should be restarted.
const ( RestartAlways RestartPolicy = "always" RestartOnFailure RestartPolicy = "on-failure" RestartNever RestartPolicy = "never" )
type RetryConfig ¶
type RetryConfig struct {
MaxAttempts int `yaml:"max_attempts,omitempty" env:"MAX_ATTEMPTS" env-default:"1"`
InitialDelay Duration `yaml:"initial_delay,omitempty" env:"INITIAL_DELAY" env-default:"100ms"`
MaxDelay Duration `yaml:"max_delay,omitempty" env:"MAX_DELAY" env-default:"5s"`
RetryableErrors []string `yaml:"retryable_errors,omitempty"`
}
RetryConfig controls retry behavior for retryable downstream failures.
type SecurityConfig ¶
type SecurityConfig struct {
// BearerToken is the shared secret for Authorization header validation.
// When empty, authentication is not enforced (open access).
// Supports ${VAR} expansion from the environment.
BearerToken string `yaml:"bearer_token,omitempty" env:"VISION_BEARER_TOKEN"`
// AllowedOrigins is the list of permitted Origin header values.
// When empty, origin checking is not enforced.
// Wildcard ("*") is explicitly rejected and treated as disallowed.
AllowedOrigins []string `yaml:"allowed_origins,omitempty"`
}
SecurityConfig holds daemon-wide security settings for MCP endpoints.
type ServerConfig ¶
type ServerConfig struct {
// Port is the HTTP port Vision exposes this server on (6276-6300).
Port int `yaml:"port" env:"PORT"`
// Transport is "stdio", "managed-http", "http", or "sse". Inferred if not set,
// except managed-http which must be explicit because it owns command + URL.
Transport TransportType `yaml:"transport,omitempty" env:"TRANSPORT"`
// Command is the executable to run (for stdio transport).
Command string `yaml:"command,omitempty" env:"COMMAND"`
// Args are command-line arguments passed to Command.
Args []string `yaml:"args,omitempty"`
// Env are environment variables passed to the subprocess.
// Values support ${VAR} expansion from the host environment.
Env map[string]string `yaml:"env,omitempty"`
// URL is the upstream MCP server URL (for http/sse transports).
URL string `yaml:"url,omitempty" env:"URL"`
// Headers are HTTP headers to forward (for http transport).
Headers map[string]string `yaml:"headers,omitempty"`
// Autostart determines if this server starts with the daemon.
Autostart bool `yaml:"autostart,omitempty" env:"AUTOSTART" env-default:"false"`
// RestartPolicy controls automatic restart behavior.
RestartPolicy RestartPolicy `yaml:"restart_policy,omitempty" env:"RESTART_POLICY" env-default:"on-failure"`
// MaxRestarts is the maximum restart attempts within a 5-minute window.
MaxRestarts int `yaml:"max_restarts,omitempty" env:"MAX_RESTARTS" env-default:"5"`
// Stateful enables process-per-session mode for isolated state.
Stateful bool `yaml:"stateful,omitempty" env:"STATEFUL" env-default:"false"`
// AvailabilityProfile selects opinionated resilience defaults for the server.
AvailabilityProfile AvailabilityProfile `yaml:"availability_profile,omitempty" env:"AVAILABILITY_PROFILE"`
// SessionTimeout is how long an idle session lives (for stateful servers).
SessionTimeout Duration `yaml:"session_timeout,omitempty" env:"SESSION_TIMEOUT" env-default:"5m"`
// MaxSessions limits concurrent sessions (for stateful servers, 0 = unlimited).
MaxSessions int `yaml:"max_sessions,omitempty" env:"MAX_SESSIONS" env-default:"0"`
// SessionTTL is the absolute maximum lifetime of a session regardless of activity.
// 0 means no TTL (sessions only expire via idle timeout or explicit close).
SessionTTL Duration `yaml:"session_ttl,omitempty" env:"SESSION_TTL" env-default:"0s"`
// HealthCheckInterval is how often to probe idle downstream sessions for liveness.
// When set, the proxy layer sends periodic tools/list calls to detect dead
// subprocesses before a tool call hits the failure path. Must be >= 5s if set.
// 0 means use default (30s).
HealthCheckInterval Duration `yaml:"health_check_interval,omitempty" env:"HEALTH_CHECK_INTERVAL" env-default:"30s"`
// RequestTimeout is the default deadline Vision applies to downstream tool calls
// when the upstream request does not already specify one. 0 means use default (30s).
RequestTimeout Duration `yaml:"request_timeout,omitempty" env:"REQUEST_TIMEOUT" env-default:"30s"`
// Retry configures retry/backoff behavior for retryable downstream tool-call failures.
Retry *RetryConfig `yaml:"retry,omitempty"`
// CircuitBreaker configures fast-fail behavior after repeated downstream failures.
CircuitBreaker *CircuitBreakerConfig `yaml:"circuit_breaker,omitempty"`
// concurrent sessions for this server.
SharedReadOnlyTools []string `yaml:"shared_read_only_tools,omitempty"`
// 0 disables caching while still allowing in-flight coalescing.
SharedResultCacheTTL Duration `yaml:"shared_result_cache_ttl,omitempty" env:"SHARED_RESULT_CACHE_TTL"`
// 0 uses the default for the selected profile.
SharedResultCacheSize int `yaml:"shared_result_cache_size,omitempty" env:"SHARED_RESULT_CACHE_SIZE"`
// MaxInFlightRequests caps concurrent downstream tool calls per server.
// 0 means unlimited.
MaxInFlightRequests int `yaml:"max_in_flight_requests,omitempty" env:"MAX_IN_FLIGHT_REQUESTS"`
// Required indicates the server MUST be running for Vision (and any
// dependent agent) to function correctly. When both Autostart and
// Required are true, initial-start failure is fatal to daemon startup
// (daemon.StartAll returns a non-nil error). When Required is true but
// Autostart is false, the field is informational only — external tools
// such as OCA may surface it in doctor output.
Required bool `yaml:"required,omitempty" env:"REQUIRED" env-default:"false"`
// Source is an informational URL describing where this server comes
// from (homepage, repo). Accepted and preserved on round-trip; not
// interpreted by Vision. Populated by external configuration tools
// such as OpenCode Advance.
Source string `yaml:"source,omitempty"`
// Description is a short human-readable summary of the server.
// Accepted and preserved on round-trip; not interpreted by Vision.
// Populated by external configuration tools.
Description string `yaml:"description,omitempty"`
// DisconnectGracePeriod controls how long to wait after the last HTTP connection
// closes before removing a shared-mode upstream session. Only applies to
// non-stateful servers using SharedSessionManager. 0 uses default (60s).
// Negative values disable disconnect detection entirely.
DisconnectGracePeriod Duration `yaml:"disconnect_grace_period,omitempty"`
// IdleReapTimeout controls how long a shared-mode backend subprocess lives after
// the last upstream session disconnects. Only applies to non-stateful servers
// using SharedSessionManager. 0 uses default (5m). Negative values disable
// idle reaping entirely (subprocess lives forever).
IdleReapTimeout Duration `yaml:"idle_reap_timeout,omitempty"`
// SlotGroup is internal metadata set when this server was synthesized from a
// slot_groups entry. It is not persisted to YAML.
SlotGroup string `yaml:"-"`
// SlotIndex is the 1-based position of the synthesized server within its
// slot group. It is not persisted to YAML.
SlotIndex int `yaml:"-"`
}
ServerConfig defines a single MCP server's configuration.
func (*ServerConfig) ApplyDefaults ¶
func (s *ServerConfig) ApplyDefaults()
ApplyDefaults sets default values for missing optional fields.
func (*ServerConfig) InferTransport ¶
func (s *ServerConfig) InferTransport() TransportType
InferTransport determines the transport type from config fields. Returns TransportStdio if command is set, or infers from URL pattern.
func (*ServerConfig) ResolvedDisconnectGracePeriod ¶ added in v1.2.3
func (s *ServerConfig) ResolvedDisconnectGracePeriod() time.Duration
ResolvedDisconnectGracePeriod returns the effective disconnect grace period. Negative values return 0 (disabled). Zero returns the default (60s).
func (*ServerConfig) ResolvedIdleReapTimeout ¶ added in v1.2.4
func (s *ServerConfig) ResolvedIdleReapTimeout() time.Duration
ResolvedIdleReapTimeout returns the effective idle reap timeout. Negative values return 0 (disabled). Zero returns the default (5m).
func (*ServerConfig) Validate ¶
func (s *ServerConfig) Validate(name string) error
Validate checks that the ServerConfig is valid.
type ServerInstructions ¶
type ServerInstructions struct {
// Priority indicates how preferred this server is (high, medium, low)
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
// Guidance is extended usage instructions for AI agents
Guidance string `yaml:"guidance,omitempty" json:"guidance,omitempty"`
// PreferFor lists use cases where this server should be preferred
PreferFor []string `yaml:"prefer_for,omitempty" json:"prefer_for,omitempty"`
// AvoidFor lists use cases where this server should NOT be used
AvoidFor []string `yaml:"avoid_for,omitempty" json:"avoid_for,omitempty"`
// Examples are usage examples to help agents understand correct usage
Examples []string `yaml:"examples,omitempty" json:"examples,omitempty"`
}
ServerInstructions defines guidance for an MCP server.
type SlotGroupConfig ¶
type SlotGroupConfig struct {
Template string `yaml:"template"`
BasePort int `yaml:"base_port"`
Count int `yaml:"count"`
GroupPort int `yaml:"group_port"`
Defaults *ServerConfig `yaml:"defaults,omitempty"`
}
SlotGroupConfig defines a pool of identical servers plus one virtual group endpoint that routes sessions to the least-loaded healthy slot.
type SupervisionConfig ¶
type SupervisionConfig struct {
// HealthCheckInterval is how often to check server health.
HealthCheckInterval Duration `yaml:"health_check_interval" env:"HEALTH_CHECK_INTERVAL" env-default:"30s"`
// ShutdownTimeout is the grace period for graceful shutdown.
ShutdownTimeout Duration `yaml:"shutdown_timeout" env:"SHUTDOWN_TIMEOUT" env-default:"10s"`
// RestartDelay is the initial delay before restarting a crashed server.
RestartDelay Duration `yaml:"restart_delay" env:"RESTART_DELAY" env-default:"1s"`
// MaxRestartDelay is the maximum delay (for exponential backoff).
MaxRestartDelay Duration `yaml:"max_restart_delay" env:"MAX_RESTART_DELAY" env-default:"60s"`
}
SupervisionConfig holds global supervisor settings.
func (*SupervisionConfig) ApplyDefaults ¶
func (sup *SupervisionConfig) ApplyDefaults()
ApplyDefaults sets default values for the supervision config.
type ToolInstructions ¶
type ToolInstructions struct {
// NamespacedName is the callable OpenCode Code Mode form, for example
// tools.lgrep.search_semantic. When omitted, Vision may derive it from the
// canonical tool name and configured server names.
NamespacedName string `yaml:"namespaced_name,omitempty" json:"namespaced_name,omitempty"`
// Priority indicates how preferred this tool is (high, medium, low)
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
// Guidance is extended usage instructions for AI agents
Guidance string `yaml:"guidance,omitempty" json:"guidance,omitempty"`
// PreferFor lists use cases where this tool should be preferred
PreferFor []string `yaml:"prefer_for,omitempty" json:"prefer_for,omitempty"`
// AvoidFor lists use cases where this tool should NOT be used
AvoidFor []string `yaml:"avoid_for,omitempty" json:"avoid_for,omitempty"`
// Examples are usage examples to help agents understand correct usage
Examples []string `yaml:"examples,omitempty" json:"examples,omitempty"`
}
ToolInstructions defines guidance for a specific tool within a server.
type TransportType ¶
type TransportType string
TransportType defines how Vision connects to an MCP server.
const ( // TransportStdio spawns a subprocess and bridges stdio to HTTP. // Requires: command (and optionally args, env) TransportStdio TransportType = "stdio" // TransportHTTP proxies to a native Streamable HTTP MCP server. // Requires: url (must end with /mcp) TransportHTTP TransportType = "http" // TransportManagedHTTP supervises a local native Streamable HTTP MCP // process and exposes it through Vision's authenticated listener. // Requires: command and a loopback URL ending exactly in /mcp. TransportManagedHTTP TransportType = "managed-http" // TransportSSE connects to a legacy SSE-based MCP server. // Requires: url TransportSSE TransportType = "sse" )