Commit Graph

12 Commits

Author SHA1 Message Date
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
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
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
Cabbache
d3ef768ad0 KiCAD 10 support 2026-03-21 23:18:30 +01:00
Tom
0688626781 fix: inject_symbol_into_lib_symbols handles sexpdata single-line compaction 2026-03-06 18:10:20 +01:00
Tom
93ae23dacc fix: prevent header corruption when sexpdata compacts schematic to single line
create_component_instance used line-based insertion which placed new
symbols BEFORE (kicad_sch ...) header when the file was written as
a single line by sexpdata.dumps(). Switch to rfind()-based string
insertion which is format-independent.

Also remove StreamHandler(sys.stdout) from logging — Python logs now
go only to file (~/.kicad-mcp/logs/kicad_interface.log) to avoid
polluting MCP stderr with INFO/DEBUG entries shown as [error].
2026-03-06 13:17:25 +01:00
Tom
2340afe9a4 fix(dynamic-loader): inline extends symbols for lib_symbols compatibility
KiCad 9 refuses to load any schematic whose lib_symbols section contains
an (extends ...) clause, because the extends mechanism is only valid
inside .kicad_sym library files - not inside schematics.

The previous implementation kept the (extends ...) clause and prepended
the parent symbol block with a qualified name, but left the child's
extends referring to the unqualified parent name, causing:
  'Error loading schematic: No parent for extended symbol Q_NMOS_GSD'

Fix: add _iter_top_level_items() and _inline_extends_symbol() helpers.
When a library symbol uses extends, the parent's content (pins, graphics,
sub-symbols) is now merged directly into the child definition:
- Parent properties are overridden by child property values
- Sub-symbol names are renamed from ParentName_X_Y to ChildName_X_Y
- The (extends ...) clause is removed entirely
- Only the fully-resolved child symbol is injected into lib_symbols

Affected symbols include Transistor_FET:2N7002, Transistor_BJT:*,
Regulator_Linear:*, Regulator_Switching:* and many others (~30% of the
KiCad standard library uses extends).

Fixes #52
2026-03-04 15:27:59 +01:00
Tom
b33d6e22fd fix: project-local library resolution + copy_routing_pattern geometric fallback + TypeScript tool
- fix: DynamicSymbolLoader reads project sym-lib-table before global dirs
  add_schematic_component now finds symbols from project-local .kicad_sym files
  project_path derived automatically from schematic file path

- fix: place_component reloads FootprintLibraryManager with project_path
  new boardPath parameter passed to place_component tool (TypeScript + Python)
  _handle_place_component wrapper recreates LibraryManager per project

- fix: copy_routing_pattern geometric fallback when pads have no nets
  primary filter: net-based (when pads are assigned to nets)
  fallback: bounding box of source footprint pads +5mm tolerance
  filterMethod field in response indicates which mode was used

- feat: register copy_routing_pattern as MCP tool in routing.ts
  sourceRefs, targetRefs, includeVias, traceWidth parameters

Live tested: ESP32 + 2x TMC2209 in Test3 project
  13 traces U2 routed, copy_routing_pattern copied all 13 to U3
  offset Y+30mm correct, 26 total traces verified
2026-03-01 15:03:52 +01:00
Tom
b1eb570183 fix: footprint param ignored, delete duplicates, add edit_schematic_component
Bug 1 - add_schematic_component: footprint parameter silently ignored
  The footprint value from MCP params was never passed through to
  DynamicSymbolLoader.add_component() / create_component_instance().
  Every placed symbol had an empty Footprint field regardless of input.
  Fix: added footprint: str='' to both functions, passed through all
  call sites, added footprint to schematic.ts tool schema.

Bug 2 - delete_schematic_component: only deleted first duplicate
  When a reference appeared multiple times (e.g. after a failed
  add attempt), only the first instance was removed due to break
  after first match. Fix: collect all matching blocks first, then
  delete back-to-front to preserve indices. Response now includes
  deleted_count.

