Commit Graph

388 Commits

Author SHA1 Message Date
Samuel Price
b3940b9331 test: add unit parameter tests for add_schematic_component
Covers create_component_instance and _handle_add_schematic_component:
- default unit=1 behaviour
- explicit unit 2 and 4 written to (unit N) in schematic S-expression
- (instances ...) block also records the correct unit
- multiple units of the same reference placed independently
- handler param validation (missing schematicPath, missing component)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:15:02 -04:00
Samuel Price
78e3b8860a feat: add unit parameter to add_schematic_component for multi-unit symbols
Allows placing a specific unit (A=1, B=2, C=3, …) of a multi-unit KiCad
symbol rather than always defaulting to unit 1. Required for quad
optocouplers, dual op-amps, and other multi-unit parts where each channel
must be placed independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:11:15 -04:00
Tom
c4bcc34894 Merge pull request #113 from thesamprice/fix/mac-python-path
fix: use KICAD_PYTHON env var instead of hardcoded Windows path
2026-04-19 13:55:19 +02:00
Eugene Mikhantyev
e164f12ffa tests: add regression tests for pin location y-axis, reference trailing underscore, and clone dedup
Covers the three bugs fixed in the previous commit:
- TestAddComponentNoTrailingUnderscore (integration): verifies clone() + no extra append()
- TestPinLocatorYAxisNegation (unit): rotation=0 and 90° cases with y-negation
- TestPinLocatorReferenceRstrip (unit): lookup tolerates 'R1_' artifact from kicad-skip

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:42:08 +01:00
Noah Piqué
ab2500fb8d fix: correct pin location calculation and symbol reference dedup in kicad-skip
Three bugs fixed in the schematic component and pin locator pipeline:

1. component_schematic: remove redundant symbol.append() after clone()
   kicad-skip's clone() already inserts the raw element into the schematic
   tree. The subsequent NamedCollection.append() detects the reference as
   already registered (from the elementRename triggered by setting
   property.Reference.value) and renames it "R1_" with a trailing
   underscore, causing all subsequent pin lookups to fail.

2. pin_locator: negate lib y coordinate before rotation
   lib_symbols in .kicad_sch use library y-up convention; schematic
   coordinates use y-down. get_pin_location now negates pin_rel_y before
   applying rotation, matching KiCad's own transform order (same approach
   as _transform_local_point in schematic_analysis.py).

3. pin_locator: add .rstrip("_") guard in all symbol reference lookups
   Defensive guard against any residual cases where kicad-skip writes a
   trailing underscore to the Reference property value.

Also fixes the self-test script to use template_with_symbols.kicad_sch
(which contains placed _TEMPLATE_* symbols) rather than the expanded
template (which only contains lib_symbols definitions and has no cloneable
instances).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:31:14 +01:00
Eugene Mikhantyev
f494f5fb37 chore: untrack CLAUDE.md and add to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:24:50 +01:00
Eugene Mikhantyev
c8f6a58116 feat: add move_schematic_net_label tool
Moves a net label (local, global, or hierarchical) to a new position in
place, avoiding the error-prone delete-then-re-add workflow. Supports an
optional currentPosition disambiguator and labelType filter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:14:29 +01:00
Samuel Price
8ace3e4d24 fix: use KICAD_PYTHON env var instead of hardcoded Windows path
The Python executable and PYTHONPATH were hardcoded to Windows paths,
causing the server to fail silently on macOS/Linux. Now reads
KICAD_PYTHON from the environment (set by setup-macos.sh) with
python3 as the fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 17:10:56 -04:00
Eugene Mikhantyev
3d996427ee Merge pull request #111 from mixelpixx/chore/normalize-line-endings
chore: enforce LF line endings and normalize the tree
2026-04-18 15:34:45 +01:00
Eugene Mikhantyev
e06082bb44 chore: normalize schematic.py and apply black to create_schematic signature
Bundles two changes for python/commands/schematic.py:
  1. CRLF → LF line-ending normalization (matches the bulk renormalize
     from the previous commit — was held back here because black would
     also need to re-reformat it).
  2. Black reflow of create_schematic()'s parameter list, which exceeded
     the line length. Pre-existing drift, no logic change.

