Commit Graph

457 Commits

Author SHA1 Message Date
Gavin Colonese
ab7a2101af feat: add export_gencad tool (kicad-cli, GenCAD assembly/test format)
New MCP tool `export_gencad` wrapping `kicad-cli pcb export gencad`:
exposes define-var plus the flip-bottom-pads, unique-pins,
unique-footprints, use-drill-origin and store-origin-coord flags.
Self-contained interface handler reading the saved .kicad_pcb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:55:26 -04:00
Gavin Colonese
cdaa1eb635 feat: add export_ipcd356 tool (kicad-cli, IPC-D-356 netlist)
New MCP tool `export_ipcd356` wrapping `kicad-cli pcb export ipcd356`:
generates an IPC-D-356 bare-board electrical-test netlist for flying-probe
and bed-of-nails testers. Minimal option set (outputPath + boardPath only,
matching the subcommand's --help). Self-contained interface handler reading
the saved .kicad_pcb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:55:02 -04:00
Gavin Colonese
0f07ccd593 feat: add export_odb tool (kicad-cli, ODB++ archive)
New MCP tool `export_odb` wrapping `kicad-cli pcb export odb`: precision,
compression mode (zip/tgz/none), and units. Single ODB++ job archive for
CAM/MES/assembly. Self-contained interface handler reading the saved
.kicad_pcb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:54:37 -04:00
Gavin Colonese
88226d567b feat: add export_ipc2581 tool (kicad-cli, with BOM column mapping)
New MCP tool `export_ipc2581` wrapping `kicad-cli pcb export ipc2581`:
precision, compression, standard version, units, and the five
--bom-col-* field mappings (internal id, mfg P/N, mfg, distributor P/N,
distributor) that control the BOM part data embedded in the IPC-2581
file — directly useful for MES/assembly imports that need a real
internal P/N rather than the description. Self-contained interface
handler reading the saved .kicad_pcb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:54:11 -04:00
Gavin Colonese
b37ca6a225 feat: add export_drill tool (kicad-cli, full drill option set)
New MCP tool `export_drill` wrapping `kicad-cli pcb export drill`:
format (excellon/gerber), drill origin, Excellon zero-suppression and
oval formats, units, mirror-Y, minimal header, separate PTH/NPTH files,
drill map generation + map format, and Gerber precision. Self-contained
interface handler reading the saved .kicad_pcb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:53:45 -04:00
Gavin Colonese
82e5de7aa9 feat: add export_gerbers tool (kicad-cli, full Plot option set)
New MCP tool `export_gerbers` wrapping `kicad-cli pcb export gerbers`,
exposing the complete Plot-dialog option surface that the existing
SWIG-based export_gerber lacks: layer + common-layer lists, X2 on/off,
netlist attributes, soldermask subtraction, aperture macros, the three
DNP fab-layer modes, refdes/value exclusion, border+title, drill-file
origin, coordinate precision (5/6), Protel vs KiCad extensions, and
--board-plot-params to reuse the board's stored plot settings.

Implemented as a self-contained interface handler (_handle_export_gerbers)
that resolves the board path (param or current board) and shells out to
kicad-cli, mirroring the _handle_export_netlist pattern — no dependence
on a live SWIG board, since the KiCad IPC API exposes no plot/export
endpoints. Reads the saved .kicad_pcb on disk.

Wiring: dispatch map + src/tools/export.ts registration + export
category in registry.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:53:19 -04:00
Gavin Colonese
2fb54802b6 chore: add fitz to mypy ignore_missing_imports overrides
PyMuPDF (`fitz`) has no type stubs, so mypy's import-not-found fails on
any edit to files importing it (commands/board/view.py,
kicad_interface.py). Same treatment as the existing pcbnew/kipy/PIL
entries. Needed so the export-tool commits on this branch pass the mypy
pre-commit hook independently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:51:29 -04:00
mixelpixx
8fd5c8c64e Merge pull request #228 from ravishivt/feat/batch-schematic-authoring
feat(schematic): batch component authoring + connection tools
2026-06-03 17:50:35 -04:00
Ravi
4a251b7343 feat(schematic): batch component authoring + connection tools
Adds batch authoring tools that collapse the dozens of round-trips needed to
stand up a schematic into a handful: batch_add_components,
batch_edit_schematic_components, replace_schematic_component,
batch_add_no_connects, batch_connect, and batch_add_and_connect (place a set of
parts and wire them in one call). These reuse the existing single-item handlers
internally, so behavior matches exactly.

- python/commands/schematic_batch.py: SchematicBatchCommands(iface)
- python/commands/schematic_text_utils.py: shared .kicad_sch text helpers
- src/tools/schematic-batch.ts + registry 'schematic_batch' category
- python/kicad_interface.py: import + instantiate + dispatch routes
- tests/test_schematic_batch.py: 13 unit tests

Note: schematic_text_utils.py is also shipped by the field-placement and
hierarchy PRs; if those merge first, drop the duplicate copy on rebase.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 17:49:04 -04:00
mixelpixx
a0bf45488b Merge pull request #227 from ravishivt/feat/autoplace-schematic-fields
feat(schematic): reposition and auto-place Ref/Value field labels
2026-06-03 17:47:18 -04:00
Ravi
7c385b993f feat(schematic): reposition and auto-place Ref/Value field labels
Adds field-placement tools:
- set_schematic_property_position / batch_set_schematic_property_positions:
  move a symbol's Reference/Value field labels
- autoplace_schematic_fields: place every symbol's fields clear of its body
  and nearby net labels (the #1 readability problem in generated schematics)
- check_schematic_layout: audit out-of-bounds / fields-in-body / duplicate
  labels (note: overlaps upstream find_overlapping_elements etc. — reuse or
  drop on request)

Generic .kicad_sch text helpers are factored into commands/schematic_text_utils.py
so the batch/hierarchy modules don't import from one another.

- python/commands/schematic_text_utils.py: shared text/S-expr helpers
- python/commands/schematic_field_layout.py: SchematicFieldLayoutCommands
- src/tools/schematic-layout.ts + registry 'schematic_layout' category
- python/kicad_interface.py: import + instantiate + dispatch routes
- tests/test_schematic_field_layout.py: 23 unit tests incl. end-to-end on real .kicad_sch

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 17:45:17 -04:00
mixelpixx
2dcfc0f4c2 Merge pull request #229 from ravishivt/feat/hierarchical-sheets
feat(schematic): hierarchical sheet insertion and subsheet scaffolding
2026-06-03 17:43:33 -04:00
Ravi
a9d7af5edf feat(schematic): hierarchical sheet insertion and subsheet scaffolding
Adds add_hierarchical_sheet (insert a sheet symbol referencing a child
.kicad_sch, with sheet_instances + fixed component instance paths) and
create_hierarchical_subsheet (create the child file + wire it into the parent
in one call). Upstream has add_sheet_pin / add_schematic_hierarchical_label
but no way to create a sheet or stand up a child sheet, so hierarchical
designs can't be built through the MCP server today.

- python/commands/schematic_hierarchy.py: SchematicHierarchyCommands
- src/tools/schematic-hierarchy.ts + registry 'schematic_hierarchy' category
- python/kicad_interface.py: import + instantiate + dispatch routes
- tests/test_schematic_hierarchy.py: 5 unit/integration tests on real .kicad_sch

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 17:41:12 -04:00
mixelpixx
df82ff5c56 Merge pull request #226 from ravishivt/feat/list-symbol-pins
feat(schematic): add list_symbol_pins to read pins from symbol libraries
2026-06-03 17:38:30 -04:00
mixelpixx
6fdbb65ce6 Merge pull request #212 from mixelpixx/fix/issue-209-kicad10-board-view
fix(board-view): KiCad 10 kicad-cli svg export compatibility (#209)
2026-06-03 17:34:13 -04:00
mixelpixx
02095088e1 Merge pull request #213 from mixelpixx/fix/issue-84-derive-pythonpath
fix(windows): derive PYTHONPATH from the detected KiCAD python (#84)
2026-06-03 17:31:47 -04:00
mixelpixx
ef963ac783 Merge pull request #218 from dubanoze/fix/symbol-library-empty-cache-rebuild
fix(library): rebuild SymbolLibraryManager when cache is empty
2026-06-03 17:30:50 -04:00
mixelpixx
f60f21aad2 Merge pull request #216 from stefanobaldo/fix/stdin-close-cleanup
fix(server): close Python backend and exit gracefully when stdin closes
2026-06-03 17:29:05 -04:00
mixelpixx
072b8f580e Merge pull request #219 from bhoot1234567890/fix/transport-before-warmup
fix: connect MCP transport before warm-up to prevent client timeout
2026-06-03 17:28:09 -04:00
Ravi
f5d7c0aaf4 feat(schematic): add list_symbol_pins to read pins from symbol libraries
Adds list_symbol_pins and batch_list_symbol_pins: read a symbol's pin
number/name/type/local-position straight from the .kicad_sym libraries,
without placing it on a schematic. Fills a gap in library_symbol.py
(which can search/list symbols and read properties but not pins) and
complements get_schematic_pin_locations (placed-symbol coords only).

- python/commands/symbol_pins.py: SymbolPinCommands (stateless)
- src/tools/library-symbol.ts: tool wrappers; registry 'symbol_pins' category
- python/kicad_interface.py: import + instantiate + dispatch routes
- tests/test_symbol_pins.py: 12 unit tests (MagicMock loader; no system KiCad)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 14:36:22 -07:00
Chaitanya Malhotra
3ecf5f38fd fix: connect MCP transport before warm-up to prevent client timeout
Swap Phase 3 (transport connect) before Phase 4 (warm-up) in
server.ts startup. Previously the transport was connected only after
warm-up completed (55-125s), which exceeded the MCP client's 30s
connection timeout on macOS cold-start.

PR #210 fixed the Python-side by daemon-threading warm_cache, but
the Node-side still blocked transport connect on warm-up completion.

Complements #210. Replaces the server.ts portion of #206.
2026-06-01 18:42:50 +05:30
Denis
f7a92c6eb2 fix(library): rebuild SymbolLibraryManager when cache is empty
When a project is opened for the first time (e.g. right after
create_project) the sym-lib-table may not exist on disk yet.
SymbolLibraryManager.__init__ succeeds but leaves self.libraries={}.

The original guard in use_project() was:

    if self.library_manager.project_path == project_path:
        return

Because the path already matched the newly-created manager, the
early-return fired and the manager was never rebuilt once the
sym-lib-table appeared.  All subsequent list_symbols / search calls
returned nothing.

Fix: also require that at least one library was loaded before
treating the cache as valid.

Adds three unit tests that cover:
- rebuild triggered when project_path matches but libraries={}
- no spurious rebuild when libraries are already loaded
- rebuild on project_path change (existing behaviour)
2026-06-01 18:12:36 +05:00
mixelpixx
3b4ffef724 Merge pull request #196 from gcolonese/feat-schematic-justify
feat(schematic): expose justify directive on field labels via MCP
2026-05-30 12:15:28 -04:00
mixelpixx
40cbea3870 Merge pull request #215 from mixelpixx/fix/issue-181-log-rotation
fix(logging): bound log size + honor LOG_LEVEL + mute kicad-skip (#181)
2026-05-30 12:11:17 -04:00
Stefano Baldo
c6395ed0b1 fix(server): close Python backend and exit when stdin closes 2026-05-30 13:08:24 -03:00
mixelpixx
f95de32cdd fix(logging): bound log size + honor LOG_LEVEL + mute kicad-skip (#181)
The server wrote gigabytes to ~/.kicad-mcp/logs and ignored LOG_LEVEL. Three
root causes, all fixed here (the logging carve-out of #182):

- Python (kicad_interface.py): replace the unbounded FileHandler with a
  RotatingFileHandler (10 MB x 3 backups, env-tunable via KICAD_MCP_LOG_MAX_BYTES
  / KICAD_MCP_LOG_BACKUP_COUNT); read the level from KICAD_MCP_LOG_LEVEL or
  LOG_LEVEL (default INFO) instead of hardcoding DEBUG; mute the noisy
  skip / skip.sexp.* loggers to WARNING unless KICAD_MCP_DEBUG_SKIP is set.
- TypeScript (config.ts): honor KICAD_MCP_LOG_LEVEL / LOG_LEVEL for the TS logger.
- TypeScript (logger.ts): size-cap the per-day log files with the same env knobs.
- Docs + a no-network test for the env helpers, skip muting, and that no
  unbounded handler targets kicad_interface.log.

Verified: LOG_LEVEL is now applied, skip is muted, and the file rotates instead
of growing forever. Full suite unchanged from baseline.

The hierarchical-sheet rewrite from #182 is intentionally left out (stays as a
separate PR pending the #169/#170 design discussion).

Co-Authored-By: angelorodem <angelorodem@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 12:07:03 -04:00
mixelpixx
df02627134 fix(windows): derive PYTHONPATH from the detected KiCAD python (#84)
findPythonExecutable already auto-detects KiCAD's bundled python across versions
(10.0/9.0/…) and both Program Files and per-user %LOCALAPPDATA% installs, but the
spawn still defaulted PYTHONPATH to a hardcoded "C:/Program Files/KiCad/9.0/..."
path. So a KiCad 10 or per-user user whose python.exe was found correctly still
got the wrong PYTHONPATH unless they set it by hand — the exact manual fixup
people keep posting in #84.

Add deriveKiCadSitePackages(pythonExe): for a detected KiCAD python at
<root>/<version>/bin/python.exe it returns the matching site-packages
(<...>/bin/Lib/site-packages, or the older lib/python3/dist-packages layout),
verified to exist. Use it as the PYTHONPATH default. Precedence is unchanged at
the top: explicit PYTHONPATH env override still wins; the legacy 9.0 string
remains only as a last-resort fallback, so this can't regress below current
behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:47:25 -04:00
mixelpixx
066e7f63d4 fix(board-view): KiCad 10 kicad-cli svg export compatibility (#209)
KiCad 10 changed `kicad-cli pcb export svg` in three ways that broke
get_board_2d_view (reported with a verified fix in #209):
  - `--output` is now a FILE path, not a directory (a dir fails with
    "Failed to create file '<dir>'").
  - `--mode-single` is required to merge layers into one SVG (the default
    multi-file behavior is deprecated).
  - exit code 2 is returned for the deprecation warning even on success.

Pass a file path to `--output` and add `--mode-single` (both also valid on
KiCad 8/9). Stop gating on the exit code — judge success by whether an SVG was
actually produced — so the exit-2 deprecation warning is no longer a false
failure. Add regression tests for the exit-2-is-success case and the command
shape (file output + --mode-single).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:42:20 -04:00
mixelpixx
5493a37024 Merge pull request #205 from romybompart/feat/opencode-backend-selection
feat: improve OpenCode KiCad setup and backend selection
2026-05-30 09:36:02 -04:00
mixelpixx
74a153aab4 Merge pull request #207 from karu2003/feat/schematic-mirrorY
feat(schematic): add angle and mirrorY to add_schematic_component
2026-05-30 09:34:45 -04:00
mixelpixx
40d32d187c Merge pull request #203 from jbjardine/cojbdev/kicad-mcp-lib-table-spaces
fix: parse quoted KiCad library table URIs with spaces
2026-05-30 09:33:09 -04:00
mixelpixx
034ffb79bd Merge pull request #204 from mixelpixx/fix/issue-199-jlcpcb-prebuilt-download
fix(jlcpcb): download prebuilt catalog instead of broken JLCSearch offset loop (#199)
2026-05-30 09:29:48 -04:00
mixelpixx
a18e729076 fix(jlcpcb): skip re-download when cache file already complete (#199, #204)
bhoot found that download_cdfer 416-loops when a complete cdfer.sqlite3 already
exists in the cache (e.g. a prior run downloaded it but died before
conversion/cleanup): resuming a complete file sends Range: bytes=<size>- which
the server answers with HTTP 416, and raise_for_status treated that as a
retryable error, spinning until max_retries then failing.

Fix: HEAD once for Content-Length up front and short-circuit when the local file
already matches the full size; and in the loop, treat a 416 as "complete" when
the size matches (else drop the stale partial and restart fresh). Remove the now
-unused _head_last_modified helper (HEAD is done inline). Add a no-network test.

Verified live: happy path still downloads+converts 616k parts (~50s); a
pre-existing complete file now short-circuits in ~0.4s instead of looping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:29:22 -04:00
mixelpixx
00618befb6 Merge pull request #211 from MoChahadeh/ref-based-tools-fix
Fix: reference-based schematic tools fail when lib_symbols contains a paren inside a quoted string
2026-05-30 08:56:27 -04:00
mixelpixx
adea0998d2 Merge pull request #210 from MoChahadeh/macos-connect-fix
Fix MCP tool launch timeout on macos / unable to connect
2026-05-30 08:52:07 -04:00
mixelpixx
4a61ad233d test(symbol-library): init _cache_lock in __new__-based fixture
The background warm-cache change made list_symbols() guard cache writes with
self._cache_lock. _manager_for_fixture() builds the manager via __new__ (to skip
disk I/O to system libs), bypassing __init__ where the lock is created, so the 8
SPICE-parsing tests raised AttributeError. Set the lock in the fixture. The
string-aware parser itself is correct — all 8 pass once the lock exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 08:51:46 -04:00
Mo Chahadeh
fdc760a73a Fix ref-based tools fail bug 2026-05-29 20:28:15 +03:00
Mo Chahadeh
36820d6897 Fix MCP tool launch timeout on macos / unable to connect 2026-05-29 14:10:22 +03:00
Gavin Colonese
7313037dc3 feat(schematic): expose justify directive on field labels via MCP
Add optional `justify` property to `fieldPositions` entries in
`edit_schematic_component` and to `set_schematic_component_property`.

Changes:
- `python/kicad_interface.py`: new `_set_justify_on_property()` helper
  that adds/replaces/removes the `(justify ...)` token inside a property's
  `(effects ...)` block. Passing "center" (the KiCad default) removes the
  directive entirely. Integrated into `_set_property_in_block()` (for the
  `properties` dict path) and into the `field_positions` loop in
  `_handle_edit_schematic_component()`. `_handle_set_schematic_component_property()`
  now forwards `justify` from params through to the spec dict.
  Also fixes pre-existing mypy type-ignore on `circle.radius` (kipy stub).
- `src/tools/schematic.ts`: extend the `fieldPositions` Zod schema to accept
  `justify?: string | string[]` (array form normalised to a space-separated
  string before the Python call). Add `justify?: string` to
  `set_schematic_component_property`.
- `python/commands/routing.py`: fix pre-existing mypy error — annotate `ex`
  and `ey` as `float` in `_point_to_segment_distance_nm`.
- `python/commands/pin_locator.py`: fix pre-existing mypy error — use explicit
  `str()` cast on `pin_data["number"]` before `dict.get()` call.
- `tests/test_schematic_field_justify.py`: 14 unit + integration tests
  covering add/replace/remove of the justify directive and backward
  compatibility (calls without justify leave existing directives untouched).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:29:00 -04:00
mixelpixx
d2ea43d061 Merge pull request #168 from jflaflamme/fix/board-view-kicad-cli
fix(board-view): use kicad-cli instead of pcbnew/cffi, return image to Claude
2026-05-27 22:51:14 -04:00
Jeff Laflamme
6c44273d55 fix(board-view): rebase onto main — fold responseMode + restore jpg
Rebased onto current main (d765bfe). Merged changes:

Board view (kicad-cli, cffi-free):
- Replace pcbnew/PLOT_CONTROLLER + cairosvg with kicad-cli SVG export
  and cffi-free PNG conversion: pymupdf → inkscape → imagemagick chain
- pcbPath optional param with fallback to loaded board
- Restore jpg output via PIL post-processing on PNG bytes
- responseMode inline/file from main's #161: inline returns imageData,
  file writes <board>_2d_view.<ext> and returns filePath
- shutil.which for cross-platform kicad-cli lookup
- Explicit TimeoutExpired catch; errorDetails on all error returns
- Validate fmt strictly; TypeScript returns image type for inline png/jpg

Schematic view (kicad_interface.py):
- Same cffi-free _svg_to_png helper for get_schematic_view and
  get_schematic_view_region (pymupdf → inkscape → imagemagick)

Tests:
- Update test_get_board_2d_view_save_to_file.py to mock subprocess/
  kicad-cli and _svg_to_png instead of PLOT_CONTROLLER/cairosvg
- All 5 responseMode tests pass
2026-05-27 10:50:21 +07:00
ka ru
2ced6764b0 fix: restore property-position regex for RefDes/Value placement
cacb27b omitted the closing parenthesis anchor in _extract_lib_property_positions, leaving lib_props empty and falling back to generic resistor positions.
2026-05-26 19:59:29 +02:00
ka ru
5a9790301e feat: add angle rotation and mirrorY horizontal flipping for components
- New angle parameter for component rotation (degrees, KiCad CCW-in-screen)
- New mirrorY parameter for horizontal symbol flipping (transistor orientation)
- Property positions (Reference, Value, Footprint) automatically rotated
- Property text effects preserved from library definitions
- Updates to add_schematic_component tool with new parameters
- Implements proper S-expression formatting for (mirror y) attribute
- Text angles and offsets derived from library properties for correct placement
2026-05-26 19:50:54 +02:00
romybompart
3f8068f5e4 feat: improve OpenCode KiCad setup and backend selection 2026-05-24 16:15:50 -04:00
mixelpixx
030d008843 feat(jlcpcb): make the FULL ~10GB catalog reachable + resumable downloads (#199)
People want to be able to pull the whole catalog, and prior downloads stalled or
repeated the same parts. Two fixes:

- Full catalog correctness: yaqwsx's cache.sqlite3 (the full ~10GB set) stores
  category/manufacturer as IDs with no v_components view, so the convert left
  those fields blank. Build an equivalent v_components join for yaqwsx-style
  sources so the full catalog converts with category/subcategory/manufacturer
  populated. Clarify in the tool schema that source="yaqwsx" = full catalog
  (needs 7z) vs cdfer = in-stock subset.
- Resumable downloads: CDFER stream download now uses a read timeout and resumes
  from the partial file via HTTP Range on interruption (up to 5 retries); the
  yaqwsx curl calls use -C - / --retry. Addresses the stall/partial-download
  complaints.

Adds a yaqwsx-schema conversion test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 13:57:07 -04:00
mixelpixx
cb5f744754 feat(jlcpcb): warn when downloaded catalog is stale (#199)
Per review feedback: CDFER's upstream scraper pipeline has stalled for weeks
(broken cart API + a bug in their scraper), so a "fresh download" can still be
old data. Compute the catalog age from the source Last-Modified header, expose
catalog_age_days, and emit a stale=True + warning when older than 14 days that
points users to source='yaqwsx' (fresh, needs 7z) or source='official'. Surface
the warning in the MCP tool output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 13:49:40 -04:00
mixelpixx
b21b1410eb fix(jlcpcb): download prebuilt catalog instead of broken JLCSearch offset loop (#199)
The download_jlcpcb_database tool paged the community JLCSearch API with an
offset parameter, but that endpoint is a search front-end that ignores offset
and returns the same first 100 parts on every page, so a full catalog download
was impossible.

Add commands/jlcpcb_downloader.py with a layered strategy that reuses prebuilt
catalogs the whole ecosystem already trusts:
  - CDFER single-file SQLite (primary; no 7z/zip, reliable on Windows)
  - yaqwsx/jlcparts split 7z (fallback; only if a 7z CLI is present)
  - official JLCPCB API (optional; cursor pagination, if credentials set)

Conversion reads CDFER's v_components view (or sniffs the largest table for
yaqwsx), C-prefixes integer lcsc, derives library_type from basic/preferred,
maps mfr->mfr_part, and normalizes price JSON to the manager's [{qty,price}]
shape. Rewire _handle_download_jlcpcb_database to use it (closing/reopening the
manager connection so the on-disk db can be rewritten on Windows). Remove the
broken offset loop from jlcsearch.py (client kept for interactive lookups).
Reduce download_jlcpcb.py to a thin CLI wrapper and update the TS tool schema.

Verified end-to-end against live CDFER: 616k parts downloaded + converted in
~40s, FTS search and price-break parsing correct. New unit tests cover the
conversion and source fall-through; no network in tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 11:53:12 -04:00
mixelpixx
d765bfec78 Merge pull request #202 from jbjardine/cojbdev/kicad-mcp-backend-state
Add backend state MCP tool
2026-05-24 08:51:34 -04:00
mixelpixx
88d81e77b1 Merge pull request #201 from jbjardine/cojbdev/kicad-mcp-error-payloads
Fix MCP error result for DRC failure payloads
2026-05-24 08:51:31 -04:00
jbjardine
458631b24c fix: parse quoted KiCad library table URIs with spaces 2026-05-24 12:34:47 +02:00