New tool - edit_schematic_component
  Update footprint, value or reference of a placed symbol in-place.
  More efficient than delete+re-add: preserves position and UUID.
  Accepts: schematicPath, reference, footprint?, value?, newReference?

All 3 fixes verified by live tests on a real JLCPCB/KiCAD 9 project:
  - R_TEST1: footprint Resistor_SMD:R_0603_1608Metric written correctly
  - J1 duplicate: deleted_count=2 with single call
  - J2 edit: PinSocket footprint assigned in-place, no delete+add needed
  - PCB update (F8) confirmed: only components with footprint imported
2026-02-28 15:21:07 +01:00
FlowSync0
a69d288251 fix: Rewrite DynamicSymbolLoader to prevent schematic file corruption (#40)
Fixes Issue #26 - add_schematic_component corrupts .kicad_sch files

Complete rewrite of DynamicSymbolLoader to use text manipulation instead of sexpdata:
- Preserves KiCAD file formatting perfectly
- Correctly handles KiCAD 9 symbol naming conventions (library prefix for top-level, no prefix for sub-symbols)
- Resolves parent-child symbol dependencies with (extends)
- Adds symbol caching for performance
- Simplifies component addition workflow

Tested on KiCAD 9.0.7 with R, C, LED, ESP32, and transistor components.
Compatible with recent Windows fixes (UUID generation, IPC, JLCPCB).

Co-authored-by: FlowSync0 <249798311+FlowSync0@users.noreply.github.com>
2026-02-26 11:02:10 -05:00
KiCAD MCP Bot
62d97f1fa6 feat: Dynamic symbol loading - CORE FUNCTIONALITY WORKING! 🎉
**MAJOR BREAKTHROUGH:** Implemented dynamic symbol loading from KiCad library files!
This eliminates the 13-component limitation and enables access to ALL KiCad symbols.

**What Works (Phase A Complete):**
 Symbol extraction from .kicad_sym library files
 S-expression parsing and manipulation
 Dynamic injection of symbols into schematics
 Template instance creation for cloning
 Full end-to-end workflow tested successfully

**Test Results:**
- Loaded 5 symbols dynamically (R, C, LED, L, D) from Device.kicad_sym
- Injected symbol definitions into schematic's lib_symbols section
- Created template instances at offscreen positions
- Successfully cloned components from dynamic templates
- All operations work with kicad-skip library

**New File:**
- python/commands/dynamic_symbol_loader.py (400+ lines)
  - DynamicSymbolLoader class
  - find_kicad_symbol_libraries() - cross-platform library discovery
  - parse_library_file() - S-expression parsing with caching
  - extract_symbol_definition() - extract specific symbols
  - inject_symbol_into_schematic() - inject symbols into lib_symbols
  - create_template_instance() - create cloneable templates
  - load_symbol_dynamically() - complete workflow

**Modified:**
- python/commands/component_schematic.py
  - Added dynamic loader integration hooks
  - get_or_create_template() method for hybrid approach
  - Falls back to static templates gracefully

**How It Works:**
1. Parse .kicad_sym file with sexpdata library
2. Extract specific symbol definition (S-expression tree)
3. Inject into schematic's lib_symbols section
4. Create offscreen template instance (_TEMPLATE_Device_R)
5. kicad-skip can clone() the template to create components

**Benefits:**
- Access to ~10,000+ standard KiCad symbols
- No manual template maintenance required
- Works with ANY .kicad_sym library file
- Maintains static template fallback

**Next Steps (Integration):**
- Wire through MCP interface layer (has schematic path)
- Create add_schematic_component_dynamic MCP tool
- Add symbol search/discovery tools
- Cross-platform testing (Windows, macOS)

**Technical Notes:**
- Uses sexpdata library for S-expression manipulation
- Caches parsed libraries for performance
- Generates unique UUIDs for template instances
- Positions templates offscreen (y = -100 - offset)
- Preserves schematic structure and formatting

This is a MASSIVE step forward! The hardest part (S-expression manipulation
and template injection) is DONE and WORKING. 🚀

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-10 10:10:57 -05:00