Skip to main content
Glama
ShivamPansuriya

Dynamic Per-User Tool Generation MCP Server

config_loader.py7.31 kB
""" Configuration Loader Loads and parses field mapping configurations from JSON files. Provides type-safe access to field mappings with validation. """ import json import logging from pathlib import Path from typing import Dict, List, Optional from dataclasses import dataclass logger = logging.getLogger(__name__) @dataclass class FieldMapping: """ Represents a single field mapping configuration. Attributes: column_name: The field name in the incoming request (e.g., "impact", "assignee") primitive_type: The data type (e.g., "long", "string") reference_to: The entity type to search in Elasticsearch (e.g., "impact", "user") db_key: The target field name in the transformed request (e.g., "impactId", "technicianId") required: Whether this field is required filters: Optional contextual filters to apply during resolution """ column_name: str primitive_type: str reference_to: str db_key: str required: bool = False filters: Optional[Dict[str, any]] = None @classmethod def from_dict(cls, data: dict) -> "FieldMapping": """Create FieldMapping from dictionary.""" return cls( column_name=data["columnName"], primitive_type=data["primitiveType"], reference_to=data["referenceTo"], db_key=data["dbKey"], required=data.get("required", False), filters=data.get("filters") ) def to_dict(self) -> dict: """Convert FieldMapping to dictionary.""" result = { "columnName": self.column_name, "primitiveType": self.primitive_type, "referenceTo": self.reference_to, "dbKey": self.db_key, "required": self.required } if self.filters: result["filters"] = self.filters return result class FieldMappingLoader: """ Loads and manages field mapping configurations. Supports multiple modules (request, problem, change, etc.) with lazy loading and caching for performance. """ def __init__(self, config_path: Optional[Path] = None): """ Initialize the configuration loader. Args: config_path: Path to the field_mappings.json file. If None, uses default path relative to this file. """ if config_path is None: # Default to field_mappings.json in the same directory config_path = Path(__file__).parent / "field_mappings.json" self.config_path = config_path self._config_cache: Optional[Dict[str, List[FieldMapping]]] = None logger.info(f"FieldMappingLoader initialized with config: {self.config_path}") def _load_config(self) -> Dict[str, List[FieldMapping]]: """ Load configuration from JSON file. Returns: Dictionary mapping module names to lists of FieldMapping objects Raises: FileNotFoundError: If config file doesn't exist json.JSONDecodeError: If config file is invalid JSON ValueError: If config structure is invalid """ if not self.config_path.exists(): raise FileNotFoundError(f"Configuration file not found: {self.config_path}") logger.debug(f"Loading configuration from {self.config_path}") with open(self.config_path, 'r') as f: raw_config = json.load(f) # Parse and validate configuration parsed_config = {} for module_name, field_list in raw_config.items(): if not isinstance(field_list, list): raise ValueError(f"Invalid config for module '{module_name}': expected list, got {type(field_list)}") parsed_config[module_name] = [ FieldMapping.from_dict(field_data) for field_data in field_list ] logger.info(f"Loaded configuration for {len(parsed_config)} modules: {list(parsed_config.keys())}") return parsed_config def get_config(self, force_reload: bool = False) -> Dict[str, List[FieldMapping]]: """ Get the full configuration with caching. Args: force_reload: If True, reload from file even if cached Returns: Dictionary mapping module names to field mappings """ if self._config_cache is None or force_reload: self._config_cache = self._load_config() return self._config_cache def get_module_mappings(self, module: str) -> List[FieldMapping]: """ Get field mappings for a specific module. Args: module: Module name (e.g., "request", "problem", "change") Returns: List of FieldMapping objects for the module Raises: ValueError: If module is not found in configuration """ config = self.get_config() if module not in config: available_modules = list(config.keys()) raise ValueError( f"Module '{module}' not found in configuration. " f"Available modules: {available_modules}" ) return config[module] def get_field_mapping(self, module: str, column_name: str) -> Optional[FieldMapping]: """ Get mapping for a specific field in a module. Args: module: Module name (e.g., "request") column_name: Field name (e.g., "impact", "assignee") Returns: FieldMapping object if found, None otherwise """ mappings = self.get_module_mappings(module) for mapping in mappings: if mapping.column_name == column_name: return mapping return None def get_mapping_by_column(self, module: str) -> Dict[str, FieldMapping]: """ Get field mappings indexed by column name for fast lookup. Args: module: Module name (e.g., "request") Returns: Dictionary mapping column names to FieldMapping objects """ mappings = self.get_module_mappings(module) return {mapping.column_name: mapping for mapping in mappings} def get_available_modules(self) -> List[str]: """ Get list of available module names. Returns: List of module names (e.g., ["request", "problem", "change"]) """ config = self.get_config() return list(config.keys()) def validate_module(self, module: str) -> bool: """ Check if a module exists in the configuration. Args: module: Module name to validate Returns: True if module exists, False otherwise """ return module in self.get_config() def reload(self): """Force reload configuration from file.""" logger.info("Reloading configuration from file") self._config_cache = None self.get_config()

Latest Blog Posts

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/ShivamPansuriya/MCP-server-Python'

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