Commit Graph

140 Commits

Author SHA1 Message Date
Leah Armstrong
15d06e449a fix: ERC handler fails on KiCad 9 schematics
Two issues with run_erc on KiCad 9:

1. kicad-cli returns non-zero exit code when ERC violations exist.
   The handler treated this as a command failure and returned early
   with success=false, even though valid JSON output was produced.
   Fix: check for output file existence instead of exit code.

2. KiCad 9 nests violations under sheets[].violations instead of
   (or in addition to) the top-level violations[] array used by
   KiCad 8. The handler only read the top-level array, reporting
   0 violations on schematics with sub-sheets.
   Fix: iterate sheets[] and collect all nested violations.

Both fixes are backward-compatible with KiCad 8.

6 unit tests added covering non-zero exit codes, KiCad 8 top-level
violations, KiCad 9 sheets[] nesting, mixed structures, zero
violations, and missing output files.
2026-04-14 12:52:17 -04:00
Eugene Mikhantyev
c7b0e3105b fix: implement export_netlist handler and rewrite generate_netlist to use kicad-cli
export_netlist was returning "Unknown command" because no Python handler
existed. generate_netlist was timing out (30s) due to an O(nets × components
× pins) wire-graph algorithm with a new PinLocator instantiated per net.

Both handlers now delegate to `kicad-cli sch export netlist`:
- export_netlist: new handler; writes KiCad XML / Spice / Cadstar / OrcadPCB2
  to the caller-supplied outputPath. Added schematicPath parameter to the TS
  tool definition (was absent, making file export impossible).
- generate_netlist: replaces the slow wire-graph with kicad-cli + XML parse;
  returns the same {components, nets} JSON the TS handler already expected.

Also adds _find_kicad_cli_static() so both handlers share CLI discovery
without depending on ExportCommands (which requires a loaded pcbnew board).

Cleaned up generate_netlist schema in tool_schemas.py (removed outputPath and
format fields the handler never used), updated MCP tool descriptions and
SCHEMATIC_TOOLS_REFERENCE.md to clearly distinguish the two tools.

26 unit tests added covering parameter validation, subprocess mocking,
format mapping, XML→JSON parsing, and error/timeout propagation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 18:52:46 +01:00
Eugene Mikhantyev
ba09fc4e0f fix: change snap_to_grid default grid from 2.54mm to 1.27mm (50 mil)
Half of all valid KiCAD schematic pin positions are on the 50-mil
(1.27mm) grid but not the 100-mil (2.54mm) grid — e.g. 26.67mm = 21 ×
1.27mm. Snapping to 2.54mm displaced those coordinates by 1.27mm,
moving labels off their pins and increasing floating-label count.

KiCAD source confirms: DEFAULT_CONNECTION_GRID_MILS = 50 and the ERC
off-grid check uses exact integer modulo against this value, so any
displacement breaks connectivity unconditionally.

Also update the kicad-source absolute path in CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 18:10:55 +01:00
Eugene Mikhantyev
1df6332aa8 refactor: address code review issues — remove stale import, fix misleading var name, eliminate redundant adjacency build, add warning log on pin-angle failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 17:32:18 +01:00
Eugene Mikhantyev
4f733bb3db refactor: consolidate get_pin_net into get_wire_connections
get_pin_net was a superset of get_wire_connections with the same
coordinate-based flood-fill but two extra response fields (net, query_point)
and a reference+pin input mode. Having both tools confused LLM tool selection.

get_wire_connections now:
- Returns net (label name or null) and query_point in all response paths
- Accepts reference+pin input in addition to x/y coordinates,
  resolving the pin endpoint via PinLocator internally

get_pin_net tool, handler, schema, TS registration, and tests removed.
test_wire_connectivity.py updated with coverage for all new behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 17:02:35 +01:00
Eugene Mikhantyev
f73d8d9795 feat: warn on case-mismatched net label names in add_schematic_net_label
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:49:15 +01:00
Eugene Mikhantyev
4895bf169c feat: add connected_pin_count to list_schematic_nets and list_floating_labels tool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:46:32 +01:00
Eugene Mikhantyev
e826cf3d32 feat: add get_net_at_point tool for coordinate-based net lookup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:29:46 +01:00
Eugene Mikhantyev
5f3c20d308 feat: add get_pin_net tool for direct net/pin queries
Answers "what net is pin X of component Y on?" without requiring
callers to triangulate from list_schematic_nets or know a wire
coordinate first.

