blob: be1fefecd8930d5358428d9a04ed5f7c0e18d3b1 [file] [log] [blame]
Akron90f65212025-06-12 14:32:55 +02001package config
2
3import (
4 "fmt"
5 "os"
6)
7
8// Config represents the complete configuration for KorAP MCP server
9type Config struct {
10 // Server configuration
11 Server ServerConfig `yaml:"server" embed:""`
12
13 // OAuth2 authentication configuration
14 OAuth OAuthConfig `yaml:"oauth"`
15
16 // KorAP API configuration
17 KorAP KorAPConfig `yaml:"korap"`
18
Akrone73bc912025-06-17 16:36:45 +020019 // Cache configuration
20 Cache CacheConfig `yaml:"cache"`
21
Akron90f65212025-06-12 14:32:55 +020022 // Logging configuration
23 Logging LoggingConfig `yaml:"logging"`
24}
25
26// ServerConfig represents server-specific configuration
27type ServerConfig struct {
28 // Name is the server name (constant, not configurable)
29 Name string `yaml:"-"`
30
31 // Version is the server version (constant, not configurable)
32 Version string `yaml:"-"`
33
34 // ConfigFile is the path to the configuration file (handled by CLI layer)
35 ConfigFile string `yaml:"-"`
36}
37
38// KorAPConfig represents KorAP API configuration
39type KorAPConfig struct {
40 // BaseURL is the KorAP server base URL
41 BaseURL string `yaml:"base_url" default:"https://korap.ids-mannheim.de" help:"KorAP server base URL"`
42
43 // APIVersion is the API version to use
44 APIVersion string `yaml:"api_version" default:"v1.0" help:"KorAP API version"`
45
46 // Timeout is the HTTP request timeout in seconds
47 Timeout int `yaml:"timeout" default:"30" help:"HTTP request timeout in seconds"`
48
49 // MaxRetries is the maximum number of retry attempts
50 MaxRetries int `yaml:"max_retries" default:"3" help:"Maximum number of retry attempts"`
51}
52
53// LoggingConfig represents logging configuration
54type LoggingConfig struct {
55 // Level is the logging level (trace, debug, info, warn, error)
56 Level string `yaml:"level" default:"info" enum:"trace,debug,info,warn,error" help:"Logging level"`
57
58 // Format is the log format (json, text)
59 Format string `yaml:"format" default:"text" enum:"json,text" help:"Log output format"`
60
61 // File is the log file path (empty for stdout)
62 File string `yaml:"file" help:"Log file path (empty for stdout)"`
63}
64
65// DefaultConfig returns a default configuration
66func DefaultConfig() *Config {
67 return &Config{
68 Server: ServerConfig{
69 // Name and Version are set by the CLI layer as constants
70 },
71 OAuth: *DefaultOAuthConfig(),
72 KorAP: KorAPConfig{
73 BaseURL: "https://korap.ids-mannheim.de",
74 APIVersion: "v1.0",
75 Timeout: 30,
76 MaxRetries: 3,
77 },
Akrone73bc912025-06-17 16:36:45 +020078 Cache: *DefaultCacheConfig(),
Akron90f65212025-06-12 14:32:55 +020079 Logging: LoggingConfig{
80 Level: "info",
81 Format: "text",
82 },
83 }
84}
85
86// Validate validates the complete configuration
87func (c *Config) Validate() error {
88 if err := c.OAuth.Validate(); err != nil {
89 return fmt.Errorf("oauth config validation failed: %w", err)
90 }
91
92 if err := c.KorAP.Validate(); err != nil {
93 return fmt.Errorf("korap config validation failed: %w", err)
94 }
95
Akrone73bc912025-06-17 16:36:45 +020096 if err := c.Cache.Validate(); err != nil {
97 return fmt.Errorf("cache config validation failed: %w", err)
98 }
99
Akron90f65212025-06-12 14:32:55 +0200100 if err := c.Logging.Validate(); err != nil {
101 return fmt.Errorf("logging config validation failed: %w", err)
102 }
103
104 return nil
105}
106
107// Validate validates KorAP configuration
108func (k *KorAPConfig) Validate() error {
109 if k.BaseURL == "" {
110 return fmt.Errorf("base_url cannot be empty")
111 }
112
113 if k.APIVersion == "" {
114 return fmt.Errorf("api_version cannot be empty")
115 }
116
117 if k.Timeout <= 0 {
118 return fmt.Errorf("timeout must be positive")
119 }
120
121 if k.MaxRetries < 0 {
122 return fmt.Errorf("max_retries cannot be negative")
123 }
124
125 return nil
126}
127
128// Validate validates logging configuration
129func (l *LoggingConfig) Validate() error {
130 validLevels := map[string]bool{
131 "trace": true,
132 "debug": true,
133 "info": true,
134 "warn": true,
135 "error": true,
136 }
137
138 if !validLevels[l.Level] {
139 return fmt.Errorf("invalid log level: %s", l.Level)
140 }
141
142 validFormats := map[string]bool{
143 "json": true,
144 "text": true,
145 }
146
147 if !validFormats[l.Format] {
148 return fmt.Errorf("invalid log format: %s", l.Format)
149 }
150
151 // Check if log file is writable if specified
152 if l.File != "" {
153 file, err := os.OpenFile(l.File, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
154 if err != nil {
155 return fmt.Errorf("cannot write to log file %s: %w", l.File, err)
156 }
157 file.Close()
158 }
159
160 return nil
161}
162
163// GetKorAPEndpoint returns the full KorAP API endpoint URL
164func (k *KorAPConfig) GetKorAPEndpoint() string {
165 return fmt.Sprintf("%s/api/%s", k.BaseURL, k.APIVersion)
166}