# CLAUDE.md This file provides guidance to Claude Code when working with the mckicad codebase. ## Development Commands - `make install` - Install dependencies with uv (creates .venv) - `make run` - Start the MCP server (`uv run python main.py`) - `make test` - Run all tests (`uv run pytest tests/ -v`) - `make test ` - Run a specific test file - `make lint` - Lint with ruff + mypy (`src/mckicad/` and `tests/`) - `make format` - Auto-format with ruff - `make build` - Build package - `make clean` - Remove build artifacts and caches Python 3.10+ required. Uses `uv` for everything. Configure via `.env` (copy `.env.example`). ## Architecture mckicad is a FastMCP 3 server for KiCad electronic design automation. It uses src-layout packaging with `hatchling` as the build backend. ### Project Structure ``` src/mckicad/ __init__.py # __version__ only server.py # FastMCP 3 server + lifespan + module imports config.py # Lazy config functions (no module-level env reads) tools/ schematic.py # kicad-sch-api: create/edit schematics (9 tools) project.py # Project discovery and structure (3 tools) drc.py # DRC checking + manufacturing constraints (4 tools) bom.py # BOM generation and export (2 tools) export.py # Gerber, drill, PDF, SVG via kicad-cli (4 tools) routing.py # FreeRouting autorouter integration (3 tools) analysis.py # Board validation + real-time analysis (3 tools) pcb.py # IPC-based PCB manipulation via kipy (5 tools) resources/ projects.py # kicad://projects resource files.py # kicad://project/{path} resource prompts/ templates.py # debug_pcb, analyze_bom, design_circuit, debug_schematic utils/ kicad_cli.py # KiCad CLI detection and execution path_validator.py # Path security / directory traversal prevention secure_subprocess.py # Safe subprocess execution with timeouts ipc_client.py # kipy IPC wrapper for live KiCad connection freerouting.py # FreeRouting JAR engine file_utils.py # Project file discovery kicad_utils.py # KiCad path detection, project search tests/ conftest.py # Shared fixtures (tmp dirs, project paths) test_*.py # Per-module test files main.py # Entry point: .env loader + server start ``` ### Key Design Decisions **Lazy config** (`config.py`): All environment-dependent values are accessed via functions (`get_search_paths()`, `get_kicad_user_dir()`) called at runtime, not at import time. Static constants (`KICAD_EXTENSIONS`, `TIMEOUT_CONSTANTS`, `COMMON_LIBRARIES`) remain as module-level dicts since they don't read env vars. This eliminates the .env load-order race condition. **Decorator-based tool registration**: Each tool module imports `mcp` from `server.py` and decorates functions with `@mcp.tool()` at module level. `server.py` imports the modules to trigger registration. No `register_*_tools()` boilerplate. **Schematic abstraction point**: `tools/schematic.py` uses `kicad-sch-api` for file-level schematic manipulation. The `_get_schematic_engine()` helper exists as a swap point for when kipy adds schematic IPC support. **Dual-mode operation**: PCB tools work via IPC (kipy, requires running KiCad) or CLI (kicad-cli, batch mode). Tools degrade gracefully when KiCad isn't running. ### Tool Registration Pattern ```python # tools/example.py from mckicad.server import mcp @mcp.tool() def my_tool(param: str) -> dict: """Tool description for the calling LLM.""" return {"success": True, "data": "..."} ``` ### Tool Return Convention All tools return dicts with at least `success: bool`. On failure, include `error: str`. On success, include relevant data fields. ## Adding New Features 1. Choose the right module (or create one in `tools/`) 2. Import `mcp` from `mckicad.server` 3. Decorate with `@mcp.tool()` and add a clear docstring 4. If new module: add import in `server.py` 5. Write tests in `tests/test_.py` ## Security - All file paths validated via `utils/path_validator.py` before access - External commands run through `utils/secure_subprocess.py` with timeouts - KiCad CLI commands sanitized — no shell injection - `main.py` inline .env loader runs before any mckicad imports ## Environment Variables - `KICAD_USER_DIR` - KiCad user config directory - `KICAD_SEARCH_PATHS` - Comma-separated project search paths - `KICAD_CLI_PATH` - Explicit kicad-cli path - `FREEROUTING_JAR_PATH` - Path to FreeRouting JAR - `LOG_LEVEL` - Logging level (default: INFO) ## Testing Markers: `unit`, `integration`, `requires_kicad`, `slow`, `performance` ```bash make test # all tests make test tests/test_schematic.py # one file uv run pytest -m "unit" # by marker ``` ## Entry Point ```toml [project.scripts] mckicad = "mckicad.server:main" ``` Run via `uvx mckicad`, `uv run mckicad`, or `uv run python main.py`. ## FreeRouting Setup 1. Download JAR from https://freerouting.app/ 2. Place at `~/freerouting.jar`, `/usr/local/bin/freerouting.jar`, or `/opt/freerouting/freerouting.jar` 3. Install Java runtime 4. Verify with `check_routing_capability()` tool 5. Or set `FREEROUTING_JAR_PATH` in `.env` ## Logging Logs go to `mckicad.log` in project root, overwritten each start. Never use `print()` — MCP uses stdin/stdout for JSON-RPC transport.