config

package
v1.3.5 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package config provides configuration loading, validation, and persistence for Vision MCP server registry.

Index

Constants

View Source
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

View Source
const (
	PriorityHigh   = "high"
	PriorityMedium = "medium"
	PriorityLow    = "low"
)

Priority levels for tool/server guidance

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

View Source
const InstructionsFile = "instructions.yaml"

InstructionsFile is the default filename for tool instructions

Variables

View Source
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")
)
View Source
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")
	ErrInvalidSharedResultCacheSize   = errors.New("config: shared_result_cache_size must be >= 0")
	ErrInvalidMaxInFlightRequests     = errors.New("config: max_in_flight_requests must be >= 0")
)

Validation errors

View Source
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

func ExpandEnvVars(input string) string

ExpandEnvVars expands environment variables in the format ${VAR} or ${VAR:-default}.

func LoadEnvFile

func LoadEnvFile(path string) error

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

func Save

func Save(cfg *Config, path string) error

Save writes a config to the given path using atomic write. It writes to a temp file first, then renames for atomicity.

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

func Load(path string) (*Config, error)

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

func LoadOrCreate(path string) (*Config, error)

LoadOrCreate loads a config file, creating a default one if it doesn't exist. This is useful for first-run scenarios.

func MustLoad

func MustLoad(path string) *Config

MustLoad loads a config file, panicking on error. Useful for tests and initialization where errors should be fatal.

func ParseYAML

func ParseYAML(data string) (*Config, error)

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

func (c *Config) NextAvailablePort() (int, error)

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

func (c *Config) ServerNames() []string

ServerNames returns a sorted list of server names.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks that the entire Config is valid. An empty config (no servers) is considered valid for first-run scenarios.

type Duration

type Duration time.Duration

Duration is a time.Duration that supports YAML unmarshaling from strings like "30s".

func (Duration) Duration

func (d Duration) Duration() time.Duration

Duration returns the underlying time.Duration value.

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (interface{}, error)

MarshalYAML implements yaml.Marshaler for Duration.

func (Duration) String

func (d Duration) String() string

String implements fmt.Stringer.

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error

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

	// SharedReadOnlyTools lists tool names that are safe to coalesce/cache across
	// concurrent sessions for this server.
	SharedReadOnlyTools []string `yaml:"shared_read_only_tools,omitempty"`

	// SharedResultCacheTTL is how long successful shared read-only results stay cached.
	// 0 disables caching while still allowing in-flight coalescing.
	SharedResultCacheTTL Duration `yaml:"shared_result_cache_ttl,omitempty" env:"SHARED_RESULT_CACHE_TTL"`

	// SharedResultCacheSize caps cached shared read-only results per server.
	// 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"
)

Jump to

Keyboard shortcuts

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