Initial minimal mcp server for KorAP
diff --git a/config/config.go b/config/config.go
new file mode 100644
index 0000000..361ae2b
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,158 @@
+package config
+
+import (
+ "fmt"
+ "os"
+)
+
+// Config represents the complete configuration for KorAP MCP server
+type Config struct {
+ // Server configuration
+ Server ServerConfig `yaml:"server" embed:""`
+
+ // OAuth2 authentication configuration
+ OAuth OAuthConfig `yaml:"oauth"`
+
+ // KorAP API configuration
+ KorAP KorAPConfig `yaml:"korap"`
+
+ // Logging configuration
+ Logging LoggingConfig `yaml:"logging"`
+}
+
+// ServerConfig represents server-specific configuration
+type ServerConfig struct {
+ // Name is the server name (constant, not configurable)
+ Name string `yaml:"-"`
+
+ // Version is the server version (constant, not configurable)
+ Version string `yaml:"-"`
+
+ // ConfigFile is the path to the configuration file (handled by CLI layer)
+ ConfigFile string `yaml:"-"`
+}
+
+// KorAPConfig represents KorAP API configuration
+type KorAPConfig struct {
+ // BaseURL is the KorAP server base URL
+ BaseURL string `yaml:"base_url" default:"https://korap.ids-mannheim.de" help:"KorAP server base URL"`
+
+ // APIVersion is the API version to use
+ APIVersion string `yaml:"api_version" default:"v1.0" help:"KorAP API version"`
+
+ // Timeout is the HTTP request timeout in seconds
+ Timeout int `yaml:"timeout" default:"30" help:"HTTP request timeout in seconds"`
+
+ // MaxRetries is the maximum number of retry attempts
+ MaxRetries int `yaml:"max_retries" default:"3" help:"Maximum number of retry attempts"`
+}
+
+// LoggingConfig represents logging configuration
+type LoggingConfig struct {
+ // Level is the logging level (trace, debug, info, warn, error)
+ Level string `yaml:"level" default:"info" enum:"trace,debug,info,warn,error" help:"Logging level"`
+
+ // Format is the log format (json, text)
+ Format string `yaml:"format" default:"text" enum:"json,text" help:"Log output format"`
+
+ // File is the log file path (empty for stdout)
+ File string `yaml:"file" help:"Log file path (empty for stdout)"`
+}
+
+// DefaultConfig returns a default configuration
+func DefaultConfig() *Config {
+ return &Config{
+ Server: ServerConfig{
+ // Name and Version are set by the CLI layer as constants
+ },
+ OAuth: *DefaultOAuthConfig(),
+ KorAP: KorAPConfig{
+ BaseURL: "https://korap.ids-mannheim.de",
+ APIVersion: "v1.0",
+ Timeout: 30,
+ MaxRetries: 3,
+ },
+ Logging: LoggingConfig{
+ Level: "info",
+ Format: "text",
+ },
+ }
+}
+
+// Validate validates the complete configuration
+func (c *Config) Validate() error {
+ if err := c.OAuth.Validate(); err != nil {
+ return fmt.Errorf("oauth config validation failed: %w", err)
+ }
+
+ if err := c.KorAP.Validate(); err != nil {
+ return fmt.Errorf("korap config validation failed: %w", err)
+ }
+
+ if err := c.Logging.Validate(); err != nil {
+ return fmt.Errorf("logging config validation failed: %w", err)
+ }
+
+ return nil
+}
+
+// Validate validates KorAP configuration
+func (k *KorAPConfig) Validate() error {
+ if k.BaseURL == "" {
+ return fmt.Errorf("base_url cannot be empty")
+ }
+
+ if k.APIVersion == "" {
+ return fmt.Errorf("api_version cannot be empty")
+ }
+
+ if k.Timeout <= 0 {
+ return fmt.Errorf("timeout must be positive")
+ }
+
+ if k.MaxRetries < 0 {
+ return fmt.Errorf("max_retries cannot be negative")
+ }
+
+ return nil
+}
+
+// Validate validates logging configuration
+func (l *LoggingConfig) Validate() error {
+ validLevels := map[string]bool{
+ "trace": true,
+ "debug": true,
+ "info": true,
+ "warn": true,
+ "error": true,
+ }
+
+ if !validLevels[l.Level] {
+ return fmt.Errorf("invalid log level: %s", l.Level)
+ }
+
+ validFormats := map[string]bool{
+ "json": true,
+ "text": true,
+ }
+
+ if !validFormats[l.Format] {
+ return fmt.Errorf("invalid log format: %s", l.Format)
+ }
+
+ // Check if log file is writable if specified
+ if l.File != "" {
+ file, err := os.OpenFile(l.File, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
+ if err != nil {
+ return fmt.Errorf("cannot write to log file %s: %w", l.File, err)
+ }
+ file.Close()
+ }
+
+ return nil
+}
+
+// GetKorAPEndpoint returns the full KorAP API endpoint URL
+func (k *KorAPConfig) GetKorAPEndpoint() string {
+ return fmt.Sprintf("%s/api/%s", k.BaseURL, k.APIVersion)
+}