33
44This module provides functionality to load and validate MCI configuration files
55using the MCIClient from mci-py. It handles schema validation, error handling,
6- and provides user-friendly error messages.
6+ and provides user-friendly error messages. It also automatically loads environment
7+ variables from .env files in the project root and ./mci directory.
78"""
89
10+ from pathlib import Path
11+
912from mcipy import MCIClient , MCIClientError
1013
14+ from mci .utils .dotenv import get_env_with_dotenv
15+
1116
1217class MCIConfig :
1318 """
@@ -17,19 +22,40 @@ class MCIConfig:
1722 MCIClient from mci-py, which performs built-in schema validation.
1823 It also provides utilities for validating schemas and extracting
1924 user-friendly error messages.
25+
26+ The class automatically loads environment variables from .env files in:
27+ - The project root directory (same location as the MCI schema file)
28+ - The ./mci directory
29+
30+ Variables are merged with project root taking precedence over ./mci/.env.
2031 """
2132
2233 @staticmethod
23- def load (file_path : str , env_vars : dict [str , str ] | None = None ) -> MCIClient :
34+ def load (
35+ file_path : str , env_vars : dict [str , str ] | None = None , auto_load_dotenv : bool = True
36+ ) -> MCIClient :
2437 """
2538 Load and parse an MCI configuration file using MCIClient.
2639
2740 This method uses MCIClient from mci-py to load and validate the schema.
2841 The MCIClient performs comprehensive schema validation during initialization.
2942
43+ If auto_load_dotenv is True (default), automatically loads environment variables
44+ from .env and .env.mci files. Priority order:
45+ - If .env.mci files exist:
46+ 1. ./mci/.env.mci (library MCI-specific)
47+ 2. Project root .env.mci (project MCI-specific)
48+ - If no .env.mci files exist:
49+ 1. ./mci/.env (library defaults)
50+ 2. Project root .env (project-level)
51+ - Then:
52+ 3. System environment variables
53+ 4. env_vars argument (highest priority)
54+
3055 Args:
3156 file_path: Path to the MCI schema file (.json, .yaml, or .yml)
32- env_vars: Optional environment variables for template substitution
57+ env_vars: Optional environment variables for template substitution (highest priority)
58+ auto_load_dotenv: Whether to automatically load .env files (default: True)
3359
3460 Returns:
3561 An initialized MCIClient instance
@@ -41,20 +67,33 @@ def load(file_path: str, env_vars: dict[str, str] | None = None) -> MCIClient:
4167 Example:
4268 >>> config = MCIConfig()
4369 >>> try:
70+ ... # Auto-loads .env files from project root and ./mci
4471 ... client = config.load("mci.json")
4572 ... tools = client.tools()
4673 ... except MCIClientError as e:
4774 ... print(f"Schema invalid: {e}")
4875 """
4976 try :
50- client = MCIClient (schema_file_path = file_path , env_vars = env_vars or {})
77+ # Determine project root from schema file location
78+ project_root = Path (file_path ).parent .resolve ()
79+
80+ # Load environment variables with proper precedence
81+ if auto_load_dotenv :
82+ merged_env = get_env_with_dotenv (project_root , env_vars )
83+ else :
84+ # If auto-loading is disabled, just use provided env_vars
85+ merged_env = env_vars or {}
86+
87+ client = MCIClient (schema_file_path = file_path , env_vars = merged_env )
5188 return client
5289 except MCIClientError :
5390 # Re-raise with the original error message from mci-py
5491 raise
5592
5693 @staticmethod
57- def validate_schema (file_path : str , env_vars : dict [str , str ] | None = None ) -> tuple [bool , str ]:
94+ def validate_schema (
95+ file_path : str , env_vars : dict [str , str ] | None = None , auto_load_dotenv : bool = True
96+ ) -> tuple [bool , str ]:
5897 """
5998 Validate an MCI schema file using MCIClient.
6099
@@ -63,9 +102,13 @@ def validate_schema(file_path: str, env_vars: dict[str, str] | None = None) -> t
63102 MCIClient performs comprehensive validation including schema structure,
64103 required fields, and data types.
65104
105+ If auto_load_dotenv is True (default), automatically loads environment variables
106+ from .env files in the project root and ./mci directory.
107+
66108 Args:
67109 file_path: Path to the MCI schema file to validate
68110 env_vars: Optional environment variables for template substitution
111+ auto_load_dotenv: Whether to automatically load .env files (default: True)
69112
70113 Returns:
71114 A tuple of (is_valid, error_message) where:
@@ -79,9 +122,19 @@ def validate_schema(file_path: str, env_vars: dict[str, str] | None = None) -> t
79122 ... print(f"Validation failed: {error}")
80123 """
81124 try :
125+ # Determine project root from schema file location
126+ project_root = Path (file_path ).parent .resolve ()
127+
128+ # Load environment variables with proper precedence
129+ if auto_load_dotenv :
130+ merged_env = get_env_with_dotenv (project_root , env_vars )
131+ else :
132+ # If auto-loading is disabled, just use provided env_vars
133+ merged_env = env_vars or {}
134+
82135 # Use validating=True to skip template resolution for MCP servers
83136 # This allows validation without requiring all env_vars at validation time
84- MCIClient (schema_file_path = file_path , env_vars = env_vars or {} , validating = True )
137+ MCIClient (schema_file_path = file_path , env_vars = merged_env , validating = True )
85138 return (True , "" )
86139 except MCIClientError as e :
87140 return (False , str (e ))
0 commit comments