From 4ebf8f08e95b75584b1eca8bbee6356d23e8704b Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Tue, 3 Mar 2026 16:53:40 -0700 Subject: [PATCH] Fix .env loading order so KICAD_SEARCH_PATHS takes effect config.py evaluates os.environ at import time, but mckicad/__init__.py eagerly imports config via 'from .config import *'. The old main.py loaded .env after importing from mckicad, so the search paths were always empty. Now .env is parsed with stdlib before any mckicad imports. Also fix start.sh to use 'uv run' instead of stale venv/ path. --- main.py | 75 +++++++++++++++++++++++++------------------------------- start.sh | 3 ++- 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/main.py b/main.py index be799ce..83ca85d 100644 --- a/main.py +++ b/main.py @@ -4,60 +4,51 @@ KiCad MCP Server - A Model Context Protocol server for KiCad on macOS. This server allows Claude and other MCP clients to interact with KiCad projects. """ import os -import sys -import logging # Import logging module +import logging -# Must import config BEFORE env potentially overrides it via os.environ -from mckicad.config import KICAD_USER_DIR, ADDITIONAL_SEARCH_PATHS -from mckicad.server import main as server_main -from mckicad.utils.env import load_dotenv - -# --- Setup Logging --- -log_file = os.path.join(os.path.dirname(__file__), 'mckicad.log') +# --- Setup Logging --- +log_file = os.path.join(os.path.dirname(__file__), 'mckicad.log') logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - [PID:%(process)d] - %(message)s', handlers=[ - logging.FileHandler(log_file, mode='w'), # Use 'w' to overwrite log on each start - # logging.StreamHandler() # Optionally keep logging to console if needed + logging.FileHandler(log_file, mode='w'), ] ) # --------------------- -logging.info("--- Server Starting --- ") -logging.info(f"Initial KICAD_USER_DIR from config.py: {KICAD_USER_DIR}") -logging.info(f"Initial ADDITIONAL_SEARCH_PATHS from config.py: {ADDITIONAL_SEARCH_PATHS}") +logging.info("--- Server Starting ---") -# Get PID for logging (already used by basicConfig) -_PID = os.getpid() +# Load .env BEFORE any mckicad imports. Importing mckicad.utils.env would +# trigger mckicad/__init__.py which eagerly imports config.py, evaluating +# os.environ.get("KICAD_SEARCH_PATHS") before .env is loaded. So we +# inline the loading here using only stdlib. +_dotenv_path = os.path.join(os.path.dirname(__file__), '.env') +if os.path.exists(_dotenv_path): + logging.info(f"Loading .env from: {_dotenv_path}") + with open(_dotenv_path) as _f: + for _line in _f: + _line = _line.strip() + if not _line or _line.startswith("#"): + continue + if "=" in _line: + _key, _val = _line.split("=", 1) + _key, _val = _key.strip(), _val.strip() + if (_val.startswith('"') and _val.endswith('"')) or ( + _val.startswith("'") and _val.endswith("'") + ): + _val = _val[1:-1] + os.environ[_key] = _val + logging.info(f" {_key}={_val}") +else: + logging.info("No .env file found") -# Load environment variables from .env file if present -# This attempts to update os.environ -dotenv_path = os.path.join(os.path.dirname(__file__), '.env') -logging.info(f"Attempting to load .env file from: {dotenv_path}") -found_dotenv = load_dotenv() # Assuming this returns True/False or similar -logging.info(f".env file found and loaded: {found_dotenv}") +# Now safe to import mckicad — config.py will see the .env values +from mckicad.config import KICAD_USER_DIR, ADDITIONAL_SEARCH_PATHS +from mckicad.server import main as server_main -# Log effective values AFTER load_dotenv attempt -# Note: The config values might not automatically re-read from os.environ -# depending on how config.py is written. Let's check os.environ directly. -effective_user_dir = os.getenv('KICAD_USER_DIR') -effective_search_paths = os.getenv('KICAD_SEARCH_PATHS') -logging.info(f"os.environ['KICAD_USER_DIR'] after load_dotenv: {effective_user_dir}") -logging.info(f"os.environ['KICAD_SEARCH_PATHS'] after load_dotenv: {effective_search_paths}") - -# Re-log the values imported from config.py to see if they reflect os.environ changes -# (This depends on config.py using os.getenv internally AFTER load_dotenv runs) -try: - from mckicad import config - import importlib - importlib.reload(config) # Attempt to force re-reading config - logging.info(f"Effective KICAD_USER_DIR from config.py after reload: {config.KICAD_USER_DIR}") - logging.info(f"Effective ADDITIONAL_SEARCH_PATHS from config.py after reload: {config.ADDITIONAL_SEARCH_PATHS}") -except Exception as e: - logging.error(f"Could not reload config: {e}") - logging.info(f"Using potentially stale KICAD_USER_DIR from initial import: {KICAD_USER_DIR}") - logging.info(f"Using potentially stale ADDITIONAL_SEARCH_PATHS from initial import: {ADDITIONAL_SEARCH_PATHS}") +logging.info(f"KICAD_USER_DIR: {KICAD_USER_DIR}") +logging.info(f"ADDITIONAL_SEARCH_PATHS: {ADDITIONAL_SEARCH_PATHS}") if __name__ == "__main__": try: diff --git a/start.sh b/start.sh index 387769e..62ab212 100755 --- a/start.sh +++ b/start.sh @@ -1,2 +1,3 @@ #!/bin/bash -/home/rpm/claude/kicad-mcp/venv/bin/python /home/rpm/claude/kicad-mcp/main.py "$@" \ No newline at end of file +cd /home/rpm/claude/kicad-mcp +uv run python main.py "$@" \ No newline at end of file