`git show --ignore-all-space HEAD` shows just the 2-line signature diff.
2026-04-18 15:24:02 +01:00
Eugene Mikhantyev
bfc25639c2 chore: normalize all tracked files to LF line endings
Mechanical application of the `.gitattributes` rules from the prior commit.
All 50 files differ only in line endings — verified by
`git diff --cached --ignore-all-space` being empty.

Before: main had 42 CRLF + 27 LF Python files plus mixed-ending in YAML,
templates, and shell scripts. After: every text file is LF (except the
Windows-native *.ps1, *.bat scripts which remain CRLF per gitattributes).

This eliminates the noisy-diff failure mode seen in PR #102, where a
small logic change produced a 918-line diff due to whole-file CRLF→LF
conversion.
2026-04-18 15:23:00 +01:00
Eugene Mikhantyev
2c35ff40a7 chore: enforce LF line endings via gitattributes, editorconfig, pre-commit
Introduces a three-layer defence against CRLF/LF drift:

- `.gitattributes` normalizes all text files to LF on commit and checkout;
  Windows-native scripts (*.bat, *.cmd, *.ps1) explicitly keep CRLF.
- `.editorconfig` instructs editors (VS Code, JetBrains, vim, etc.) to save
  with LF by default so the problem is prevented at the source.
- `mixed-line-ending --fix=lf` hook in pre-commit catches anything that
  slips through and auto-fixes it before commit.

No file contents are normalized in this commit — that follows in a
separate `git add --renormalize .` commit for easier review.
2026-04-18 15:20:20 +01:00
Eugene Mikhantyev
03bafce616 Merge pull request #110 from mixelpixx/refactor/remove-dead-list-library-symbols-stub
refactor: remove dead list_library_symbols stub in LibraryManager
2026-04-18 15:16:50 +01:00
Eugene Mikhantyev
0bc31b2043 refactor: remove dead list_library_symbols stub
The placeholder static method on LibraryManager (library_schematic.py)
returned [] and had no dispatch entry or caller. The real tool of the
same name lives in library_symbol.py.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:14:53 +01:00
Eugene Mikhantyev
2dc6f6a81a Merge pull request #109 from mixelpixx/feat/schematic-label-filters-and-duplicates
feat: add netName and labelType filters to list_schematic_labels
2026-04-18 15:09:19 +01:00
Eugene Mikhantyev
9a66f5e0b9 feat: add netName and labelType filters to list_schematic_labels
Add optional netName (exact case-sensitive match) and labelType
(net/global/power enum) parameters. Both are optional and AND
together when combined. Omitting both preserves current behaviour.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:07:23 +01:00
Eugene Mikhantyev
4ec63f7544 Merge pull request #107 from mixelpixx/fix/get-symbol-info-spice-opamp
fix: get_symbol_info returns neighboring symbol's data for short blocks
2026-04-18 14:46:49 +01:00
Eugene Mikhantyev
e5cd924b0a Merge pull request #102 from ffindog/fix/netlist-label-at-pin
fix: resolve nets when labels are placed directly at pin endpoints
2026-04-18 14:37:46 +01:00
Tom
a422e4eb0c Merge pull request #87 from tnemrap/fix/create-schematic-path
fix: create_schematic now respects the path parameter
2026-04-18 14:33:58 +02:00
Tom
56e6aead88 Update python/commands/schematic.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-18 14:31:22 +02:00
Tom
75a0b764d5 Update python/kicad_interface.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-18 14:31:09 +02:00
Eugene Mikhantyev
55ec4950d9 fix: get_symbol_info returns wrong data for every small symbol
Parser used a 5000-char heuristic slice per symbol; any symbol block
shorter than 5000 chars bled into the next one, and last-write-wins in
the properties dict ensured the neighbor's data clobbered the target.
Reported as Simulation_SPICE:OPAMP returning PJFET data.

