Commit Graph

247 Commits

Author SHA1 Message Date
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
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
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
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
94b234a36e docs: update SCHEMATIC_TOOLS_REFERENCE for pin-snapping and coord feedback
- add_schematic_net_label: document new optional componentRef/pinNumber
  snap-to-pin mode, labelType/orientation params, response fields
  (actual_position, snapped_to_pin), and updated position to optional
- connect_to_net: document new response fields (pin_location,
  label_location, wire_stub)
- get_schematic_pin_locations: update cross-reference to reflect that
  direct pin snapping is now available in add_schematic_net_label

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:33:48 +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
Eugene Mikhantyev
0bf73674da Merge pull request #91 from mixelpixx/refactor/consolidate-tests-directory
refactor: consolidate Python tests into single tests/ directory
2026-04-12 11:28:13 +01:00
Eugene Mikhantyev
5de932e2b3 refactor: consolidate python/tests/ into tests/ directory
Move all Python test files from python/tests/ to the top-level tests/
directory to match the project's CONTRIBUTING.md guidelines. Update
sys.path inserts and template path references to reflect the new
location.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 11:22:39 +01:00
Tom
c92ca96bac Merge pull request #89 from nhebling/feat/macos-setup-script
feat: Add macOS automated setup script and update platform documentation
2026-04-11 21:29:30 +02:00
nhebling
e28df51eb1 fix: address maintainer review feedback on setup-macos.sh
Fix incorrect default Claude Desktop config path — macOS uses
~/Library/Application Support/Claude/claude_desktop_config.json,
not ~/.config/Claude/claude_desktop_config.json.

Capture stderr in merge_config subshell (2>&1) so Python tracebacks
and interpreter errors are surfaced instead of silently dropped when
the command substitution fails under set -e.

Update README.md and docs/PLATFORM_GUIDE.md to reflect the corrected
macOS config path, and split the combined Linux/macOS config location
reference into separate per-platform entries.

Add trailing newline at the end.
2026-04-11 21:10:14 +02:00
nhebling
0255064648 feat: add macOS automated setup script and update platform documentation
Add setup-macos.sh, a shell script that automates Claude Desktop MCP
configuration on macOS. The script detects KiCad's bundled Python,
resolves PYTHONPATH, generates the correct MCP server config, and
safely merges it into the existing Claude Desktop configuration with
backup support. Supports --verify, --dry-run, and --apply modes.

Update README.md with documentation for the automated setup workflow,
including usage examples, parameter reference, and post-setup steps.

Extend docs/PLATFORM_GUIDE.md with macOS-specific sections covering
installation, path handling, Python environment, troubleshooting,
best practices, cross-platform migration, and support resources.

