Files
kicad-mcp-server/CHANGELOG.md
NiNjA-CodE 76e644e4ef feat(routing): add add_gnd_stitching_vias MCP tool with all-layer collision (#191)
Drop GND stitching vias across the board with collision checking
against every non-GND segment, via, and pad on every copper layer.
PTH vias penetrate the full stackup, so an F.Cu-only check (the most
common shortcut) silently creates shorts on inner / B.Cu copper —
this implementation explicitly walks all layers.

  grid          Regular grid across the board interior. Default
                spacing 5mm.

  around_refs   Densify around specified footprints (e.g. MCUs,
                switching regulators, RF parts). Configurable
                density via densifyRadius.

  in_zones      Restrict placements to candidates inside the filled
                polygons of GND copper zones, so each new via lands
                on copper that's already a GND equipotential.
                Recommended on boards where the GND zone is fragmented:
                these vias actually stitch real polygons rather than
                floating on silkscreen.

All three strategies use the same collision check + intra-call
clump-prevention, so passing `["grid", "around_refs", "in_zones"]`
is a safe kitchen-sink configuration.

  - Auto-detect GND net (tries GND / GROUND / VSS / /GND in order)
    OR explicit `gndNet` parameter.
  - Per-via geometry control: viaSize, viaDrill, clearance.
  - edgeMargin: keep-out distance from board edge.
  - maxVias: cap on total placements (useful for incremental work).
  - dryRun: return placements without modifying the board — for
    previewing before committing.
  - Validates viaDrill < viaSize, rejects unknown strategy names,
    surfaces clear errors when GND net can't be resolved or the
    board outline is missing.

Approach ported from morningfire-pcb-automation
(https://github.com/NiNjA-CodE/morningfire-pcb-automation,
scripts/ground/add_gnd_vias.py). The original parses the PCB text
with regex and writes vias by string concatenation; this port reads
obstacles via the pcbnew API (handles rotated footprints, integrates
with the live in-memory board so two sequential calls see each
other's placements, picks up net codes from the loaded board) and
adds the in_zones strategy, the maxVias cap, and dry-run mode.

Credit is in the docstring, the TypeScript wrapper comment, the MCP
tool description (visible to clients), and the CHANGELOG entry.

tests/test_add_gnd_stitching_vias.py — 18 cases, all passing.
Uses mocked pcbnew objects so the suite runs under both the conftest
stub and a real pcbnew install.

  - grid strategy fills empty board with correct count
  - collision blocks via near a signal track (with extent assertion)
  - GND-net obstacles are correctly ignored
  - around_refs densifies near footprints with bounded extent
  - in_zones rejects candidates outside HitTestFilledArea
  - dryRun does NOT call board.Add
  - actual run calls board.Add per placement
  - maxVias caps total placements
  - intra-call clump prevention (asserts pairwise distance)
  - viaDrill >= viaSize is rejected
  - unknown strategy name is rejected
  - missing GND net returns clear error payload
  - no board loaded returns clear error
  - named GND net (e.g. VSS) is honoured even when GND also exists
  - direct unit tests for _point_to_segment_distance_nm helper

Real-board smoke test on TuneForge_TF001 (4-layer, 44 footprints):
  - GND net auto-detected
  - grid spacing 4mm: 141 placements, 129 blocked by collision
  - grid + in_zones: 140 placed, 15 rejected by zone membership,
    115 blocked by collision

  python/commands/routing.py         (+impl, ~370 LOC)
  python/kicad_interface.py          (+handler registration)
  python/schemas/tool_schemas.py     (+MCP schema)
  src/tools/routing.ts               (+TypeScript surface, builds clean)
  tests/test_add_gnd_stitching_vias.py (+18 tests)
  CHANGELOG.md                       (+Unreleased -> New MCP Tools)
2026-05-19 21:17:25 -04:00

36 KiB
Raw Blame History

Changelog

All notable changes to the KiCAD MCP Server project are documented here.

[Unreleased]

Bug Fixes

  • rotate_component now treats angle as an absolute target rotation, matching its schema description. Previously the IPC backend added the supplied angle to the current rotation, so two consecutive rotate_component(angle=90) calls would rotate the part to 180° instead of leaving it at 90°. Workflows that relied on the additive behavior will need to be updated.

  • Project-scope sym-lib-table is now visible to symbol-discovery tools: search_symbols, list_symbol_libraries, list_library_symbols, and get_symbol_info previously only consulted the global sym-lib-table. A library registered with project scope (i.e. an entry in <project>/sym-lib-table) was therefore invisible — even right after open_project succeeded — making add_schematic_component the only tool that could see it. Two changes:

    1. open_project and create_project now rebuild the SymbolLibraryManager against the project directory so subsequent search/list/info calls see project-scope libraries automatically.
    2. The four discovery tools also accept an optional projectPath parameter (a project directory, .kicad_pro, .kicad_pcb, or .kicad_sch path) for stateless callers, so project libraries can be resolved without first calling open_project.
  • Schematic symbol lookup: get_schematic_component, edit_schematic_component, set_schematic_component_property, remove_schematic_component_property, and delete_schematic_component no longer fail with Component '<ref>' not found in schematic when the placed symbol uses KiCad's rescued / locally-customised serialisation form (symbol (lib_name "...") (lib_id "...") ...). The block-matching regex now accepts any opening paren after (symbol, and the parent-position lookup uses the first (at ...) inside the symbol block, so newly-added properties anchor to the symbol origin instead of silently falling back to (0, 0). Added 7 regression tests reproducing the failure on a real-world user schematic.

New MCP Tools

  • add_gnd_stitching_vias — Drop GND stitching vias across the board with collision checking against every non-GND segment, via, and pad on every copper layer. PTH vias penetrate the full stackup, so an F.Cu-only check (the most common shortcut) silently creates shorts on inner / B.Cu copper — this implementation explicitly walks all layers.

    Combines three placement strategies, freely composable:

    • grid — regular grid across the board interior.
    • around_refs — densify around named footprints (good for tucking extra ground under MCUs, switching regulators, or RF parts).
    • in_zones — restrict candidates to points inside the filled polygons of GND copper zones, so each new via actually stitches real ground polygons together rather than floating on silkscreen.

    Also supports per-via geometry control (viaSize, viaDrill, clearance, edgeMargin), an maxVias cap for incremental work, auto-detection of the GND net (tries GND / GROUND / VSS / /GND), and a dryRun mode that returns the placements that would be made without modifying the board — useful for previewing before committing.

    Returns { placed: [{x, y, unit}, ...], summary: {placed_count, candidates_evaluated, skipped_by_zone_membership, skipped_by_collision, ...} }.

    Approach ported from morningfire-pcb-automation (scripts/ground/add_gnd_vias.py). The original parses the PCB text with regex and writes new vias by string concatenation; this port reads obstacles via the pcbnew API so it handles rotated footprints correctly, integrates with the in-memory board (two sequential calls see each other's placements), picks up net codes from the live board, and adds the in_zones strategy + the maxVias cap + dry-run.

  • check_courtyard_overlaps — Detect courtyard overlaps between footprints and (optionally) flag courtyards that extend past the board outline. Returns overlap pairs with intersection extents (mm), per-component boundary violations, and a placement summary. Accepts a positions dict of hypothetical placements (with optional rotation) so an AI agent can validate a proposed move_component / place_component before committing it — closing the feedback loop that previously required writing the move, running DRC, parsing violations, and reverting.

    Approach ported from morningfire-pcb-automation (scripts/placement/check_overlaps.py). The original uses a static per-footprint-type courtyard lookup table; this implementation reads the real courtyard polygons (or pad bounding box fallback) from the loaded board for accuracy on custom and rotated footprints, and adds virtual placement + clearance margin support.

  • query_zones — Query copper zones (filled pours) on the board with optional filters by net, layer, or bounding box. Returns one entry per zone with its net, layers, priority, fill state, min thickness, bounding box, and filled area. Complements query_traces, which only reports tracks/vias and silently omits power-plane and GND pours — making layer-usage audits incomplete on any board that uses copper zones.

  • set_schematic_component_property — Add or update a single custom property (BOM / sourcing field) on a placed schematic symbol. Convenience wrapper around edit_schematic_component for the common case of attaching one MPN / Manufacturer / DigiKey_PN / LCSC / JLCPCB_PN / Voltage / Tolerance / Dielectric value at a time. Newly created properties default to hidden so they do not clutter the schematic canvas.

  • remove_schematic_component_property — Delete a custom property from a placed schematic symbol. The four built-in fields (Reference, Value, Footprint, Datasheet) are protected and cannot be removed; clear them by setting their value to "" via edit_schematic_component instead.

Tool Enhancements

  • autoroute: best-of-N support. New optional parameters attempts, targetNets, and passSchedule. When attempts > 1, Freerouting is invoked multiple times with varied --max-passes values, each result is scored by (nets_routed * 1000) + segments plus a 50,000-point bonus when every targetNets entry is routed, and the winning SES is imported into the board. Single-attempt behaviour is unchanged when attempts is omitted, so existing callers don't need updates.

    Motivation: on dense boards a single Freerouting run routinely leaves 17 nets unrouted. Cycling through a few -mp values typically drives the unrouted count to zero. Empirically, 3 attempts is usually enough for 4-layer designs; 58 for stubborn cases.

    The scoring approach and the default passSchedule are ported from morningfire-pcb-automation (scripts/routing/freeroute_runner.py). The MCP version adds: cleaner per-attempt result reporting, automatic single-thread optimisation (-mt 1) during scored attempts so the multi-threaded optimiser's known clearance-violation bug doesn't distort the comparison, and graceful degradation when one attempt errors out (the run continues and the best of the remainder wins).

  • edit_schematic_component: extended with two new optional parameters that promote arbitrary custom properties to first-class citizens:

    • properties — map of property name to either a string value or a full spec object { value, x?, y?, angle?, hide?, fontSize? }. Adds the property if it does not yet exist on the symbol, otherwise updates the existing value (and optionally its label position / visibility). Lets a single tool call attach an entire BOM / sourcing payload to a component: properties: { MPN: "RC0603FR-0710KL", Manufacturer: "Yageo", Tolerance: "1%" }.
    • removeProperties — list of custom property names to delete in the same call.
    • String values written through any of the property paths are now properly backslash-escaped so descriptions containing " or \ no longer corrupt the .kicad_sch file.
  • get_schematic_component: clarified description — it already returns every field on the symbol (built-in + custom). The tool description now spells this out explicitly so agents know they can use it to inspect MPN, Manufacturer, Distributor PN and other BOM fields without a separate call.

New MCP Prompt

  • component_sourcing_properties — Guides the LLM through attaching BOM and sourcing metadata (MPN, Manufacturer, distributor part numbers, parametric fields like Voltage / Tolerance / Dielectric) to schematic components. Lists the conventional property names recognised by downstream BOM tooling and the recommended call sequence (list_schematic_componentsget_schematic_componentset_schematic_component_property / edit_schematic_component).

Tests

  • tests/test_schematic_component_properties.py: 32 new tests covering custom property add / update / remove (single + batched), full spec dicts, position defaults, (hide yes) defaulting, protected built-in field rejection, no-op removal, special-character escaping, UUID preservation, and the two new convenience tools.

Removed

  • add_schematic_junction MCP tool has been removed. Junctions are now inserted and removed automatically via WireManager.sync_junctions whenever wires are added, deleted, or moved.
  • Junction placement is pin-aware: sync_junctions consults component pin positions so that T-junctions at component pins are correctly recognised.

[2.2.3] - 2026-03-11

Merged: PR #57 (Kletternaut/demo/rpiCSI-videotest → main)

This release incorporates 28 commits developed and live-tested during a full Raspberry Pi CSI adapter PCB design session. All tools listed below were validated end-to-end using Claude Desktop + KiCAD 9 on Windows.

New MCP Tools

  • connect_passthrough — Schematic-only tool that wires all pins of one connector directly to the matching pins of another (e.g. J1 pin N → J2 pin N). Creates nets named with a configurable prefix (netPrefix). Designed for FFC/ribbon cable passthrough adapters. Schematic only — do not call for PCB routing.

  • sync_schematic_to_board — Imports all net/pad assignments from the schematic into the open PCB file. Required after connect_passthrough before routing can start. Returns pads_assigned count for verification.

  • snapshot_project — Saves a named checkpoint of the entire project folder into a snapshots/ subdirectory inside the project. Allows resuming from a known-good state without redoing earlier steps. Accepts step, label, and optional prompt parameters.

  • run_erc — Runs KiCAD's Electrical Rules Check on the schematic and returns violations as structured JSON.

  • import_svg_logo — Converts an SVG file to PCB silkscreen polygons and places them on a specified layer.

Bug Fixes

  • route_pad_to_pad: Critical fix for B.Cu footprints in KiCAD 9. pad.GetLayerName() always returned F.Cu for SMD pads on flipped footprints (KiCAD 9 SWIG bug). Fix: use footprint.GetLayer() instead, which correctly reflects the placed layer after Flip(). Without this fix, no vias were inserted for back-to-back connectors.

  • route_pad_to_pad: Via was placed at the geometric midpoint between the two pads. For back-to-back mirrored connectors (J1 F.Cu / J2 B.Cu) this caused all 15 vias to stack at the same X coordinate (board center). Fix: via is now placed at the X coordinate of the start pad (via_x = start_pos.x), producing 15 parallel vertical traces.

  • place_component (B.Cu footprints): Flip() was called before board.Add(), causing KiCAD 9 to hang for ~30 seconds. Fix: board.Add() first, then Flip().

  • add_board_outline: Three separate bugs fixed — incorrect cornerRadius fallback, wrong top-left origin default, and broken arc delegation for IPC rounded rectangles.

  • snapshot_project: Snapshots were saved one level above the project directory, cluttering the parent folder. Fix: snapshots now go into <project>/snapshots/.

  • MCP server log timestamp was always UTC/ISO. Fix: now uses local system time.

  • search_tools (router pattern): direct tools like snapshot_project were invisible to the router. Fix: direct tool names added to the router's known-tool list.

Developer Mode (KICAD_MCP_DEV=1)

Set the environment variable KICAD_MCP_DEV=1 in your Claude Desktop config to enable developer features:

"env": {
  "KICAD_MCP_DEV": "1"
}

What it does:

  • export_gerber automatically copies the current MCP session log into the project's logs/ subdirectory as mcp_log_<timestamp>.txt.
  • snapshot_project copies the MCP session log into logs/ at every checkpoint as mcp_log_step<N>_<timestamp>.txt.
  • If a prompt parameter is passed to snapshot_project, it is saved as PROMPT_step<N>_<timestamp>.md alongside the log.

Purpose: Makes it easy to include the full tool call history when filing a bug report or GitHub issue — just attach the log file from the project's logs/ folder.

⚠️ Privacy warning: The MCP session log contains the complete conversation history between Claude and the MCP server, including all tool parameters and responses. When sharing a project directory (e.g. as a ZIP attachment in a GitHub issue), review or delete the logs/ folder first to avoid accidentally disclosing sensitive file paths, component names, or design details.

Snapshot Logging (always active)

Regardless of dev mode, snapshot_project now always saves a copy of the current MCP session log into <project>/logs/ at each checkpoint. This means every project automatically retains a traceable record of which tools were called and in what order.

⚠️ Same privacy note applies: the logs/ directory inside your project folder contains tool call history. Do not share it publicly without reviewing its contents.


[2.2.2-alpha] - 2026-03-01

New MCP Tools

  • route_pad_to_pad Convenience wrapper around route_trace that looks up pad positions automatically. Accepts fromRef/fromPad/toRef/toPad instead of raw XY coordinates. Auto-detects net from pad assignment (overridable via net param). Saves ~2 tool calls per connection (~64 calls for a full TMC2209 board compared to the 3-step get_pad_position flow). Live tested: ESP32 ↔ TMC2209 STEP/DIR traces routed without prior coordinate lookup.

  • copy_routing_pattern Now registered as MCP tool in TypeScript layer (routing.ts). Was previously implemented in Python but missing from the MCP tool registry. Parameters: sourceRefs, targetRefs, includeVias?, traceWidth?.

Bug Fixes

  • add_schematic_component / DynamicSymbolLoader: ignored project-local sym-lib-table. find_library_file() only searched global KiCAD install directories, causing "library not found" errors for any symbol in a project-local .kicad_sym file. Fix: added project_path parameter; reads project sym-lib-table first via new _resolve_library_from_table() helper before falling back to global dirs. project_path is auto-derived from the schematic path.

  • place_component: ignored project-local fp-lib-table. FootprintLibraryManager was initialised once at server start without a project path, so self-created .kicad_mod footprints were never found. Fix: new boardPath parameter in TypeScript + Python; _handle_place_component wrapper recreates FootprintLibraryManager(project_path=…) whenever the active project changes (cached to avoid redundant recreation).

  • copy_routing_pattern: copied 0 traces when pads had no net assignments. The filter track.GetNetname() in source_nets always returned empty when pads were placed without net assignment. Fix: geometric fallback using bounding box of source footprint pads ±5mm tolerance. Response includes filterMethod field indicating which mode was used ("net-based" or "geometric (pads have no nets)").

  • template_with_symbols.kicad_sch, template_with_symbols_expanded.kicad_sch: restored format version 20250114 (KiCAD 9) after upstream commit 2b38796 accidentally downgraded both files to 20240101. KiCAD 9 rejects schematics with outdated version numbers.

  • CRITICAL: template_with_symbols_expanded.kicad_sch: removed 7 invalid ;; comment lines introduced by upstream commit b98c94b. KiCAD's S-expression parser does not support any comment syntax — it expects every non-empty, non-whitespace line to start with (. The comments (;; PASSIVES, ;; SEMICONDUCTORS, ;; INTEGRATED CIRCUITS, ;; CONNECTORS, ;; POWER/REGULATORS, ;; MISC, ;; TEMPLATE INSTANCES (...)) caused KiCAD 9 to reject every schematic created from this template with a hard parse error:

    Expecting '(' in <file>.kicad_sch, line 8, offset 5 Action required for existing projects: delete every line beginning with ;; from any .kicad_sch file created between upstream commit b98c94b and this fix.

  • add_schematic_component / inject_symbol_into_schematic: symbol definition in lib_symbols was never refreshed after editing via create_symbol / edit_symbol. If the symbol was already present in the schematic's embedded lib_symbols section, the function returned immediately — delete + re-add still pulled in the stale cached definition. Fix: always read the current definition from the .kicad_sym file; if a stale entry exists in lib_symbols, remove it first, then inject the fresh one. Verified live.

  • template_with_symbols_expanded.kicad_sch: removed 13 legacy _TEMPLATE_* offscreen instances (_TEMPLATE_R, _TEMPLATE_C, _TEMPLATE_U, etc.) that were placed at x=-100 as clone-sources for the old ComponentManager approach. DynamicSymbolLoader (the current implementation) injects symbols directly and never needs these placeholders. They appeared as dangling reference designators in KiCAD's component navigator and in the schematic canvas when zoomed far out.

Maintenance

  • .gitignore: added *.kicad_pcb.bak, *.kicad_pro.bak alongside existing -bak variants; consolidated personal/local files under myContribution/.

[2.2.1-alpha] - 2026-02-28

New MCP Tools

  • edit_schematic_component Update properties of a placed symbol in-place (footprint, value, reference rename). More efficient than delete + re-add: preserves position and UUID.

Bug Fixes

  • add_schematic_component: footprint parameter was accepted but silently ignored the value was never passed through to DynamicSymbolLoader.add_component() / create_component_instance(). All newly placed symbols always had an empty Footprint field. Fix: added footprint: str = "" to both functions and threaded it through every call site including the TypeScript tool schema.

  • delete_schematic_component: only deleted the first matching instance when duplicate references existed (e.g. after an aborted add attempt). Root cause: loop used break after the first match. Fix: collect all matching blocks first, then delete them all back- to-front (to preserve line indices). Response now includes deleted_count.

  • templates/*.kicad_sch, project.py, schematic.py: Update KiCAD schematic format version from 20230121 (KiCAD 7) to 20250114 (KiCAD 9). The MCP server targets KiCAD 9 exclusively (pcbnew.pyd compiled for KiCAD 9.0, Python 3.11.5) generating files in an outdated format caused a spurious "This file was created with an older KiCAD version" warning on every newly created schematic.

  • template_with_symbols_expanded.kicad_sch: Remove 13 corrupt _TEMPLATE_* placed-symbol blocks with (lib_id -100) an integer caused by old sexpdata serializer (same bug PR #40 fixed for the add path). KiCAD crashed with a null-pointer when selecting these symbols. They appeared as grey _TEMPLATE_R?, _TEMPLATE_U_REG? etc. labels far outside the sheet boundary (~5000mm off-sheet).

    Discovered via: live testing on a real JLCPCB/KiCAD 9 project. Affected users: schematics created from this template before this fix contain the same corrupt blocks remove all (symbol (lib_id -100) ...) blocks whose Reference starts with _TEMPLATE_.



[2.2.0-alpha] - 2026-02-27

New MCP Tools (TypeScript layer previously Python-only)

Routing tools:

  • delete_trace - Delete traces by UUID, position or net name
  • query_traces - Query/filter traces on the board
  • get_nets_list - List all nets with net code and class
  • modify_trace - Modify trace width or layer
  • create_netclass - Create or update a net class
  • route_differential_pair - Route a differential pair between two points
  • refill_zones - Refill all copper zones ⚠️ SWIG segfault risk, prefer IPC/UI

Component tools:

  • get_component_pads - Get all pad data for a component
  • get_component_list - List all components on the board
  • get_pad_position - Get absolute position of a specific pad
  • place_component_array - Place components in a grid array
  • align_components - Align components along an axis
  • duplicate_component - Duplicate a component with offset

Bug Fixes

  • routing.py: Fix SwigPyObject UUID comparison (str()m_Uuid.AsString())
  • routing.py: Fix SWIG iterator invalidation after board.Remove() by snapshotting list(board.Tracks())
  • routing.py: Add board.SetModified() + track = None after Remove() to prevent dangling SWIG pointer crashes
  • routing.py: Per-track try/except in query_traces() to skip invalid objects after bulk delete
  • routing.py: Add missing return statement (mypy)
  • library.py: Fix search_footprints parameter mapping (search_termpattern)
  • library.py: Fix field access (fp.namefp.full_name)
  • library.py: Accept both pattern and search_term parameter names
  • library.py: Fix loop variable shadowing Path object (mypy)
  • design_rules.py: Add type annotation for violation_counts (mypy)

New MCP Tools (cont.)

Datasheet tools:

  • get_datasheet_url - Return LCSC datasheet PDF URL and product page URL for a given LCSC number (e.g. C179739https://www.lcsc.com/datasheet/C179739.pdf). No API key required URL is constructed directly from the LCSC number.
  • enrich_datasheets - Scan a .kicad_sch file and write LCSC datasheet URLs into every symbol that has an LCSC property but an empty Datasheet field. After enrichment the URL appears natively in KiCAD's symbol properties, footprint browser and any other tool that reads the standard KiCAD Datasheet field. Supports dry_run=true for preview without writing. Implementation: python/commands/datasheet_manager.py (text-based, no skip writes)

Schematic tools:

  • delete_schematic_component - Remove a placed symbol from a .kicad_sch file by reference designator (e.g. R1, U3).

Bug Fixes (cont.)

  • schematic.ts / kicad_interface.py: Fix missing delete_schematic_component MCP tool.

    Root cause (two separate issues):

    1. No MCP tool named delete_schematic_component existed. Claude had no way to call it, so any "delete schematic component" request fell through to the PCB-only delete_component tool, which searches pcbnew.BOARD and always returned "Component not found" for schematic symbols.
    2. component_schematic.py::remove_component() still used skip for writes. PR #40 rewrote DynamicSymbolLoader (add path) to avoid skip-induced schematic corruption, but remove_component (delete path) was not touched by that PR.

    Fix:

    • Added delete_schematic_component to the TypeScript tool layer (schematic.ts) with clear docstring distinguishing it from the PCB delete_component.
    • Implemented _handle_delete_schematic_component in kicad_interface.py using direct text manipulation (parenthesis-depth tracking, same approach as PR #40). Does not call component_schematic.py::remove_component() at all.
    • Error message explicitly guides the user when the wrong tool is used: "note: this tool removes schematic symbols, use delete_component for PCB footprints"

Additional Bug Fixes

  • connection_schematic.py / kicad_interface.py: Fix generate_netlist missing schematic_path parameter without it get_net_connections always fell back to proximity matching which only returns one connection per component (first wire hit, then break). PinLocator was never invoked. Fix: added schematic_path: Optional[Path] to generate_netlist signature and threaded it through to get_net_connections, and updated _handle_generate_netlist in kicad_interface.py to pass schematic_path.
  • server.ts: Fix KiCAD bundled Python (3.11.5) not being selected on Windows the detection condition process.env.PYTHONPATH?.includes("KiCad") was fragile and failed in some environments, causing System Python 3.12 to be used instead. Since pcbnew.pyd is compiled for KiCAD's Python 3.11.5, this resulted in No module named 'pcbnew'. Fix: removed the condition, KiCAD bundled Python is now always preferred on Windows when it exists at C:\Program Files\KiCad\9.0\bin\python.exe. Also added KICAD_PYTHON to claude_desktop_config.json as explicit override.
  • pin_locator.py: Fix generate_netlist timeout get_pin_location and get_all_symbol_pins called Schematic(schematic_path) on every single pin lookup, causing O(nets × components × pins) schematic file loads (e.g. 400+ loads for a medium schematic). Fix: added _schematic_cache dict to PinLocator.__init__, schematic is now loaded once per path and reused.

[2.1.0-alpha] - 2026-01-10

Phase 1: Intelligent Schematic Wiring System - Core Infrastructure

Major Features:

  • Automatic pin location discovery with rotation support
  • Smart wire routing (direct, orthogonal horizontal/vertical)
  • Net label management (local, global, hierarchical)
  • S-expression-based wire creation
  • Professional right-angle routing

New Components:

  • python/commands/wire_manager.py - S-expression wire creation engine
  • python/commands/pin_locator.py - Intelligent pin discovery with rotation
  • Updated python/commands/connection_schematic.py - High-level connection API
  • docs/SCHEMATIC_WIRING_PLAN.md - Implementation roadmap

MCP Tools Enhanced:

  • add_schematic_wire - Create wires with stroke customization
  • add_schematic_connection - Auto-connect pins with routing options (NEW)
  • add_schematic_net_label - Add labels with type and orientation control (NEW)
  • connect_to_net - Connect pins to named nets (ENHANCED)

Technical Implementation:

  • Rotation transformation matrix for pin coordinates
  • S-expression injection for guaranteed format compliance
  • Pin definition caching for performance
  • Orthogonal path generation for professional schematics

Testing:

  • End-to-end integration test: 100% passing
  • MCP handler integration test: 100% passing
  • Pin discovery with rotation: Verified working
  • KiCad-skip verification: All wires/labels correctly formed

Phase 2: Power Nets & Wire Connectivity - COMPLETE

Major Features:

  • Power symbol support (VCC, GND, +3V3, +5V, etc.) via dynamic loading
  • Wire graph analysis for net connectivity tracking
  • Geometric wire tracing with tolerance-based point matching
  • Accurate netlist generation with component/pin connections
  • Critical template mapping bug fixes

Updates:

  • connect_to_net() - Migrated to WireManager + PinLocator
  • get_net_connections() - Complete rewrite with geometric wire tracing
  • generate_netlist() - Now uses wire graph analysis for connectivity
  • get_or_create_template() - Fixed special character handling, auto-reload after dynamic loading
  • add_component() - Fixed template lookup with symbol iteration

Bug Fixes:

  • CRITICAL: Template mapping after dynamic symbol loading
  • Special character handling in symbol names (+ prefix in +3V3, +5V)
  • Schematic reload synchronization after S-expression injection
  • Multi-format template reference detection

Wire Graph Analysis Algorithm:

  1. Find all labels matching target net name
  2. Trace wires connected to label positions (point coincidence)
  3. Collect all wire endpoints and polyline segments
  4. Match component pins at wire connection points using PinLocator
  5. Return accurate component/pin connection pairs

Technical Implementation:

  • Tolerance-based point matching (0.5mm for grid alignment)
  • Multi-segment wire (polyline) support
  • Rotation-aware pin location matching via PinLocator
  • Fallback proximity detection (10mm threshold)
  • Template existence checking via symbol iteration (handles special characters)

Testing:

  • Power symbols: 4/4 loaded (VCC, GND, +3V3, +5V)
  • Components: 4/4 placed
  • Connections: 8/8 created successfully
  • Net connectivity: 100% accurate (VCC: 2, GND: 4, +3V3: 1, +5V: 1)
  • Netlist generation: 4 nets with accurate connections
  • Comprehensive integration test: 100% PASSING

Commits:

  • c67f400 - Updated connect_to_net to use WireManager
  • b77f008 - Fixed template mapping bug (critical)
  • a5a542b - Implemented wire graph analysis

Addresses:

  • Issue #26 - Schematic workflow wiring functionality (Phase 2)

Phase 2: JLCPCB Integration Complete

Major Features:

  • Complete JLCPCB parts integration via JLCSearch public API
  • Access to ~100k JLCPCB parts catalog
  • Real-time stock and pricing data
  • Parametric component search
  • Cost optimization (Basic vs Extended library)
  • KiCad footprint mapping
  • Alternative part suggestions

New Components:

  • python/commands/jlcsearch.py - JLCSearch API client (no auth required)
  • python/commands/jlcpcb_parts.py - Enhanced with import_jlcsearch_parts()
  • docs/JLCPCB_INTEGRATION.md - Comprehensive integration guide

MCP Tools Available:

  • download_jlcpcb_database - Download full parts catalog
  • search_jlcpcb_parts - Parametric search with filters
  • get_jlcpcb_part - Part details + footprint suggestions
  • get_jlcpcb_database_stats - Database statistics
  • suggest_jlcpcb_alternatives - Find similar/cheaper parts

Technical Improvements:

  • SQLite database with full-text search (FTS5)
  • Package-to-footprint mapping for standard SMD packages
  • Price comparison and cost optimization algorithms
  • HMAC-SHA256 authentication support (for official JLCPCB API)

Testing:

  • All integration tests passing
  • Database operations validated
  • Live API connectivity confirmed
  • End-to-end MCP tool testing complete

Documentation:

  • Complete API reference with examples
  • Package mapping tables (0402, 0603, 0805, SOT-23, etc.)
  • Best practices guide
  • Troubleshooting section

[2.1.0-alpha] - 2025-11-30

Phase 1: Schematic Workflow Fix

Critical Bug Fix:

  • Fixed completely broken schematic workflow (Issue #26)
  • Created template-based symbol cloning approach
  • All schematic tests now passing

Root Cause:

  • kicad-skip library limitation: cannot create symbols from scratch, only clone existing ones

Solution:

  • Template schematic with cloneable R, C, LED symbols
  • Updated create_project to create both PCB and schematic
  • Rewrote add_schematic_component to use clone() API
  • Proper UUID generation and position setting

Files Modified:

  • python/commands/project.py - Now creates schematic files
  • python/commands/schematic.py - Uses template approach
  • python/commands/component_schematic.py - Complete rewrite

Files Created:

  • python/templates/template_with_symbols.kicad_sch
  • python/templates/empty.kicad_sch
  • docs/SCHEMATIC_WORKFLOW_FIX.md

Testing:

  • Created comprehensive test suite
  • All 7 tests passing
  • KiCad CLI validation successful

[2.0.0-alpha] - 2025-11-05

Router Pattern & Tool Organization

Major Architecture Change:

  • Implemented tool router pattern (70% context reduction)
  • 12 direct tools, 47 routed tools in 7 categories
  • Smart tool discovery system

New Router Tools:

  • list_tool_categories - Browse available categories
  • get_category_tools - View tools in category
  • search_tools - Find tools by keyword
  • execute_tool - Run any routed tool

Benefits:

  • Dramatically reduced AI context usage
  • Maintained full functionality (64 tools)
  • Improved tool discoverability
  • Better organization for users

[2.0.0-alpha] - 2025-11-01

IPC Backend Integration

Experimental Feature:

  • KiCad 9.0 IPC API integration for real-time UI sync
  • Changes appear immediately in KiCad (no manual reload)
  • Hybrid backend: IPC + SWIG fallback
  • 20+ commands with IPC support

Implementation:

  • Routing operations (interactive push-and-shove)
  • Component placement and modification
  • Zone operations and fills
  • DRC and verification

Status:

  • Under active development
  • Enable via KiCad: Preferences > Plugins > Enable IPC API Server
  • Automatic fallback to SWIG when IPC unavailable

[2.0.0-alpha] - 2025-10-26

Initial JLCPCB Integration (Local Libraries)

Features:

  • Local JLCPCB symbol library search
  • Integration with KiCad Plugin and Content Manager
  • Search by LCSC part number, manufacturer, description

Credit:

Components:

  • python/commands/symbol_library.py
  • Basic library search functionality

[1.0.0] - 2025-10-01

Initial Release

Core Features:

  • 64 fully-documented MCP tools
  • JSON Schema validation for all tools
  • 8 dynamic resources for project state
  • Cross-platform support (Linux, Windows, macOS)
  • Comprehensive error handling
  • Detailed logging

Tool Categories:

  • Project Management (4 tools)
  • Board Operations (9 tools)
  • Component Management (8 tools)
  • Routing (6 tools)
  • Export & Manufacturing (5 tools)
  • Design Rule Checking (4 tools)
  • Schematic Operations (6 tools)
  • Symbol Library (3 tools)
  • JLCPCB Integration (5 tools)

Platform Support:

  • Linux (KiCad 7.x, 8.x, 9.x)
  • Windows (KiCad 9.x)
  • macOS (KiCad 9.x)

Documentation:

  • Complete README with setup instructions
  • Platform-specific guides
  • Tool reference documentation
  • Contributing guidelines

Version Numbering

  • 2.1.0-alpha: Current development version with JLCPCB integration
  • 2.0.0-alpha: Router pattern and IPC backend
  • 1.0.0: Initial stable release

Breaking Changes

2.1.0-alpha

  • None (additive changes only)

2.0.0-alpha

  • Tool execution now requires router for 47 tools
  • Direct tool access limited to 12 high-frequency tools
  • Schema validation stricter (catches errors earlier)

Deprecations

2.1.0-alpha

  • docs/JLCPCB_USAGE_GUIDE.md - Superseded by docs/JLCPCB_INTEGRATION.md
  • docs/JLCPCB_INTEGRATION_PLAN.md - Implementation complete

Migration Guide

Upgrading to 2.1.0-alpha from 2.0.0-alpha

New Dependencies:

  • No new system dependencies
  • Python packages: requests (already in requirements.txt)

Database Setup:

  1. Run download_jlcpcb_database tool (one-time, ~5-10 minutes)
  2. Database created at data/jlcpcb_parts.db
  3. Subsequent searches use local database (instant)

API Changes:

  • All existing tools remain compatible
  • 5 new JLCPCB tools available
  • No breaking changes to existing functionality

Upgrading to 2.0.0-alpha from 1.0.0

Router Pattern:

  • Some tools now accessed via execute_tool instead of direct calls
  • Use list_tool_categories to discover available tools
  • Search with search_tools to find specific functionality

IPC Backend (Optional):

  • Enable in KiCad: Preferences > Plugins > Enable IPC API Server
  • Set KICAD_BACKEND=ipc environment variable
  • Falls back to SWIG if unavailable

Credits

  • JLCSearch API: @tscircuit
  • JLCParts Database: @yaqwsx
  • Local JLCPCB Search: @l3wi
  • KiCad: KiCad Development Team
  • MCP Protocol: Anthropic

License

See LICENSE file for details.