Switch to parenthesis-depth tracking to find the true end of each
(symbol ...) block. Also surface Sim.Pins so agents can read opamp pin
numbering without inferring it from schematic placement.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 12:55:41 +01:00
Eugene Mikhantyev
e687fa39e1 Merge pull request #104 from LeahArmstrong/feat/hierarchy-tools
feat: add hierarchical label and sheet pin tools
2026-04-18 12:00:22 +01:00
Tom
4a6d6c725a Merge pull request #106 from Kletternaut/feat/github-readme-multilingual
Feat/GitHub readme multilingual
2026-04-17 16:32:07 +02:00
Tom
497a6ce1d5 docs: add top anchor and back-to-top navigation links 2026-04-17 16:30:03 +02:00
Tom
402dec2d86 docs: add disclaimer/liability exclusion in EN, DE, ZH 2026-04-17 16:30:03 +02:00
Tom
b5fdf19a94 docs: add Simplified Chinese (ZH) translation to README 2026-04-17 16:30:03 +02:00
Tom
5f1efaafa2 docs: add link to full README in EN and DE documentation sections 2026-04-17 16:30:03 +02:00
Tom
74cd27957f docs: sync German translation with updated English sections 2026-04-17 16:30:03 +02:00
Tom
ef4d0f0ffb feat: improve .github/README.md landing page copy 2026-04-17 16:30:03 +02:00
Tom
8d12993304 feat: add .github/README.md multilingual landing page with logo 2026-04-17 16:30:03 +02:00
Eugene Mikhantyev
bddb7d9e34 Merge pull request #100 from LeahArmstrong/fix/erc-kicad9-violations
fix: ERC handler fails on KiCad 9 schematics
2026-04-15 23:17:31 +01:00
Eugene Mikhantyev
5b67967442 Merge pull request #101 from OmsAhmad/fix/macos-python-39-support
chore: align Python version floor with KiCad's macOS bundle (3.9)
2026-04-15 22:48:20 +01:00
Leah Armstrong
101b4e1dad feat: add hierarchy tools (hierarchical label + sheet pin)
Two new tools for managing hierarchical schematic connections:

- add_schematic_hierarchical_label: create sheet interface ports on
  sub-sheet schematics. These are the sub-sheet side of hierarchical
  connections, linking to sheet pins on the parent.

- add_sheet_pin: add pins to sheet symbol blocks on the parent
  schematic. Targets the correct sheet by matching the Sheetname
  property. The pinName must match a hierarchical_label in the
  sub-sheet.

Both tools use text-based S-expression insertion (not sexpdata
round-trip) to preserve KiCad's native file formatting. Labels
include proper justification based on orientation: left-justify for
rightward labels (0°), right-justify for leftward labels (180°).

Wire manager additions:
- _find_insertion_point(): locates sheet_instances block or final paren
- _text_insert(): inserts formatted S-expression text at the right position
- _make_hierarchical_label_text(): generates hierarchical_label S-expression
- _make_sheet_pin_text(): generates sheet pin S-expression
- WireManager.add_hierarchical_label(): static method for label insertion
- WireManager.add_sheet_pin(): static method for pin insertion into
  named sheet blocks

12 unit tests covering insertion, orientation/justification mapping,
parameter validation, multi-sheet targeting, and error handling.
2026-04-15 12:32:09 -04:00
ffindog
ef660afdb4 fix: resolve nets when labels are placed directly at pin endpoints
get_net_connections() built its match-point set exclusively from wire
endpoints. If a net label was placed directly at a pin endpoint with no
wire segment (valid KiCad style), the function returned 0 connections
because connected_wire_points was empty.

Fix: build all_match_points as the union of connected wire endpoints and
label positions. Pin matching checks both, so label-at-pin schematics
produce correct netlists alongside traditional wired schematics.

Also handles the case where the schematic object has no wire attribute
at all — instead of returning early, we continue with label positions
as the sole match points.

