kicad-mcp/CLAUDE.md
Ryan Malloy 458583ee08
Some checks are pending
CI / Security Scan (push) Waiting to run
CI / Build Package (push) Blocked by required conditions
CI / Lint and Format (push) Waiting to run
CI / Test Python 3.11 on macos-latest (push) Waiting to run
CI / Test Python 3.12 on macos-latest (push) Waiting to run
CI / Test Python 3.13 on macos-latest (push) Waiting to run
CI / Test Python 3.10 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.11 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.12 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.13 on ubuntu-latest (push) Waiting to run
Add autowire documentation and update project structure
Autowire guide covers the decision tree, threshold tuning, workflow
patterns, and troubleshooting. CLAUDE.md updated to reflect the new
autowire/ package and tools/autowire.py.
2026-03-09 00:35:15 -06:00

5.6 KiB

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 <file> - 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)
  autowire/
    __init__.py         # Package init
    strategy.py         # Wiring decision tree: classify_net, crossing estimation
    planner.py          # NetPlan → apply_batch JSON conversion
  tools/
    autowire.py         # autowire_schematic MCP tool (1 tool)
    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

# 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_<module>.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

make test                          # all tests
make test tests/test_schematic.py  # one file
uv run pytest -m "unit"            # by marker

Entry Point

[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.