This commit is contained in:
2026-01-29 19:53:36 +01:00
parent 1bda2013bb
commit a9708b33e2
27 changed files with 3745 additions and 4 deletions

View 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