Skip to main content
Glama

FastAPI MCP Template

by joonheeu
config.py10.2 kB
""" Application configuration management with environment variable support. This module provides centralized configuration management with secure defaults, environment variable support, and validation for all application settings. """ from pydantic_settings import BaseSettings from pydantic import Field, field_validator from typing import Optional, List, Union import os import secrets from pathlib import Path class Settings(BaseSettings): """ Application settings with environment variable support. This class handles all configuration for the FastAPI + MCP application, including security, database, logging, and service settings. """ # App Info app_name: str = Field( default="My Awesome API", description="Application name displayed in docs and logs" ) app_version: str = Field( default="0.1.0", description="Application version" ) app_description: str = Field( default="FastAPI와 MCP를 활용한 API 서버", description="Application description for API documentation" ) environment: str = Field( default="development", description="Current environment (development, production, test)" ) # Server Settings host: str = Field( default="127.0.0.1", description="Server host address" ) port: int = Field( default=8000, ge=1, le=65535, description="Server port number" ) debug: bool = Field( default=True, description="Enable debug mode" ) reload: bool = Field( default=True, description="Enable auto-reload in development" ) # MCP Settings mcp_host: str = Field( default="127.0.0.1", description="MCP server host address" ) mcp_port: int = Field( default=8001, ge=1, le=65535, description="MCP server port number" ) mcp_transport: str = Field( default="sse", pattern="^(stdio|sse|streamable-http)$", description="MCP transport protocol" ) # Database Settings (for future use) database_url: Optional[str] = Field( default=None, description="Database connection URL" ) database_echo: bool = Field( default=False, description="Enable database query logging" ) # Security Settings secret_key: str = Field( default_factory=lambda: secrets.token_urlsafe(32), description="Secret key for JWT tokens and encryption" ) algorithm: str = Field( default="HS256", description="JWT algorithm" ) access_token_expire_minutes: int = Field( default=30, ge=1, description="JWT token expiration time in minutes" ) # CORS Settings - More secure defaults cors_origins: str = Field( default="http://localhost:3000,http://localhost:8080", description="Allowed CORS origins (comma-separated)" ) cors_credentials: bool = Field( default=True, description="Allow credentials in CORS requests" ) cors_methods: str = Field( default="GET,POST,PUT,DELETE,OPTIONS", description="Allowed CORS methods (comma-separated)" ) cors_headers: str = Field( default="*", description="Allowed CORS headers (comma-separated)" ) # External APIs external_api_url: Optional[str] = Field( default=None, description="External API base URL" ) external_api_key: Optional[str] = Field( default=None, description="External API key" ) # Logging Settings log_level: str = Field( default="INFO", pattern="^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$", description="Logging level" ) log_format: str = Field( default="%(asctime)s - %(name)s - %(levelname)s - %(message)s", description="Log message format" ) log_file: str = Field( default="logs/app.log", description="Log file path" ) # Testing testing: bool = Field( default=False, description="Enable testing mode" ) @property def cors_origins_list(self) -> List[str]: """Get CORS origins as a list.""" if isinstance(self.cors_origins, str): return [origin.strip() for origin in self.cors_origins.split(',') if origin.strip()] return self.cors_origins @property def cors_methods_list(self) -> List[str]: """Get CORS methods as a list.""" if isinstance(self.cors_methods, str): return [method.strip() for method in self.cors_methods.split(',') if method.strip()] return self.cors_methods @property def cors_headers_list(self) -> List[str]: """Get CORS headers as a list.""" if isinstance(self.cors_headers, str): if self.cors_headers.strip() == "*": return ["*"] return [header.strip() for header in self.cors_headers.split(',') if header.strip()] return self.cors_headers @field_validator('secret_key') @classmethod def validate_secret_key(cls, v): """Validate that secret key is not the default insecure value.""" if v == "your-secret-key-change-this-in-production": # Generate a secure random key if default is used return secrets.token_urlsafe(32) if len(v) < 32: raise ValueError("Secret key must be at least 32 characters long") return v @property def is_development(self) -> bool: """Check if running in development environment.""" return self.environment.lower() == "development" @property def is_production(self) -> bool: """Check if running in production environment.""" return self.environment.lower() == "production" @property def is_testing(self) -> bool: """Check if running in testing environment.""" return self.environment.lower() == "test" or self.testing model_config = { "env_file": ".env", "env_file_encoding": "utf-8", "case_sensitive": False, "extra": "ignore", "env_parse_none_str": "null", "env_parse_enums": True, "env_nested_delimiter": "__", } class DevelopmentSettings(Settings): """ Development environment settings. These settings are optimized for local development with enhanced debugging capabilities and relaxed security constraints. """ debug: bool = True reload: bool = True log_level: str = "DEBUG" # More permissive CORS for development cors_origins: str = "http://localhost:3000,http://localhost:3001,http://localhost:8080,http://localhost:8081,http://127.0.0.1:3000,http://127.0.0.1:8080" class ProductionSettings(Settings): """ Production environment settings. These settings prioritize security and performance for production deployments with strict validation and minimal logging. """ debug: bool = False reload: bool = False log_level: str = "WARNING" # Strict CORS settings for production cors_origins: str = "" # Must be explicitly set via environment @field_validator('secret_key') @classmethod def validate_production_secret_key(cls, v): """Ensure secret key is properly set in production.""" if not v or len(v) < 32: raise ValueError( "SECRET_KEY environment variable must be set with a secure value " "of at least 32 characters in production" ) return v @field_validator('cors_origins') @classmethod def validate_production_cors(cls, v): """Ensure CORS origins are explicitly configured in production.""" if not v: raise ValueError( "CORS_ORIGINS must be explicitly configured in production. " "Set CORS_ORIGINS environment variable with allowed domains." ) return v class TestSettings(Settings): """ Test environment settings. These settings are optimized for automated testing with predictable behavior and enhanced logging for debugging test failures. """ debug: bool = True testing: bool = True log_level: str = "DEBUG" # Use fixed secret key for consistent testing secret_key: str = "test-secret-key-for-testing-purposes-only-32-chars" # Test database settings database_url: str = "sqlite:///./test.db" database_echo: bool = True # Permissive CORS for testing cors_origins: str = "*" def get_settings() -> Settings: """ Get settings based on environment. This function determines the current environment and returns the appropriate settings class with environment-specific configurations. Returns: Settings instance for the current environment Environment Variables: ENVIRONMENT: Set to 'development', 'production', or 'test' ENV: Alternative to ENVIRONMENT (for backward compatibility) """ # Check both ENVIRONMENT and ENV for flexibility env = os.getenv("ENVIRONMENT") or os.getenv("ENV", "development") env = env.lower().strip() if env == "production": return ProductionSettings() elif env in ("test", "testing"): return TestSettings() else: # Default to development return DevelopmentSettings() # Global settings instance settings = get_settings() # Log the configuration being used (for debugging) import logging _config_logger = logging.getLogger(__name__) _config_logger.debug(f"Configuration loaded: {settings.__class__.__name__}") _config_logger.debug(f"Environment: {settings.environment}") _config_logger.debug(f"Debug mode: {settings.debug}") def get_settings_for_testing() -> TestSettings: """ Get test settings explicitly. This function is useful for dependency injection in tests where you want to ensure test settings are used. Returns: TestSettings instance """ return TestSettings()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/joonheeu/fastapi-mcp-template'

If you have feedback or need assistance with the MCP directory API, please join our Discord server