.
This commit is contained in:
109
src/aegis_gitea_mcp/config.py
Normal file
109
src/aegis_gitea_mcp/config.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""Configuration management for AegisGitea MCP server."""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field, HttpUrl, field_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application settings loaded from environment variables."""
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
case_sensitive=False,
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
# Gitea configuration
|
||||
gitea_url: HttpUrl = Field(
|
||||
...,
|
||||
description="Base URL of the Gitea instance",
|
||||
)
|
||||
gitea_token: str = Field(
|
||||
...,
|
||||
description="Bot user access token for Gitea API",
|
||||
min_length=1,
|
||||
)
|
||||
|
||||
# MCP server configuration
|
||||
mcp_host: str = Field(
|
||||
default="0.0.0.0",
|
||||
description="Host to bind MCP server to",
|
||||
)
|
||||
mcp_port: int = Field(
|
||||
default=8080,
|
||||
description="Port to bind MCP server to",
|
||||
ge=1,
|
||||
le=65535,
|
||||
)
|
||||
|
||||
# Logging configuration
|
||||
log_level: str = Field(
|
||||
default="INFO",
|
||||
description="Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
|
||||
)
|
||||
audit_log_path: Path = Field(
|
||||
default=Path("/var/log/aegis-mcp/audit.log"),
|
||||
description="Path to audit log file",
|
||||
)
|
||||
|
||||
# Security configuration
|
||||
max_file_size_bytes: int = Field(
|
||||
default=1_048_576, # 1MB
|
||||
description="Maximum file size that can be read (in bytes)",
|
||||
ge=1,
|
||||
)
|
||||
request_timeout_seconds: int = Field(
|
||||
default=30,
|
||||
description="Timeout for Gitea API requests (in seconds)",
|
||||
ge=1,
|
||||
)
|
||||
rate_limit_per_minute: int = Field(
|
||||
default=60,
|
||||
description="Maximum number of requests per minute",
|
||||
ge=1,
|
||||
)
|
||||
|
||||
@field_validator("log_level")
|
||||
@classmethod
|
||||
def validate_log_level(cls, v: str) -> str:
|
||||
"""Validate log level is one of the allowed values."""
|
||||
allowed_levels = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
|
||||
v_upper = v.upper()
|
||||
if v_upper not in allowed_levels:
|
||||
raise ValueError(f"log_level must be one of {allowed_levels}")
|
||||
return v_upper
|
||||
|
||||
@field_validator("gitea_token")
|
||||
@classmethod
|
||||
def validate_token_not_empty(cls, v: str) -> str:
|
||||
"""Validate Gitea token is not empty or whitespace."""
|
||||
if not v.strip():
|
||||
raise ValueError("gitea_token cannot be empty or whitespace")
|
||||
return v.strip()
|
||||
|
||||
@property
|
||||
def gitea_base_url(self) -> str:
|
||||
"""Get Gitea base URL as string."""
|
||||
return str(self.gitea_url).rstrip("/")
|
||||
|
||||
|
||||
# Global settings instance
|
||||
_settings: Optional[Settings] = None
|
||||
|
||||
|
||||
def get_settings() -> Settings:
|
||||
"""Get or create global settings instance."""
|
||||
global _settings
|
||||
if _settings is None:
|
||||
_settings = Settings() # type: ignore
|
||||
return _settings
|
||||
|
||||
|
||||
def reset_settings() -> None:
|
||||
"""Reset global settings instance (primarily for testing)."""
|
||||
global _settings
|
||||
_settings = None
|
||||
Reference in New Issue
Block a user