Tests: tests/test_label_at_pin_net_connections.py (11 unit tests)
  - label at pin, no wire → pin found
  - label at pin, within/outside tolerance
  - label via wire → still found (regression)
  - mixed wired and direct labels on same net
  - no wire attribute → still detects label-at-pin
  - template symbols skipped

Black/isort/flake8/mypy verified manually (pre-commit local npm hook
fails to install on Windows due to MobaXterm path environment issue).
2026-04-15 22:40:14 +10:00
ffindog
5d87d9bc74 merge: upstream/main (57 commits) — preserve PR #102 net label fix
Merged upstream/main into our fork. Conflict in connection_schematic.py
resolved by taking upstream's file and re-applying our fix:
- all_match_points = connected_wire_points | label positions
- Allows nets where labels are placed directly at pin endpoints (no wire)

Upstream changes include: security fixes (8 vulns), new schematic tools
(get_net_at_point, find_orphaned_wires, snap_to_grid, get_wire_connections),
generate_netlist rewrite via kicad-cli, wire preservation on component move,
schematic analysis tools, KiCad 10 support.
2026-04-15 22:27:41 +10:00
ffindog
00a59a590b fix: resolve nets when labels are placed directly at pin endpoints
get_net_connections() previously required wire segments between net
labels and component pins. If a label was placed exactly at a pin
endpoint (no wire), the net was silently dropped and generate_netlist
returned 0 nets.

Fix: build all_match_points as the union of connected wire endpoints
and label positions. Pin matching now checks both, so label-at-pin
schematics (valid KiCad style) produce correct netlists alongside
traditional wired schematics.
2026-04-15 22:10:22 +10:00
Omair
a50a60cb52 fix: align Python version floor with KiCad's macOS bundle (3.9)
KiCad ships Python 3.9 on macOS (both v9 and v10), and `pcbnew.so` is
compiled against that interpreter. The previous `>=3.10` floor was
unreachable on macOS and docs referenced nonexistent
`python3.11/site-packages` paths. Lower the floor and correct the docs;
no source changes needed — all 49 files in `python/` already compile
clean on 3.9.

Also add `.venv/` to `.gitignore` (dotted form used by `python -m venv`).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 23:55:32 -04:00
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
Tom
eea43d18f1 Merge pull request #97 from Kletternaut/fix/security-and-docs-fixes
Fix/security and docs fixes
2026-04-13 09:41:07 +02:00
Tom
5c559998c7 chore: ignore generated windows-mcp-config.json 2026-04-13 09:38:51 +02:00
Tom
5ab13172ff fix: replace placeholder repo URL with correct mixelpixx/KiCAD-MCP-Server 2026-04-13 09:38:51 +02:00
Tom
3f3df82aa4 fix: npm audit fix - resolve 8 vulnerabilities (4 high, 4 moderate) 2026-04-13 09:38:51 +02:00
Eugene Mikhantyev
71fc45e9f5 Merge pull request #96 from mixelpixx/docs/pre-commit-hooks
docs: add pre-commit hooks setup instructions to CONTRIBUTING.md
2026-04-12 20:23:20 +01:00
Eugene Mikhantyev
d1b87f9281 docs: add pre-commit hooks setup instructions to CONTRIBUTING.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 20:19:42 +01:00
Eugene Mikhantyev
3d02e83db8 Merge pull request #95 from mixelpixx/fix/netlist-tools
fix: implement export_netlist handler and rewrite generate_netlist to use kicad-cli
2026-04-12 18:57:14 +01: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
921a6bc4aa Merge pull request #92 from mixelpixx/fix/net-label-pin-snapping-feedback
feat: pin-snapping, coordinate feedback, and schematic diagnostics for net label tools
2026-04-12 18:18:13 +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
33a2118960 docs: document get_net_at_point, list_floating_labels, find_orphaned_wires, snap_to_grid
Four tools added in this branch had no docs coverage. Add entries to
SCHEMATIC_TOOLS_REFERENCE.md with parameter tables, response field
tables, and usage notes. Update section tool counts (Net Analysis 4→5,
Validation 3→6).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 17:52:51 +01:00