Accepts either {reference, pin} (resolved via PinLocator) or {x, y}
coordinate. Returns net label name (or null for unnamed nets), all
connected pins, wire segments, and the resolved query point.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:19:14 +01:00
Eugene Mikhantyev
9387683368 feat: add snap_to_grid schematic tool
Adds a new MCP tool that snaps wire endpoints, junction positions, and
net label coordinates to the nearest grid point (default 2.54 mm). Off-grid
coordinates cause wires that appear visually connected to fail ERC checks
because KiCAD uses exact IU integer matching internally; this tool eliminates
that class of error before running ERC.

- python/commands/schematic_snap.py: core snap logic with in-place sexp mutation
- python/kicad_interface.py: route + handler
- python/schemas/tool_schemas.py: JSON schema (gridSize, elements params)
- src/tools/schematic.ts: TypeScript MCP tool registration
- tests/test_snap_to_grid.py: 20 unit + integration tests (all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:03:35 +01:00
Eugene Mikhantyev
58bb08a252 feat: add find_orphaned_wires schematic analysis tool
Detects wire segments with at least one dangling endpoint — an endpoint
not connected to a component pin, net label, or another wire.  These
cause ERC 'wire end unconnected' violations and are a common symptom of
incomplete routing or stray stub wires.

Algorithm uses exact KiCad IU (10 000 IU/mm) coordinate matching,
consistent with wire_connectivity.py:
  1. Build an endpoint-frequency map for all wires (IU precision)
  2. Collect anchored IU points: component pins (via PinLocator),
     net labels / global_labels, power symbol pins
     (via _parse_virtual_connections)
  3. An endpoint is dangling when it is touched by exactly one wire AND
     is not an anchored point; the containing wire is reported

Does not require the KiCad UI to be running.

Changes:
  python/commands/schematic_analysis.py — find_orphaned_wires() function
  python/kicad_interface.py             — handler + route registration
  python/schemas/tool_schemas.py        — MCP schema entry
  src/tools/schematic.ts                — TypeScript server.tool() call
  tests/test_schematic_analysis.py      — 7 integration tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:44:12 +01:00
Eugene Mikhantyev
94125eda7f fix: add pin-snapping and coordinate feedback to net label tools
add_schematic_net_label now accepts optional componentRef + pinNumber to
snap the label directly to the exact pin endpoint via PinLocator, removing
all approximation risk.  The response always includes actual_position and,
when snapping was used, snapped_to_pin — so the caller gets confirmation
of exactly where the label landed.

connect_to_net return type changed from bool to Dict, returning
pin_location, label_location, and wire_stub on success so agents no
longer need a separate verification call to confirm placement.

connect_passthrough updated to check result.get("success") against the
new dict return.  tool_schemas.py and schematic.ts updated to match
(position is now optional, componentRef/pinNumber/labelType/orientation
added, connect_to_net schema field names corrected).

17 new unit tests in tests/test_net_label_pin_snapping.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:12:11 +01:00
Michael Parment
dd19828cba Revert "fix: rotate_schematic_component mirror parameter no longer crashes"
This reverts commit 6e80ccd013.
2026-04-09 09:25:17 +02:00
Michael Parment
6e80ccd013 fix: rotate_schematic_component mirror parameter no longer crashes
Previously passing mirror='x' or mirror='y' to rotate_schematic_component
always raised:
  'NoneType' object has no attribute 'value'

Root cause: kicad-skip has no API for setting (mirror x/y) on a placed
symbol instance. The handler tried to use a non-existent kicad-skip
attribute, returning None, then calling .value on it.

Fix: add _apply_mirror_to_symbol_sexp() which directly patches the
(mirror x/y) S-expression token in the .kicad_sch file. The rotate
handler now applies rotation via kicad-skip (which works fine) and
delegates mirror to this helper.

The helper:
- Inserts (mirror x/y) immediately after the (at x y rot) token
- Removes any existing mirror token before inserting the new one
  (prevents duplicate tokens when toggling axis)
- Returns False gracefully when the reference is not found

Tests: 6 unit tests in tests/test_rotate_schematic_mirror.py
covering: add x, add y, remove, replace, unknown ref, no-mirror smoke test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 09:23:02 +02:00
Michael Parment
01011487d0 fix: merge upstream type annotations into create_schematic signature
Combined our path parameter fix with upstream's type annotation additions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:43:13 +02:00
Michael Parment
b3ca93a98d fix: create_schematic now respects the path parameter
Previously the path argument to create_schematic() was accepted by the
tool schema but silently ignored in SchematicManager.create_schematic()
(python/commands/schematic.py). The schematic file was always written
using only the bare filename, resolving to the MCP server's working
directory.

On systems where that directory is not writable (e.g. Program Files,
OneDrive-synced folders) this caused:
  [Errno 13] Permission denied: 'myproject.kicad_sch'

Fix:
- Add path: Optional[str] = None parameter to SchematicManager.create_schematic()
- Compute output_path as os.path.join(path, base_name) when path is given
- Forward the resolved path from _handle_create_schematic() into create_schematic()

Tests: added tests/test_create_schematic_path.py with three unit tests
covering: path respected, no-path fallback, and no double-suffix on .kicad_sch names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:27:53 +02:00
Eugene Mikhantyev
9b1024a8f3 chore: enable strict mypy checks and fix pre-commit mypy hook
Add type annotations to all previously untyped functions and remove 9
suppressed error codes (call-arg, assignment, return-value, operator,
has-type, dict-item, misc, list-item, annotation-unchecked) by fixing
the underlying type issues.

Add [[tool.mypy.overrides]] with ignore_missing_imports for KiCAD-specific
modules (pcbnew, sexpdata, skip, cairosvg, kipy, PIL) so the pre-commit
mypy hook passes in its isolated venv. Add types-requests and pytest to
additional_dependencies in .pre-commit-config.yaml.

Also fixes several real bugs uncovered by stricter checks: incorrect static
calls to instance methods in swig_backend, wrong return type on get_size,
missing value param in BoardAPI.place_component, variable shadowing in
kicad_process.py, unqualified LibraryManager reference in kicad_interface,
and missing top-level Path import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 23:50:54 +01:00
William Viana
0bc00b1451 fix: prevent pcbnew stdout noise from causing sync_schematic_to_board timeouts
The TS<->Python communication channel uses stdout for JSON responses.
pcbnew's C++ SWIG layer can write warnings and diagnostics directly to
C-level stdout (fd 1), corrupting the JSON framing. The TS parser then
never sees valid JSON and the command times out after 30 seconds.

Three changes fix this:

1. Python stdout redirect: In main(), save the original stdout fd for
   exclusive JSON response use, then redirect fd 1 to stderr so all
   pcbnew C++ output goes to logs instead of the response pipe.

2. Robust TS JSON parser: tryParseResponse() now uses newline-delimited
   parsing as a fallback. The Python side writes single-line JSON
   terminated by \n; the parser uses this as the completion signal
   instead of brace-matching, which prevents premature resolution of
   truncated chunked responses. Non-JSON preamble lines are logged
   and stripped.

3. Fix stray print() calls: Converted print() to logger in
   component_schematic.py and library_schematic.py so they don't
   leak to stdout during normal operations.

Also adds sync_schematic_to_board to the longRunningCommands list for
an appropriate timeout value.
2026-04-03 11:24:42 -07:00
Eugene Mikhantyev
d58283ef0a feat: synthesize wires for touching-pin connections on component move
When moving a schematic component whose pins directly touch pins of
stationary components (no wire segment, just pin-to-pin contact),
synthesize bridge wires to preserve the electrical connection after
the move. Also fixes duplicate-pin-position collision in old_to_new
map and updates symbol reference assignment to use setAllReferences.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 23:41:42 +01:00
Eugene Mikhantyev
a152b75db3 feat: move_schematic_component with wire preservation (drag behavior)
When moving a schematic component, connected wires are stretched/shifted
to follow the component (like KiCAD's drag behaviour), preserving
connectivity instead of leaving dangling wire stubs.

Also fixes property labels (value, reference, etc.) so they shift with
the symbol rather than staying at their original positions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 20:34:22 +01:00
Eugene Mikhantyev
c44bd9205d style: sort Python imports with isort
Add isort configuration (profile=black, line_length=100) to pyproject.toml,
add isort pre-commit hook, and auto-sort imports across all Python source files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:02:24 +01:00
Eugene Mikhantyev
75cead0860 style: apply Black formatting to all Python files
Add [tool.black] config to pyproject.toml and Black hook to
.pre-commit-config.yaml (rev 26.3.1), then auto-format all Python
source and test files with line-length=100, target-version=py310.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:01:08 +01:00
mixelpixx
a76c5bc74b Merge pull request #61 from Mehanik/fix/tool-schema-descriptions
feat: add_schematic_wire & add_schematic_junction with pin snapping and polyline routing
2026-03-28 15:40:58 -04:00
Eugene Mikhantyev
3bd3c3a962 feat: add wire/junction tools with pin-snapping and T-junction support
- Rename add_schematic_connection → add_schematic_wire with waypoints[] parameter
- Add snapToPins (default true) to snap wire endpoints to nearest pin
- Expose add_schematic_junction as an MCP tool
- Break existing wires at new wire endpoints for T-junction support
- Remove orphaned add_connection / add_wire / get_pin_location from ConnectionManager
- Update tool registry to reflect renamed schematic tools in TS layer
- Add 76 tests for wire/junction handler dispatch, schema validation, and WireManager corner cases
- Apply Black and Prettier formatting to changed files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 21:46:36 +00:00
Eugene Mikhantyev
9f89437918 chore: apply Black formatting and add tests for get_wire_connections
- Apply Black formatting to wire_connectivity.py, kicad_interface.py,
  and tool_schemas.py (changed files only)
- Add python/tests/conftest.py with pcbnew/skip C-extension stubs
- Add python/tests/test_wire_connectivity.py with 29 unit tests covering
  schema validation, handler dispatch, parameter validation, and core
  logic (_to_iu, _parse_wires, _build_adjacency, _find_connected_wires,
  get_wire_connections)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:26:25 +00:00
Eugene Mikhantyev
f120034846 refactor: extract wire connectivity into module with KiCad-native IU matching
Move wire connectivity logic from _handle_get_wire_connections into
commands/wire_connectivity.py. Use KiCad's internal integer unit system
(10,000 IU/mm) with exact coordinate matching instead of tolerance-based
float comparison, mirroring how KiCad itself determines connectivity.

Key improvements:
- Exact integer matching for wire endpoints (O(1) dict lookup vs O(n) grid scan)
- Junction support for T-connections
- Multi-unit symbol support (removed incorrect processed_refs dedup)
- Single public API: get_wire_connections()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
4277a3d000 refactor: use pre-compiled adjacency list for BFS in get_wire_connections
Replace runtime spatial-index queries during BFS with a pre-compiled
adjacency list for O(1) edge traversal. Also fix potential UnboundLocalError
for `ref` in the pin-checking exception handler and simplify validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
b257bef89b fix: harden get_wire_connections against edge cases and improve performance
- Add +1 safety margin to grid_radius to handle banker's rounding at cell
  boundaries in the spatial index
- Move symbol property guards inside per-symbol try/except to prevent
  AttributeError from aborting all pin processing
- Replace O(n) connected_points scan for pin matching with spatial index
  lookup (_frontier_has_neighbour), consistent with flood-fill approach
- Wrap float(x)/float(y) conversion with clear user-facing error message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
ddbfc62a49 fix: address review issues in get_wire_connections
- Fix critical bug: use pin_data[0]/[1] instead of pin_data["x"]/["y"]
  (get_all_symbol_pins returns List[float], not dict)
- Use index-based wire tracking to avoid fragile float list equality
- Check all polyline points (not just endpoints) during flood-fill
- Add spatial index (0.05mm grid) to replace O(n²) frontier scan
- Skip already-processed refs to avoid redundant calls for multi-unit symbols
- Include wires_out in early return when schematic has no symbols
- Add get_wire_connections schema entry to tool_schemas.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
6633cd59fd feat: add get_wire_connections tool for pin/wire lookup by schematic point
Given a single (x,y) coordinate on the schematic, flood-fills through all
connected wire segments and returns every component pin reachable on that net,
plus the full list of wire segments with their start/end coordinates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 19:24:38 +00:00
Eugene Mikhantyev
c5a0bc495c style: apply Black formatting to kicad_interface.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 21:47:49 +00:00
Eugene Mikhantyev
59bd4c4acf style: apply Black formatting to changed files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 21:37:05 +00:00
Eugene Mikhantyev
1ef4ce5cab refactor: remove find_unconnected_pins tool (redundant with run_erc)
KiCad's native ERC already checks for unconnected pins with better
accuracy (hierarchical sheets, bus connections, custom rules). Remove
the reimplemented version and its dead helper _parse_no_connects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:36:50 +00:00
Eugene Mikhantyev
0ab7428b84 fix: address PR review issues for schematic analysis tools
Eliminate repeated file parsing by extracting _extract_lib_symbols helper
that walks already-parsed sexp_data once instead of re-reading the file
per symbol via PinLocator. Support diagonal wire overlap detection using
cross-product parallelism and 1D projection. Fix wire region inclusion to
use AABB intersection for pass-through wires. Normalize view region
coordinates. Clarify tolerance docstrings across Python, TS, and schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:36:50 +00:00
Eugene Mikhantyev
76ad44121c fix: rename check_wire_collisions to find_wires_crossing_symbols and detect pass-through wires
Wires that start at a component pin but continue through the body were
incorrectly suppressed as "valid connections." Now nudges the pin endpoint
toward the other end and re-tests intersection — if the shortened segment
still hits the bbox, the wire passes through and is flagged.

Renamed the tool from check_wire_collisions to find_wires_crossing_symbols
across all layers (Python, handler, schema, TypeScript) to clarify that it
finds wires crossing over component symbols, which is unacceptable in
schematics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:36:50 +00:00
Eugene Mikhantyev
9141e33b70 fix: get_schematic_view_region SVG export and coordinate system
- Use a temp directory (not file) for kicad-cli svg output, which expects a directory path
- Clean up temp dir with shutil.rmtree instead of individual file unlinks
- Fix viewBox cropping: KiCad schematic SVGs use mm directly, not mils (removed erroneous 39.3701 multiplier)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 21:36:50 +00:00
Eugene Mikhantyev
764b8db3d3 feat: add schematic analysis tools (read-only)
Add five new read-only schematic analysis MCP tools:
- get_schematic_view_region: export cropped schematic region as PNG/SVG
- find_unconnected_pins: list pins with no wire/label/power connection
- find_overlapping_elements: detect duplicate symbols, stacked labels, collinear wire overlaps
- get_elements_in_region: list all symbols/wires/labels in a bounding box
- check_wire_collisions: detect wires passing through component bodies

Includes Python handler dispatch, tool schemas, TypeScript server bindings,
the schematic_analysis command module, and a full test suite (28 tests passing).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 21:36:50 +00:00
Jeff Laflamme
53a8b3ff3e Add Freerouting autoroute integration
4 new MCP tools: autoroute (full DSN→Freerouting→SES pipeline),
export_dsn, import_ses, check_freerouting. Requires Java 11+ and
freerouting.jar. Includes 21 test cases and README usage examples.
2026-03-20 11:33:37 +07:00
mixelpixx
5b380c0f17 Merge pull request #66 from Mehanik/feature/schematic-component-field-inspection
feat: schematic component field inspection and label repositioning
2026-03-16 21:33:51 -04:00
mixelpixx
fbbe5a408d Merge pull request #67 from Mehanik/fix/delete-schematic-component-multiline
fix: delete_schematic_component fails on multi-line KiCAD format
2026-03-16 20:14:44 -04:00
Eugene Mikhantyev
f562035f79 test: add schematic tools tests and apply black formatting
- Add python/tests/conftest.py with MagicMock stubs for pcbnew/skip
- Add python/tests/test_schematic_tools.py with 29 tests covering
  WireManager.delete_wire, WireManager.delete_label (unit + integration),
  and parameter validation for all 11 new _handle_* methods
- Apply black formatting to component_schematic.py, wire_manager.py,
  and kicad_interface.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 22:48:24 +00:00
Eugene Mikhantyev
22a7561f5c style: apply Black formatting to changed files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 22:33:50 +00:00
Eugene Mikhantyev
da359513bf fix: delete_schematic_component fails on multi-line KiCAD format
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>
2026-03-15 21:36:39 +00:00
Eugene Mikhantyev
ccd817531a feat: add get_schematic_component tool and fieldPositions to edit_schematic_component
- 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>
2026-03-15 15:37:52 +00:00
Eugene Mikhantyev
4dc351660c fix: apply sexpdata round-trip write to delete_schematic_net_label
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>
2026-03-13 01:08:49 +00:00
Eugene Mikhantyev
9d9234abd0 fix: replace kicad-skip mutation with sexpdata in delete_schematic_wire
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>
2026-03-13 00:39:23 +00:00
Eugene Mikhantyev
2956b4fa9d fix: use _elements.remove() for kicad-skip collections lacking remove method
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>
2026-03-13 00:27:17 +00:00
Eugene Mikhantyev
ffe51f0f16 fix: address review issues in schematic tools
- 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>
2026-03-13 00:23:26 +00:00
Eugene Mikhantyev
72e5320044 feat: add get_schematic_view tool for rasterized schematic images
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>
2026-03-12 23:57:39 +00:00
Eugene Mikhantyev
b2a547e624 feat: add 11 missing schematic inspection & editing tools
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>
2026-03-12 23:52:11 +00:00