Update docs/STATUS_SUMMARY.md to reflect the new macOS automation
capabilities and bump the last-updated date.
2026-04-11 17:25:01 +02:00
Eugene Mikhantyev
227433716a Merge pull request #86 from mixelpixx/fix/enable-import-untyped-mypy
chore: enable strict mypy checks and fix real bugs uncovered
2026-04-06 21:28:27 +01: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
Eugene Mikhantyev
5a2b481db3 chore: remove mypy overrides now that venv uses system-site-packages
With --system-site-packages, mypy can resolve pcbnew, skip, and sexpdata
directly from the system/venv, so per-module ignore_missing_imports
overrides are no longer needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 21:30:50 +01:00
Eugene Mikhantyev
c0630c2b64 chore: remove unused mypy overrides for cairosvg, kipy, schematic
These packages are not imported anywhere in the codebase, so their
ignore_missing_imports overrides were unnecessary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 21:26:05 +01:00
Eugene Mikhantyev
5d1477f548 chore: enable import-untyped and import-not-found mypy checks
Remove global ignore_missing_imports and the import-untyped disable,
replacing them with targeted per-package overrides for third-party
libraries that lack stubs (pcbnew, skip, sexpdata, cairosvg, kipy,
schematic). Also add python/ to mypy_path so internal modules resolve.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 21:24:00 +01:00
Eugene Mikhantyev
f9875ab617 Merge pull request #85 from vdawger/fix/extend-timeout-schematic-queries
fix: extend timeout for schematic query commands on large files
2026-04-05 20:20:39 +01:00
William Viana
c43784cd78 fix: extend timeout for schematic query commands on large files
Add list_schematic_nets, list_schematic_labels, and get_schematic_view
to the longRunningCommands list so they use the 10-minute timeout
instead of the default 30 seconds. These commands regularly exceed
the 30s limit on larger schematic files.
2026-04-05 09:33:29 -07:00
mixelpixx
25f856024c Merge pull request #83 from vdawger/fix/stdout-pollution-timeout
fix: prevent pcbnew stdout noise from causing sync_schematic_to_board timeouts
2026-04-04 14:34:19 -04: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
f79a3d6435 Merge pull request #65 from Mehanik/feat/move-component-wire-preservation
feat: move_schematic_component with wire preservation (drag behavior)
2026-03-29 23:56:00 +01:00
Eugene Mikhantyev
25e81b6411 refactor: move move_schematic_component registration back to original position
Restore the tool registration order so move_schematic_component appears
before rotate_schematic_component, matching the pre-PR location.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 23:54:29 +01:00
Eugene Mikhantyev
c4f013e6c7 fix: remove duplicate move_schematic_component tool registration and add regression test
The PR added a second server.tool("move_schematic_component", ...) at line 1127
without removing the original registration at line 722, causing the server to
fail on startup with "Tool move_schematic_component is already registered".

Also adds tests/test_ts_tool_registry.py which scans all src/tools/**/*.ts files
for duplicate server.tool() names so this class of bug is caught automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 23:45:21 +01: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
mixelpixx
74471ce72e Merge pull request #81 from mixelpixx/setup-pre-commit
chore: set up pre-commit hooks to enforce CONTRIBUTING.md code style rules
2026-03-29 10:08:49 -04:00
Eugene Mikhantyev
f39937e8b8 fix: use local prettier from package.json and clean up prettierignore
- Replace mirrors-prettier alpha (v4.0.0-alpha.8) with local hook using
  the stable prettier installed via package.json
- Remove .prettierignore entries already handled by the hook's exclude pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:35:26 +01:00
Eugene Mikhantyev
bc1e33b652 fix: resolve pre-commit hook issues for mypy and root-level files
- Fix mypy duplicate module conflict by excluding python/commands/board.py
- Add import-untyped to mypy disabled error codes
- Use explicit_package_bases for proper module resolution
- Auto-format root-level download_jlcpcb.py and test-router.js

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:21:05 +01:00
Eugene Mikhantyev
dbbbde17ba chore: add ESLint with TypeScript support and baseline config
Install eslint, @eslint/js, and typescript-eslint as dev dependencies.
Add eslint.config.js (flat config) with rules tuned to zero errors on
the current codebase, add ESLint local hook to .pre-commit-config.yaml,
and update the lint:ts npm script to use ESLint directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:15:15 +01:00
Eugene Mikhantyev
3456a1df26 chore: add MyPy type checking config with baseline ignore rules
Adds [tool.mypy] section to pyproject.toml with permissive baseline settings
and disables error codes that fire against the existing untyped codebase.
Adds the mirrors-mypy pre-commit hook (v1.19.1) running over python/ at once.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:10:03 +01:00
Eugene Mikhantyev
fc70a4785c chore: add Flake8 linting config with baseline ignore rules
Adds .flake8 config and registers the flake8 pre-commit hook scoped to
python/ at rev 7.3.0. Baseline ignore rules (E501, F401, F541, F841,
E722, E402, E741, F811, F821, F824, E231) suppress existing violations
so the hook passes cleanly on the current codebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:07:39 +01:00
Eugene Mikhantyev
7d50fa1d4c style: apply Prettier formatting to TS/JS/JSON/MD files
Add Prettier as a dev dependency with .prettierrc.json config and
.prettierignore. Hook added via mirrors-prettier in pre-commit config.
All TypeScript, JSON, Markdown, and YAML files auto-formatted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 13:05:50 +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