Skip to main content
Glama

Model Context Protocol (MCP) Server

by hideya
config_loader.py4.16 kB
import os import re from pathlib import Path from typing import TypedDict, NotRequired, Any import pyjson5 as json5 class ConfigError(Exception): """Base exception for configuration related errors.""" pass class ConfigFileNotFoundError(ConfigError): """Raised when the configuration file cannot be found.""" pass class ConfigValidationError(ConfigError): """Raised when the configuration fails validation.""" pass class LLMConfig(TypedDict): """Type definition for LLM configuration.""" model_provider: NotRequired[str] provider: NotRequired[str] model: NotRequired[str] temperature: NotRequired[float] system_prompt: NotRequired[str] def normalize_config(cfg: dict) -> LLMConfig: """ Normalize alias keys so internal code can rely on 'model_provider'. """ pv = cfg.get("provider") mp = cfg.get("model_provider") if pv is None and mp is None: raise ConfigValidationError( '"provider" needs to be specified' ) elif pv is not None and mp is not None: raise ConfigValidationError( 'Both "provider" and "model_provider" are specified' ) elif pv is None and mp is not None: cfg["provider"] = mp del cfg["model_provider"] return cfg def load_config(config_path: str): """Load and validate configuration from JSON5 file with environment variable substitution. Args: config_path: Path to the JSON5 configuration file Returns: dict: Parsed configuration with environment variables substituted Raises: ConfigFileNotFoundError: If the config file doesn't exist ConfigValidationError: If environment variables are missing or parsing fails """ config_file = Path(config_path) if not config_file.exists(): raise ConfigFileNotFoundError(f"Config file {config_path} not found") with open(config_file, "r", encoding="utf-8") as f: content = f.read() # Replace ${VAR_NAME} with environment variable values w/o checking # for key, value in os.environ.items(): # content = content.replace(f"${{{key}}}", value or '') # Replace ${VAR_NAME} with environment variable values, but skip comments # to avoid raising ConfigValidationError for undefined variables in comments # (e.g., "// ${THIS_ENV_VAR_NOT_DEFINED_SO_COMMENTED_OUT_TO_AVOID_RAISING_EXCEPTION}") def replace_env_var(match): """Replace environment variable placeholder with actual value. Args: match: Regex match object containing variable name Returns: str: Environment variable value Raises: ConfigValidationError: If environment variable is not found """ var_name = match.group(1) env_value = os.getenv(var_name) if env_value is None: raise ConfigValidationError( f'Environment variable "{var_name}" used ' f'in "{config_file}" not found' ) return env_value # Process line by line to skip comments lines = content.split("\n") processed_lines = [] for line in lines: # Split line at first occurrence of "//" to separate code from comments if "//" in line: code_part, comment_part = line.split("//", 1) # Apply environment variable substitution only to the code part processed_code = re.sub(r"\$\{([^}]+)\}", replace_env_var, code_part) # Reconstruct line with original comment processed_line = processed_code + "//" + comment_part else: # No comment in line, apply substitution to entire line processed_line = re.sub(r"\$\{([^}]+)\}", replace_env_var, line) processed_lines.append(processed_line) content = "\n".join(processed_lines) # Parse the processed content as JSON5 config: dict[str, Any] = json5.loads(content) config["llm"] = normalize_config(config["llm"]) return config

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/hideya/mcp-client-langchain-py'

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