The handler used a line-by-line regex requiring (symbol and (lib_id on
the same line, but KiCAD's file writer places them on separate lines.
Replace with the content-string approach (already used by edit handler)
so \s+ matches across newlines. Add regression tests covering inline,
multi-line, and power symbol (#PWR) cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New `get_schematic_component` MCP tool returns component position and
all field values with their label (at x/y/angle) positions
- Extends `edit_schematic_component` with optional `fieldPositions` dict
so callers can reposition Reference/Value/etc. labels in one call
- Adds 18 tests (6 unit, 12 integration) covering parsing, round-trips,
and edge cases
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
delete_schematic_net_label was using kicad-skip's write() which silently
discards in-memory _elements mutations. Replaced with WireManager.delete_label()
that uses the same sexpdata round-trip approach already used by delete_schematic_wire.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kicad-skip's write() serializes from original parsed data, silently
discarding in-memory _elements mutations. Switch to the same sexpdata
approach used by add_wire: parse, find matching wire, delete the entry,
write back. Also adds WireManager.delete_wire() static method.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ElementCollection in kicad-skip doesn't implement remove(), causing
'WireCollection object has no attribute remove' errors. Access the
underlying _elements list directly for wire, label, and symbol deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused imports in move_schematic_component
- Add warning log when mirror attribute missing on rotate
- Move `import re` out of loop in annotate_schematic
- Include global_label in list_schematic_nets
- Fix SVG export to use directory for kicad-cli --output flag
- Return actual SVG data in get_schematic_view TS handler
- Add isError: true to all failure responses in new tools
- Add connect_passthrough to schematic category in registry
- Simplify power symbol filtering control flow in list_labels
- Fix indentation in list_schematic_labels power section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exports schematic to SVG via kicad-cli, then converts to PNG using
cairosvg (same approach as get_board_2d_view). Falls back gracefully
to SVG if cairosvg is not installed. Supports configurable output
size and format (png/svg).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add all missing schematic operations identified in the gap analysis:
Inspection (P0/P2):
- list_schematic_components: enumerate all components with refs, values, pins
- list_schematic_nets: list all nets with their connections
- list_schematic_wires: list all wire geometry
- list_schematic_labels: list net labels, global labels, power flags
Editing (P0/P1):
- annotate_schematic: assign ref designators to unannotated components (R? → R1)
- move_schematic_component: reposition placed symbols
- rotate_schematic_component: rotate/mirror placed symbols
- delete_schematic_wire: remove wires by coordinates
- delete_schematic_net_label: remove labels by name/position
Export (P1):
- export_schematic_svg: schematic SVG export via kicad-cli
- export_schematic_pdf: enhanced with file path return & blackAndWhite support
Also registers list_schematic_components and annotate_schematic as
direct tools (always visible) since they're prerequisites for
reference-based workflows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detects F.Cu<->B.Cu layer mismatch in route_pad_to_pad
- Splits route into: trace on start layer + via at midpoint + trace on end layer
- route_trace description warns: use route_pad_to_pad for cross-layer routing
- route_pad_to_pad description highlights automatic via insertion
Bug 1 — Rounded corners missing (src/tools/board.ts schema)
Symptom: Claude sends shape='rectangle' + radius=2.5, but the Zod schema
only listed 'rectangle', 'circle', 'polygon' as valid shapes. The JS
handler never passed cornerRadius through the IPC path, and Python only
generated arcs for shape='rounded_rectangle'. Result: 4 straight lines,
no arcs.
Fix: Added 'rounded_rectangle' and 'cornerRadius' to the Zod schema in
src/tools/board.ts so Claude can send the correct shape directly.
Also added a Python-side auto-upgrade: if shape='rectangle' and
cornerRadius>0, silently promote to 'rounded_rectangle' so legacy
callers still work (python/commands/board/outline.py).
Bug 2 — Board outline placed at (-w/2, -h/2) instead of (0, 0)
Symptom: A 30x30 mm board outline was placed centred at the origin
(start -15 -15) ... (end 15 15) instead of the expected top-left at
(0,0) → (30,30).
Root cause: src/tools/board.ts extracted x/y from params and renamed
them to centerX/centerY before forwarding to Python:
const { x, y, ...otherParams } = params;
callKicadScript('add_board_outline', { centerX: x, centerY: y, ...otherParams })
Python received centerX=0, centerY=0 and used that as the board centre,
placing the outline at (-15,-15)→(+15,+15).
Fix: Pass x/y directly as top-left corner coordinates. Python already
contains the correct logic: center = x + width/2, y + height/2. Removed
the incorrect rename in board.ts:
callKicadScript('add_board_outline', { shape, ...params })
Bug 3 — print() on stdout corrupted JSON-RPC protocol → Timeout
Symptom: Claude Desktop reported 'Timeout' for add_board_outline even
though Python completed the command in <5 ms. KiCAD was falsely launched.
Root cause: Debug print() statements written to stdout (the same channel
used for JSON-RPC responses) injected non-JSON lines into the protocol.
Node.js could not parse the response → timeout → Claude Desktop invented
a 'KiCAD UI required' workaround.
Fix: Removed all print() calls from outline.py. Logger.info/debug writes
to the log file (~/.kicad-mcp/logs/kicad_interface.log) and is safe.
Files changed:
src/tools/board.ts — Zod schema + removed centerX/centerY rename
python/commands/board/outline.py — auto-upgrade rectangle+radius, remove print()
- searchTools() previously only searched routed tool categories, so
direct tools like snapshot_project, save_project, create_project
returned 0 results when Claude called search_tools('snapshot')
- Direct tools are now searched first, with a hint that they must be
called directly (not via execute_tool)
Also includes routing.py zone-inset fix for rounded board corners
(already staged from previous session)
save_project uses project_commands.board, which was NOT in the propagation
list after pcbnew.LoadBoard() in _handle_import_svg_logo. As a result,
save_project() wrote the old in-memory board (without logo gr_poly entries)
back to disk, erasing the logo every time.
Fix: call _update_command_handlers() after reload, which updates all
command handler board references including project_commands.
Claude sends {shape:'rectangle', params:{x,y,width,height,...}} but handlers
were reading params.get('width') on the outer dict → None → wrong board size.
outline.py: extract inner = params.get('params', params) at method start,
read all dimensions from inner dict.
kicad_interface.py (_ipc_add_board_outline): delegate 'rectangle' to SWIG
path (same as 'rounded_rectangle') so Claude's shape+dims call is handled
correctly. For polygon IPC path: also unwrap inner params for points/width.
FootprintLoad+Flip() on standalone footprint (not yet in board) causes
a 30-second block in KiCAD 9 pcbnew. Solution: add footprint to board
first, then call Flip() with board context available.
Fixes B.Cu placement timeout that killed the Python process.
create_component_instance used line-based insertion which placed new
symbols BEFORE (kicad_sch ...) header when the file was written as
a single line by sexpdata.dumps(). Switch to rfind()-based string
insertion which is format-independent.
Also remove StreamHandler(sys.stdout) from logging — Python logs now
go only to file (~/.kicad-mcp/logs/kicad_interface.log) to avoid
polluting MCP stderr with INFO/DEBUG entries shown as [error].
- add_schematic_net_label: warn in description that coords must be exact pin endpoints; recommend connect_to_net instead
- connect_to_net: stub wire direction now follows pin angle (was hardcoded +X)
- pin_locator.py: add get_pin_angle() and _get_lib_id() helpers
- new tool: get_schematic_pin_locations(schematicPath, reference) → returns exact x/y of every pin endpoint, so Claude can place labels correctly
KiCad 9 refuses to load any schematic whose lib_symbols section contains
an (extends ...) clause, because the extends mechanism is only valid
inside .kicad_sym library files - not inside schematics.
The previous implementation kept the (extends ...) clause and prepended
the parent symbol block with a qualified name, but left the child's
extends referring to the unqualified parent name, causing:
'Error loading schematic: No parent for extended symbol Q_NMOS_GSD'
Fix: add _iter_top_level_items() and _inline_extends_symbol() helpers.
When a library symbol uses extends, the parent's content (pins, graphics,
sub-symbols) is now merged directly into the child definition:
- Parent properties are overridden by child property values
- Sub-symbol names are renamed from ParentName_X_Y to ChildName_X_Y
- The (extends ...) clause is removed entirely
- Only the fully-resolved child symbol is injected into lib_symbols
Affected symbols include Transistor_FET:2N7002, Transistor_BJT:*,
Regulator_Linear:*, Regulator_Switching:* and many others (~30% of the
KiCad standard library uses extends).
Fixes#52
PROBLEM
-------
Upstream commit b98c94b added 7 comment lines (;; PASSIVES, ;; SEMICONDUCTORS,
;; INTEGRATED CIRCUITS, ;; CONNECTORS, ;; POWER/REGULATORS, ;; MISC,
;; TEMPLATE INSTANCES) to template_with_symbols_expanded.kicad_sch.
KiCAD's S-expression parser does NOT support any comment syntax.
It expects every non-empty line to begin with '('. These comments caused
KiCAD 9 to refuse opening any schematic generated from this template:
Expecting '(' in <file>.kicad_sch, line 8, offset 5
AFFECTED USERS
--------------
Any project whose .kicad_sch was generated by the MCP server after upstream
commit b98c94b and before this fix contains the same invalid lines. Those
files must be repaired manually: open the .kicad_sch in a text editor and
delete every line beginning with ';;'.
FIX
---
Remove all 7 ;; lines from the template. No functional change — the comments
provided no information that is not already evident from the symbol names.
ALSO
----
CHANGELOG: add critical bug-fix entry for this regression under v2.2.2-alpha