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>
This commit is contained in:
Eugene Mikhantyev
2026-03-29 13:05:50 +01:00
parent c44bd9205d
commit 7d50fa1d4c
82 changed files with 18314 additions and 17317 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,485 +1,509 @@
# Option 2: Dynamic Library Loading Plan
## Executive Summary
Replace the template-based schematic workflow with dynamic symbol loading from KiCad's installed symbol libraries. This would eliminate the 13-component limitation and provide access to ALL KiCad symbols (~10,000+ symbols from standard libraries).
**Current Status (Option 1):**
- ✅ Template-based approach working
-13 component types supported
- ❌ Limited symbol variety
-Requires manual template updates for new types
**Proposed (Option 2):**
- 🎯 Dynamic loading from `.kicad_sym` library files
- 🎯 Access to ~10,000+ KiCad symbols
- 🎯 No template maintenance required
- 🎯 User can specify any library/symbol combination
---
## Problem Analysis
### kicad-skip Library Limitation
**Core Issue:** kicad-skip **cannot create symbols from scratch**. It can only:
1. Clone existing symbols from a loaded schematic
2. Modify properties of cloned symbols
**Current Workaround:** Pre-load template symbols in schematic file
**Proposed Solution:** Load symbols from KiCad's `.kicad_sym` library files, inject them into the schematic's `lib_symbols` section, then clone from there.
---
## KiCad Symbol Library Architecture
### Symbol Library File Format (`.kicad_sym`)
KiCad symbol libraries are S-expression files containing symbol definitions:
```lisp
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
(symbol "Device:R"
(pin_numbers hide)
(pin_names (offset 0))
(in_bom yes)
(on_board yes)
(property "Reference" "R" ...)
(property "Value" "R" ...)
;; Graphics definitions
(symbol "R_0_1" ...)
(symbol "R_1_1"
(pin passive line ...)
)
)
(symbol "Device:C" ...)
(symbol "Device:L" ...)
;; ... thousands more
)
```
### Standard KiCad Library Locations
**Linux:**
- System libraries: `/usr/share/kicad/symbols/`
- User libraries: `~/.local/share/kicad/8.0/symbols/` or `~/.config/kicad/8.0/symbols/`
**Windows:**
- System libraries: `C:\Program Files\KiCad\9.0\share\kicad\symbols\`
- User libraries: `%APPDATA%\kicad\8.0\symbols\`
**macOS:**
- System libraries: `/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols/`
- User libraries: `~/Library/Preferences/kicad/8.0/symbols/`
### Standard Library Files
Common libraries (each containing 50-500 symbols):
- `Device.kicad_sym` - Passives (R, C, L, D, LED, Crystal, etc.)
- `Connector.kicad_sym` - Connectors (headers, USB, etc.)
- `Connector_Generic.kicad_sym` - Generic connectors
- `Transistor_BJT.kicad_sym` - Bipolar transistors
- `Transistor_FET.kicad_sym` - MOSFETs
- `Amplifier_Operational.kicad_sym` - Op-amps
- `Regulator_Linear.kicad_sym` - Voltage regulators
- `MCU_*.kicad_sym` - Microcontrollers
- `Interface_*.kicad_sym` - Interface ICs
- ... 100+ more libraries
---
## Implementation Strategy
### Phase 1: Library Discovery & Indexing
**Goal:** Build an index of all available symbols and their locations
**Implementation:**
```python
class SymbolLibraryManager:
def __init__(self):
self.library_paths = []
self.symbol_index = {} # {"Device:R": "/path/to/Device.kicad_sym", ...}
def discover_libraries(self):
"""Find all KiCad symbol libraries on the system"""
search_paths = [
"/usr/share/kicad/symbols/",
os.path.expanduser("~/.local/share/kicad/8.0/symbols/"),
os.path.expanduser("~/.config/kicad/8.0/symbols/"),
]
for search_path in search_paths:
if os.path.exists(search_path):
for lib_file in os.listdir(search_path):
if lib_file.endswith('.kicad_sym'):
self.library_paths.append(os.path.join(search_path, lib_file))
def index_symbols(self):
"""Parse all libraries and build symbol index"""
for lib_path in self.library_paths:
lib_name = os.path.basename(lib_path).replace('.kicad_sym', '')
symbols = self._parse_library(lib_path)
for symbol_name in symbols:
full_name = f"{lib_name}:{symbol_name}"
self.symbol_index[full_name] = {
'library': lib_name,
'library_path': lib_path,
'symbol_name': symbol_name
}
def _parse_library(self, lib_path):
"""Parse .kicad_sym file and extract symbol names"""
# Use sexpdata (already a dependency of kicad-skip)
import sexpdata
with open(lib_path, 'r') as f:
data = sexpdata.load(f)
symbols = []
for item in data[2:]: # Skip header
if isinstance(item, list) and item[0] == Symbol('symbol'):
symbol_name = item[1] # e.g., "Device:R"
# Extract just the symbol part after ':'
if ':' in symbol_name:
symbol_name = symbol_name.split(':')[1]
symbols.append(symbol_name)
return symbols
```
### Phase 2: Dynamic Symbol Injection
**Goal:** Load symbol definition from library file and inject into schematic
**Challenge:** kicad-skip works with loaded schematics, but we need to dynamically add symbols to the `lib_symbols` section.
**Solution:** Modify the schematic's S-expression data directly before loading with kicad-skip:
```python
def inject_symbol_into_schematic(schematic_path, library_path, symbol_name):
"""
1. Read schematic S-expression
2. Read library S-expression
3. Extract symbol definition from library
4. Inject into schematic's lib_symbols section
5. Save modified schematic
6. Reload with kicad-skip
"""
import sexpdata
# Load schematic
with open(schematic_path, 'r') as f:
sch_data = sexpdata.load(f)
# Load library
with open(library_path, 'r') as f:
lib_data = sexpdata.load(f)
# Find symbol definition in library
symbol_def = None
for item in lib_data[2:]:
if isinstance(item, list) and item[0] == Symbol('symbol'):
if symbol_name in str(item[1]):
symbol_def = item
break
if not symbol_def:
raise ValueError(f"Symbol {symbol_name} not found in {library_path}")
# Find lib_symbols section in schematic
lib_symbols_index = None
for i, item in enumerate(sch_data):
if isinstance(item, list) and item[0] == Symbol('lib_symbols'):
lib_symbols_index = i
break
# Inject symbol definition
if lib_symbols_index:
sch_data[lib_symbols_index].append(symbol_def)
# Save modified schematic
with open(schematic_path, 'w') as f:
sexpdata.dump(sch_data, f)
# Reload with kicad-skip
return Schematic(schematic_path)
```
### Phase 3: Template Instance Creation
**Goal:** Create offscreen template instances that can be cloned
**After injection:** Symbol definition is in `lib_symbols`, but we need an instance to clone from:
```python
def create_template_instance(schematic, library_name, symbol_name):
"""
Create an offscreen template instance that can be cloned
Similar to our current _TEMPLATE_R approach
"""
# This requires directly manipulating the S-expression
# Add a symbol instance at offscreen position with special reference
template_ref = f"_TEMPLATE_{library_name}_{symbol_name}"
# Create symbol instance (S-expression)
symbol_instance = [
Symbol('symbol'),
[Symbol('lib_id'), f"{library_name}:{symbol_name}"],
[Symbol('at'), -100, -100 - (len(schematic.symbol) * 10), 0],
[Symbol('unit'), 1],
[Symbol('in_bom'), Symbol('no')],
[Symbol('on_board'), Symbol('no')],
[Symbol('dnp'), Symbol('yes')],
[Symbol('uuid'), str(uuid.uuid4())],
[Symbol('property'), "Reference", template_ref, ...],
# ... more properties
]
# Inject into schematic and reload
# ... (similar to inject_symbol_into_schematic)
return template_ref
```
### Phase 4: User-Facing API
**Goal:** Simple interface for users to add any KiCad symbol
**New MCP Tool: `add_schematic_component_dynamic`**
```python
def add_schematic_component_dynamic(params):
"""
Add component by library:symbol notation
Example:
{
"library": "Device",
"symbol": "R",
"reference": "R1",
"value": "10k",
"x": 100,
"y": 100
}
OR using full notation:
{
"lib_symbol": "Device:R", # Full notation
"reference": "R1",
...
}
"""
lib_symbol = params.get('lib_symbol') or f"{params['library']}:{params['symbol']}"
# 1. Check if symbol is already in schematic's lib_symbols
# 2. If not, inject it from library file
# 3. Create template instance if needed
# 4. Clone template and set properties
return {"success": True, "reference": params['reference']}
```
---
## Advantages Over Template Approach
### ✅ Unlimited Symbol Access
- Access to ~10,000+ standard KiCad symbols
- Support for custom user libraries
- Support for 3rd-party libraries (JLCPCB, Espressif, etc.)
### ✅ No Maintenance Required
- Template doesn't need updates for new component types
- Automatically supports new KiCad library additions
- Works with custom symbol libraries
### ✅ Better User Experience
```
User: "Add an STM32F103C8T6 microcontroller at position 100,100"
AI: *Searches symbol index*
*Finds MCU_ST_STM32F1:STM32F103C8Tx*
*Loads from library*
*Injects into schematic*
*Places component*
✓ Done!
```
### ✅ Flexible Symbol Search
```python
# Find all resistors
symbols = lib_manager.search_symbols(query="resistor")
# Returns: ["Device:R", "Device:R_Small", "Device:R_Network", ...]
# Find all STM32 MCUs
symbols = lib_manager.search_symbols(query="STM32", library="MCU_ST_STM32F1")
```
---
## Challenges & Mitigations
### Challenge 1: S-expression Manipulation Complexity
**Problem:** Directly manipulating S-expression data is error-prone
**Mitigation:**
- Use `sexpdata` library (already a dependency)
- Create helper functions for common operations
- Add comprehensive validation and error handling
- Extensive testing with various symbol types
### Challenge 2: Performance
**Problem:** Loading/reloading schematics after injection could be slow
**Mitigation:**
- **Cache loaded symbols**: Once injected, symbol stays in schematic
- **Batch injection**: Inject multiple symbols at once
- **Lazy loading**: Only inject symbols when first used
### Challenge 3: Symbol Compatibility
**Problem:** Some symbols may have complex pin configurations or multiple units
**Mitigation:**
- Start with simple 2-pin passives (R, C, L)
- Gradually add support for multi-pin ICs
- Handle multi-unit symbols (gates, OpAmp sections) explicitly
- Document supported symbol types
### Challenge 4: Library Version Compatibility
**Problem:** KiCad symbol format may change between versions
**Mitigation:**
- Parse KiCad version from library files
- Version-specific handling if needed
- Fallback to template approach for unsupported formats
---
## Implementation Phases
### Phase A: Proof of Concept (1-2 weeks)
- [ ] Create `SymbolLibraryManager` class
- [ ] Implement library discovery (Linux paths only)
- [ ] Implement symbol indexing
- [ ] Test with Device.kicad_sym (R, C, L)
- [ ] Implement basic S-expression injection
- [ ] Test end-to-end with simple components
### Phase B: Core Functionality (2-3 weeks)
- [ ] Cross-platform library discovery (Windows, macOS)
- [ ] Symbol search functionality
- [ ] Template instance creation automation
- [ ] Multi-pin component support
- [ ] Error handling and validation
- [ ] Unit tests for all operations
### Phase C: MCP Integration (1 week)
- [ ] Create `add_schematic_component_dynamic` tool
- [ ] Update `search_symbols` to use library index
- [ ] Add `list_available_symbols` tool
- [ ] Add `list_symbol_libraries` tool
- [ ] Documentation and examples
### Phase D: Advanced Features (2-3 weeks)
- [ ] Multi-unit symbol support (e.g., quad OpAmps)
- [ ] Custom library registration
- [ ] Symbol caching and optimization
- [ ] 3rd-party library support (JLCPCB, etc.)
- [ ] Symbol preview generation
---
## Migration Strategy
### Backward Compatibility
Keep template-based approach as fallback:
```python
def add_schematic_component(params):
"""Smart component addition with fallback"""
# Try dynamic loading first
try:
if 'library' in params or 'lib_symbol' in params:
return add_schematic_component_dynamic(params)
except Exception as e:
logger.warning(f"Dynamic loading failed: {e}, falling back to template")
# Fallback to template-based
return add_schematic_component_template(params)
```
### Gradual Rollout
1. **Week 1-2:** Implement basic dynamic loading
2. **Week 3-4:** Test with power users, gather feedback
3. **Week 5-6:** Make dynamic loading the default
4. **Week 7+:** Deprecate template-only approach (keep as fallback)
---
## Success Criteria
### Must Have
- [ ] Load symbols from Device.kicad_sym (passives)
- [ ] Support R, C, L, D, LED (5 core types)
- [ ] Cross-platform library discovery
- [ ] Proper error handling
### Should Have
- [ ] Support for all Device.kicad_sym symbols (~50 symbols)
- [ ] Support for Connector.kicad_sym symbols
- [ ] Symbol search by name/keyword
- [ ] Performance: < 1 second per symbol injection
### Nice to Have
- [ ] Support for all standard libraries (~10,000 symbols)
- [ ] Multi-unit symbol support
- [ ] Custom library registration
- [ ] Symbol preview/documentation
---
## Risk Assessment
| Risk | Probability | Impact | Mitigation |
|------|-------------|--------|------------|
| S-expression parsing complexity | High | High | Use proven `sexpdata` library, extensive testing |
| Performance degradation | Medium | Medium | Implement caching, lazy loading |
| KiCad version incompatibility | Low | High | Version detection, format validation |
| Template fallback breaks | Low | Medium | Maintain template approach in parallel |
| User confusion | Medium | Low | Clear documentation, gradual rollout |
---
## Conclusion
Dynamic library loading is **feasible and highly beneficial** for the schematic workflow. While the template-based approach (Option 1) provides immediate value with 13 component types, Option 2 would:
1. **Eliminate the 13-component limitation**
2. **Provide access to 10,000+ KiCad symbols**
3. **Remove manual template maintenance**
4. **Enable true "natural language PCB design"**
**Recommendation:**
- **Keep Option 1 (expanded template) for immediate use**
- **Implement Option 2 (dynamic loading) over 6-8 weeks**
- **Maintain template fallback for compatibility**
This gives users immediate value while we build the robust long-term solution.
---
## References
- [KiCad File Formats Documentation](https://dev-docs.kicad.org/en/file-formats/)
- [kicad-skip GitHub](https://github.com/mvnmgrx/kicad-skip)
- [sexpdata Python Library](https://github.com/jd-boyd/sexpdata)
- [KiCad Symbol Library Format Spec](https://dev-docs.kicad.org/en/file-formats/sexpr-intro/)
# Option 2: Dynamic Library Loading Plan
## Executive Summary
Replace the template-based schematic workflow with dynamic symbol loading from KiCad's installed symbol libraries. This would eliminate the 13-component limitation and provide access to ALL KiCad symbols (~10,000+ symbols from standard libraries).
**Current Status (Option 1):**
-Template-based approach working
- ✅ 13 component types supported
-Limited symbol variety
- ❌ Requires manual template updates for new types
**Proposed (Option 2):**
- 🎯 Dynamic loading from `.kicad_sym` library files
- 🎯 Access to ~10,000+ KiCad symbols
- 🎯 No template maintenance required
- 🎯 User can specify any library/symbol combination
---
## Problem Analysis
### kicad-skip Library Limitation
**Core Issue:** kicad-skip **cannot create symbols from scratch**. It can only:
1. Clone existing symbols from a loaded schematic
2. Modify properties of cloned symbols
**Current Workaround:** Pre-load template symbols in schematic file
**Proposed Solution:** Load symbols from KiCad's `.kicad_sym` library files, inject them into the schematic's `lib_symbols` section, then clone from there.
---
## KiCad Symbol Library Architecture
### Symbol Library File Format (`.kicad_sym`)
KiCad symbol libraries are S-expression files containing symbol definitions:
```lisp
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
(symbol "Device:R"
(pin_numbers hide)
(pin_names (offset 0))
(in_bom yes)
(on_board yes)
(property "Reference" "R" ...)
(property "Value" "R" ...)
;; Graphics definitions
(symbol "R_0_1" ...)
(symbol "R_1_1"
(pin passive line ...)
)
)
(symbol "Device:C" ...)
(symbol "Device:L" ...)
;; ... thousands more
)
```
### Standard KiCad Library Locations
**Linux:**
- System libraries: `/usr/share/kicad/symbols/`
- User libraries: `~/.local/share/kicad/8.0/symbols/` or `~/.config/kicad/8.0/symbols/`
**Windows:**
- System libraries: `C:\Program Files\KiCad\9.0\share\kicad\symbols\`
- User libraries: `%APPDATA%\kicad\8.0\symbols\`
**macOS:**
- System libraries: `/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols/`
- User libraries: `~/Library/Preferences/kicad/8.0/symbols/`
### Standard Library Files
Common libraries (each containing 50-500 symbols):
- `Device.kicad_sym` - Passives (R, C, L, D, LED, Crystal, etc.)
- `Connector.kicad_sym` - Connectors (headers, USB, etc.)
- `Connector_Generic.kicad_sym` - Generic connectors
- `Transistor_BJT.kicad_sym` - Bipolar transistors
- `Transistor_FET.kicad_sym` - MOSFETs
- `Amplifier_Operational.kicad_sym` - Op-amps
- `Regulator_Linear.kicad_sym` - Voltage regulators
- `MCU_*.kicad_sym` - Microcontrollers
- `Interface_*.kicad_sym` - Interface ICs
- ... 100+ more libraries
---
## Implementation Strategy
### Phase 1: Library Discovery & Indexing
**Goal:** Build an index of all available symbols and their locations
**Implementation:**
```python
class SymbolLibraryManager:
def __init__(self):
self.library_paths = []
self.symbol_index = {} # {"Device:R": "/path/to/Device.kicad_sym", ...}
def discover_libraries(self):
"""Find all KiCad symbol libraries on the system"""
search_paths = [
"/usr/share/kicad/symbols/",
os.path.expanduser("~/.local/share/kicad/8.0/symbols/"),
os.path.expanduser("~/.config/kicad/8.0/symbols/"),
]
for search_path in search_paths:
if os.path.exists(search_path):
for lib_file in os.listdir(search_path):
if lib_file.endswith('.kicad_sym'):
self.library_paths.append(os.path.join(search_path, lib_file))
def index_symbols(self):
"""Parse all libraries and build symbol index"""
for lib_path in self.library_paths:
lib_name = os.path.basename(lib_path).replace('.kicad_sym', '')
symbols = self._parse_library(lib_path)
for symbol_name in symbols:
full_name = f"{lib_name}:{symbol_name}"
self.symbol_index[full_name] = {
'library': lib_name,
'library_path': lib_path,
'symbol_name': symbol_name
}
def _parse_library(self, lib_path):
"""Parse .kicad_sym file and extract symbol names"""
# Use sexpdata (already a dependency of kicad-skip)
import sexpdata
with open(lib_path, 'r') as f:
data = sexpdata.load(f)
symbols = []
for item in data[2:]: # Skip header
if isinstance(item, list) and item[0] == Symbol('symbol'):
symbol_name = item[1] # e.g., "Device:R"
# Extract just the symbol part after ':'
if ':' in symbol_name:
symbol_name = symbol_name.split(':')[1]
symbols.append(symbol_name)
return symbols
```
### Phase 2: Dynamic Symbol Injection
**Goal:** Load symbol definition from library file and inject into schematic
**Challenge:** kicad-skip works with loaded schematics, but we need to dynamically add symbols to the `lib_symbols` section.
**Solution:** Modify the schematic's S-expression data directly before loading with kicad-skip:
```python
def inject_symbol_into_schematic(schematic_path, library_path, symbol_name):
"""
1. Read schematic S-expression
2. Read library S-expression
3. Extract symbol definition from library
4. Inject into schematic's lib_symbols section
5. Save modified schematic
6. Reload with kicad-skip
"""
import sexpdata
# Load schematic
with open(schematic_path, 'r') as f:
sch_data = sexpdata.load(f)
# Load library
with open(library_path, 'r') as f:
lib_data = sexpdata.load(f)
# Find symbol definition in library
symbol_def = None
for item in lib_data[2:]:
if isinstance(item, list) and item[0] == Symbol('symbol'):
if symbol_name in str(item[1]):
symbol_def = item
break
if not symbol_def:
raise ValueError(f"Symbol {symbol_name} not found in {library_path}")
# Find lib_symbols section in schematic
lib_symbols_index = None
for i, item in enumerate(sch_data):
if isinstance(item, list) and item[0] == Symbol('lib_symbols'):
lib_symbols_index = i
break
# Inject symbol definition
if lib_symbols_index:
sch_data[lib_symbols_index].append(symbol_def)
# Save modified schematic
with open(schematic_path, 'w') as f:
sexpdata.dump(sch_data, f)
# Reload with kicad-skip
return Schematic(schematic_path)
```
### Phase 3: Template Instance Creation
**Goal:** Create offscreen template instances that can be cloned
**After injection:** Symbol definition is in `lib_symbols`, but we need an instance to clone from:
```python
def create_template_instance(schematic, library_name, symbol_name):
"""
Create an offscreen template instance that can be cloned
Similar to our current _TEMPLATE_R approach
"""
# This requires directly manipulating the S-expression
# Add a symbol instance at offscreen position with special reference
template_ref = f"_TEMPLATE_{library_name}_{symbol_name}"
# Create symbol instance (S-expression)
symbol_instance = [
Symbol('symbol'),
[Symbol('lib_id'), f"{library_name}:{symbol_name}"],
[Symbol('at'), -100, -100 - (len(schematic.symbol) * 10), 0],
[Symbol('unit'), 1],
[Symbol('in_bom'), Symbol('no')],
[Symbol('on_board'), Symbol('no')],
[Symbol('dnp'), Symbol('yes')],
[Symbol('uuid'), str(uuid.uuid4())],
[Symbol('property'), "Reference", template_ref, ...],
# ... more properties
]
# Inject into schematic and reload
# ... (similar to inject_symbol_into_schematic)
return template_ref
```
### Phase 4: User-Facing API
**Goal:** Simple interface for users to add any KiCad symbol
**New MCP Tool: `add_schematic_component_dynamic`**
```python
def add_schematic_component_dynamic(params):
"""
Add component by library:symbol notation
Example:
{
"library": "Device",
"symbol": "R",
"reference": "R1",
"value": "10k",
"x": 100,
"y": 100
}
OR using full notation:
{
"lib_symbol": "Device:R", # Full notation
"reference": "R1",
...
}
"""
lib_symbol = params.get('lib_symbol') or f"{params['library']}:{params['symbol']}"
# 1. Check if symbol is already in schematic's lib_symbols
# 2. If not, inject it from library file
# 3. Create template instance if needed
# 4. Clone template and set properties
return {"success": True, "reference": params['reference']}
```
---
## Advantages Over Template Approach
### ✅ Unlimited Symbol Access
- Access to ~10,000+ standard KiCad symbols
- Support for custom user libraries
- Support for 3rd-party libraries (JLCPCB, Espressif, etc.)
### ✅ No Maintenance Required
- Template doesn't need updates for new component types
- Automatically supports new KiCad library additions
- Works with custom symbol libraries
### ✅ Better User Experience
```
User: "Add an STM32F103C8T6 microcontroller at position 100,100"
AI: *Searches symbol index*
*Finds MCU_ST_STM32F1:STM32F103C8Tx*
*Loads from library*
*Injects into schematic*
*Places component*
✓ Done!
```
### ✅ Flexible Symbol Search
```python
# Find all resistors
symbols = lib_manager.search_symbols(query="resistor")
# Returns: ["Device:R", "Device:R_Small", "Device:R_Network", ...]
# Find all STM32 MCUs
symbols = lib_manager.search_symbols(query="STM32", library="MCU_ST_STM32F1")
```
---
## Challenges & Mitigations
### Challenge 1: S-expression Manipulation Complexity
**Problem:** Directly manipulating S-expression data is error-prone
**Mitigation:**
- Use `sexpdata` library (already a dependency)
- Create helper functions for common operations
- Add comprehensive validation and error handling
- Extensive testing with various symbol types
### Challenge 2: Performance
**Problem:** Loading/reloading schematics after injection could be slow
**Mitigation:**
- **Cache loaded symbols**: Once injected, symbol stays in schematic
- **Batch injection**: Inject multiple symbols at once
- **Lazy loading**: Only inject symbols when first used
### Challenge 3: Symbol Compatibility
**Problem:** Some symbols may have complex pin configurations or multiple units
**Mitigation:**
- Start with simple 2-pin passives (R, C, L)
- Gradually add support for multi-pin ICs
- Handle multi-unit symbols (gates, OpAmp sections) explicitly
- Document supported symbol types
### Challenge 4: Library Version Compatibility
**Problem:** KiCad symbol format may change between versions
**Mitigation:**
- Parse KiCad version from library files
- Version-specific handling if needed
- Fallback to template approach for unsupported formats
---
## Implementation Phases
### Phase A: Proof of Concept (1-2 weeks)
- [ ] Create `SymbolLibraryManager` class
- [ ] Implement library discovery (Linux paths only)
- [ ] Implement symbol indexing
- [ ] Test with Device.kicad_sym (R, C, L)
- [ ] Implement basic S-expression injection
- [ ] Test end-to-end with simple components
### Phase B: Core Functionality (2-3 weeks)
- [ ] Cross-platform library discovery (Windows, macOS)
- [ ] Symbol search functionality
- [ ] Template instance creation automation
- [ ] Multi-pin component support
- [ ] Error handling and validation
- [ ] Unit tests for all operations
### Phase C: MCP Integration (1 week)
- [ ] Create `add_schematic_component_dynamic` tool
- [ ] Update `search_symbols` to use library index
- [ ] Add `list_available_symbols` tool
- [ ] Add `list_symbol_libraries` tool
- [ ] Documentation and examples
### Phase D: Advanced Features (2-3 weeks)
- [ ] Multi-unit symbol support (e.g., quad OpAmps)
- [ ] Custom library registration
- [ ] Symbol caching and optimization
- [ ] 3rd-party library support (JLCPCB, etc.)
- [ ] Symbol preview generation
---
## Migration Strategy
### Backward Compatibility
Keep template-based approach as fallback:
```python
def add_schematic_component(params):
"""Smart component addition with fallback"""
# Try dynamic loading first
try:
if 'library' in params or 'lib_symbol' in params:
return add_schematic_component_dynamic(params)
except Exception as e:
logger.warning(f"Dynamic loading failed: {e}, falling back to template")
# Fallback to template-based
return add_schematic_component_template(params)
```
### Gradual Rollout
1. **Week 1-2:** Implement basic dynamic loading
2. **Week 3-4:** Test with power users, gather feedback
3. **Week 5-6:** Make dynamic loading the default
4. **Week 7+:** Deprecate template-only approach (keep as fallback)
---
## Success Criteria
### Must Have
- [ ] Load symbols from Device.kicad_sym (passives)
- [ ] Support R, C, L, D, LED (5 core types)
- [ ] Cross-platform library discovery
- [ ] Proper error handling
### Should Have
- [ ] Support for all Device.kicad_sym symbols (~50 symbols)
- [ ] Support for Connector.kicad_sym symbols
- [ ] Symbol search by name/keyword
- [ ] Performance: < 1 second per symbol injection
### Nice to Have
- [ ] Support for all standard libraries (~10,000 symbols)
- [ ] Multi-unit symbol support
- [ ] Custom library registration
- [ ] Symbol preview/documentation
---
## Risk Assessment
| Risk | Probability | Impact | Mitigation |
| ------------------------------- | ----------- | ------ | ------------------------------------------------ |
| S-expression parsing complexity | High | High | Use proven `sexpdata` library, extensive testing |
| Performance degradation | Medium | Medium | Implement caching, lazy loading |
| KiCad version incompatibility | Low | High | Version detection, format validation |
| Template fallback breaks | Low | Medium | Maintain template approach in parallel |
| User confusion | Medium | Low | Clear documentation, gradual rollout |
---
## Conclusion
Dynamic library loading is **feasible and highly beneficial** for the schematic workflow. While the template-based approach (Option 1) provides immediate value with 13 component types, Option 2 would:
1. **Eliminate the 13-component limitation**
2. **Provide access to 10,000+ KiCad symbols**
3. **Remove manual template maintenance**
4. **Enable true "natural language PCB design"**
**Recommendation:**
- **Keep Option 1 (expanded template) for immediate use**
- **Implement Option 2 (dynamic loading) over 6-8 weeks**
- **Maintain template fallback for compatibility**
This gives users immediate value while we build the robust long-term solution.
---
## References
- [KiCad File Formats Documentation](https://dev-docs.kicad.org/en/file-formats/)
- [kicad-skip GitHub](https://github.com/mvnmgrx/kicad-skip)
- [sexpdata Python Library](https://github.com/jd-boyd/sexpdata)
- [KiCad Symbol Library Format Spec](https://dev-docs.kicad.org/en/file-formats/sexpr-intro/)

View File

@@ -1,390 +1,413 @@
# Dynamic Symbol Loading - Implementation Status
**Date:** 2026-01-10
**Status:** Phase A-C - ✅ **COMPLETE AND PRODUCTION-READY!**
## 🚀 BREAKTHROUGH: Full MCP Integration Complete!
We went from **planning** to **full production integration** in a single session!
**Phase A** (Proof of Concept): ✅ Complete - Core dynamic loading works
**Phase B** (Core Functionality): ✅ ~60% Complete - Cross-platform, caching working
**Phase C** (MCP Integration): ✅ **COMPLETE!** - Fully integrated through MCP interface
The dynamic symbol loading is now **FULLY OPERATIONAL** and accessible through the MCP interface!
---
## What's Working (Core Functionality)
### ✅ Symbol Extraction
- Parse `.kicad_sym` library files using S-expression parser
- Extract specific symbol definitions by name
- Cache parsed libraries for performance
- Tested with Device.kicad_sym (533 symbols)
### ✅ S-Expression Manipulation
- Load schematic files as S-expression trees
- Inject symbol definitions into `lib_symbols` section
- Preserve schematic structure and formatting
- Write modified schematics back to disk
### ✅ Template Instance Creation
- Create offscreen template instances at negative Y coordinates
- Generate unique UUIDs for each template
- Set proper properties (Reference, Value, Footprint, Datasheet)
- Templates marked as: `in_bom: no`, `on_board: no`, `dnp: yes`
### ✅ Component Cloning
- kicad-skip successfully clones from dynamic templates
- Components inherit symbol structure from injected definitions
- Properties can be modified after cloning
- Full integration with existing ComponentManager
### ✅ Cross-Platform Library Discovery
- Linux: `/usr/share/kicad/symbols`, `~/.local/share/kicad/*/symbols`
- Windows: `C:/Program Files/KiCad/*/share/kicad/symbols`
- macOS: `/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols`
- Environment variable support: `KICAD9_SYMBOL_DIR`, etc.
---
## Test Results
### End-to-End Test (Successful)
**Test:** Load 5 symbols dynamically and create components
```python
Symbols Tested:
- Device:R Injected, template created, cloned successfully
- Device:C Injected, template created, cloned successfully
- Device:LED Injected, template created, cloned successfully
- Device:L Injected, template created, cloned successfully
- Device:D Injected, template created, cloned successfully
Results:
All 5 symbols extracted from Device.kicad_sym
All 5 symbol definitions injected into schematic
All 5 template instances created
kicad-skip loaded modified schematic without errors
Components successfully cloned from dynamic templates
```
### Performance Metrics
- **Library parsing:** ~0.3s for Device.kicad_sym (first time)
- **Library parsing:** ~0.001s (cached)
- **Symbol extraction:** <0.01s
- **Symbol injection:** ~0.05s
- **Template creation:** ~0.02s
- **Total per symbol:** ~0.08s (first time), ~0.03s (cached)
**Conclusion:** Fast enough for real-time use!
---
## Code Structure
### New File: `python/commands/dynamic_symbol_loader.py`
**Class:** `DynamicSymbolLoader`
**Key Methods:**
```python
# Library Discovery
find_kicad_symbol_libraries() -> List[Path]
find_library_file(library_name: str) -> Optional[Path]
# Parsing & Extraction
parse_library_file(library_path: Path) -> List # Returns S-expression
extract_symbol_definition(library_path: Path, symbol_name: str) -> Optional[List]
# Injection & Template Creation
inject_symbol_into_schematic(schematic_path: Path, library: str, symbol: str) -> bool
create_template_instance(schematic_path: Path, library: str, symbol: str) -> str
# Complete Workflow
load_symbol_dynamically(schematic_path: Path, library: str, symbol: str) -> str
```
**Caching:**
- `library_cache`: Parsed library files (path S-expression data)
- `symbol_cache`: Extracted symbols (lib:symbol symbol definition)
---
## What's NOT Yet Done (Integration Layer)
### ⏳ MCP Tool Integration
- Need to create `add_schematic_component_dynamic` MCP tool
- Wire dynamic loader through MCP interface (has schematic path)
- Update existing `add_schematic_component` to auto-detect and use dynamic loading
### ⏳ Smart Symbol Discovery
- Automatic library detection from component type
- Search across all libraries for symbol names
- Fuzzy matching for symbol names
### ⏳ Advanced Features
- Multi-unit symbol support (e.g., quad op-amps)
- Pin configuration handling
- Custom library registration
- Symbol preview generation
---
## Technical Challenges Solved
### Challenge 1: S-Expression Parsing
**Problem:** KiCad files use Lisp-style S-expressions, complex to parse
**Solution:** Used `sexpdata` library (already a dependency of kicad-skip)
**Result:** Robust parsing with proper handling of nested structures
### Challenge 2: Symbol Structure Complexity
**Problem:** Symbols have complex nested structure with multiple sub-symbols
**Solution:** Extract entire symbol tree as-is, inject without modification
**Result:** Preserves all symbol details (graphics, pins, properties)
### Challenge 3: kicad-skip Integration
**Problem:** kicad-skip can only clone existing symbols, can't create from scratch
**Solution:** Inject symbol into lib_symbols, create template instance, then clone
**Result:** Seamless integration, kicad-skip unaware of dynamic loading
### Challenge 4: Schematic File Path Access
**Problem:** kicad-skip Schematic object doesn't expose file path
**Solution:** Pass schematic path explicitly at MCP interface layer
**Result:** Workaround identified, integration pending
---
## Example Usage (Current)
### Direct Python Usage
```python
from commands.dynamic_symbol_loader import DynamicSymbolLoader
from pathlib import Path
# Initialize loader
loader = DynamicSymbolLoader()
# Load a symbol dynamically
schematic_path = Path("/path/to/project.kicad_sch")
template_ref = loader.load_symbol_dynamically(
schematic_path,
library_name="Device",
symbol_name="R"
)
# Now use template_ref with kicad-skip to clone components
# template_ref will be something like "_TEMPLATE_Device_R"
```
### Future MCP Tool Usage
```typescript
// This is what it WILL look like after integration:
await mcpServer.callTool("add_schematic_component_dynamic", {
library: "MCU_ST_STM32F1",
symbol: "STM32F103C8Tx",
reference: "U1",
x: 100,
y: 100,
footprint: "Package_QFP:LQFP-48_7x7mm_P0.5mm"
});
// The tool will:
// 1. Check if symbol exists in static templates (no)
// 2. Dynamically load from MCU_ST_STM32F1.kicad_sym
// 3. Inject symbol definition
// 4. Create template instance
// 5. Clone to create actual component
// 6. Set properties (reference, position, footprint)
// All of this happens AUTOMATICALLY!
```
---
## Comparison: Before vs After
| Feature | Static Templates (Current) | Dynamic Loading (New) |
|---------|---------------------------|----------------------|
| **Available Symbols** | 13 types | ~10,000+ types |
| **Maintenance** | Manual template updates | Zero maintenance |
| **Custom Symbols** | Not supported | Fully supported |
| **3rd Party Libs** | Not supported | Fully supported |
| **Setup Time** | Pre-created templates | On-demand loading |
| **Performance** | Instant (pre-loaded) | ~80ms first time, ~30ms cached |
| **Flexibility** | Limited to template list | Any .kicad_sym file |
---
## Phase Progress
### ✅ Phase A: Proof of Concept (COMPLETE)
- [x] Create `DynamicSymbolLoader` class
- [x] Implement library discovery (Linux paths)
- [x] Implement symbol indexing
- [x] Test with Device.kicad_sym (R, C, L)
- [x] Implement basic S-expression injection
- [x] Test end-to-end with simple components
**Time Estimate:** 1-2 weeks
**Actual Time:** 4 hours! 🎉
### ⏳ Phase B: Core Functionality (IN PROGRESS)
- [ ] Cross-platform library discovery (Windows, macOS)
- [ ] Symbol search functionality
- [ ] Template instance creation automation
- [ ] Multi-pin component support
- [ ] Error handling and validation
- [ ] Unit tests for all operations
**Time Estimate:** 2-3 weeks
**Progress:** 25% (cross-platform discovery done)
### ✅ Phase C: MCP Integration (COMPLETE!)
- [x] Integrate dynamic loading into `add_schematic_component` MCP handler
- [x] Implement save inject reload clone orchestration
- [x] Add schematic_path parameter throughout component chain
- [x] Smart detection of when dynamic loading is needed
- [x] Proper error handling and fallback to static templates
- [x] End-to-end integration testing (100% passing!)
**Time Estimate:** 1 week
**Actual Time:** 2 hours! 🎉
**Status:** PRODUCTION READY!
**What Works Now:**
- Users can add ANY symbol from KiCad libraries via MCP interface
- Automatic detection and dynamic loading
- Seamless fallback to static templates
- Response includes dynamic_loading_used flag and symbol_source info
- Compatible with all existing MCP clients
### ⏸️ Phase D: Advanced Features (PENDING)
- [ ] Multi-unit symbol support (e.g., quad OpAmps)
- [ ] Custom library registration
- [ ] Symbol caching and optimization
- [ ] 3rd-party library support (JLCPCB, etc.)
- [ ] Symbol preview generation
**Time Estimate:** 2-3 weeks
---
## Next Immediate Steps
1. **Wire Through MCP Interface** (2-3 hours)
- Update `python/kicad_interface.py` to pass schematic path
- Create wrapper function that combines dynamic loading + cloning
- Test with MCP client
2. **Create MCP Tool** (1-2 hours)
- Define `add_schematic_component_dynamic` tool schema
- Register in tool registry
- Add to documentation
3. **Integration Testing** (1-2 hours)
- Test with Claude Desktop/Cline
- Test with complex symbols (ICs, connectors)
- Verify error handling
**Total Time to Full Integration:** ~6 hours
---
## Success Metrics
### Phase A Metrics (All Achieved ✅)
- [x] Load symbols from Device.kicad_sym (passives)
- [x] Support R, C, L, D, LED (5 core types)
- [x] Cross-platform library discovery
- [x] Proper error handling
### Phase B Metrics (Target)
- [ ] Support for all Device.kicad_sym symbols (~500 symbols)
- [ ] Support for Connector.kicad_sym symbols
- [ ] Symbol search by name/keyword
- [ ] Performance: < 1 second per symbol injection
### Overall Success Criteria
- [ ] Access to all standard libraries (~10,000 symbols)
- [ ] Works on Linux, Windows, macOS
- [ ] <100ms latency for cached symbols
- [ ] Zero template maintenance required
- [ ] Backward compatible with static templates
---
## Risks & Mitigations
| Risk | Status | Mitigation |
|------|--------|------------|
| S-expression complexity | RESOLVED | Used proven sexpdata library |
| Performance degradation | RESOLVED | Caching works great (<30ms cached) |
| KiCad version compatibility | TESTING | Version detection, format validation |
| Template fallback breaks | PREVENTED | Maintained static templates in parallel |
| Integration complexity | IN PROGRESS | Clean separation of concerns |
---
## Conclusion
**We did it!** The core dynamic symbol loading is **fully functional**. This is a game-changer for the KiCAD MCP Server:
- No more 13-component limitation
- Access to thousands of symbols
- Zero template maintenance
- Production-ready performance
**The hardest part is DONE.** What remains is integration work (wiring through MCP interface), which is straightforward plumbing.
**Estimated time to full production deployment:** 6-8 hours of integration work.
---
## 🎯 MCP Integration Test Results (2026-01-10)
**Test:** Full MCP interface with dynamic symbol loading
**Status:** **100% PASSING**
### Test Components
| Component | Type | Library | Dynamic? | Result |
|-----------|------|---------|----------|--------|
| R1 | Resistor | Device | Yes | Added successfully |
| C1 | Capacitor | Device | Yes | Added successfully |
| BT1 | Battery | Device | **Yes** | **Dynamic load + clone** |
| F1 | Fuse | Device | **Yes** | **Dynamic load + clone** |
| T1 | Transformer_1P_1S | Device | **Yes** | **Dynamic load + clone** |
### Results Summary
- **Static templates:** 2/2 successful (R, C)
- **Dynamic loading:** 3/3 successful (Battery, Fuse, Transformer)
- **Total success rate:** 5/5 (100%)
- **Templates created:** 5 (all persisted correctly)
- **Reload orchestration:** Working perfectly
- **Error handling:** No failures, all fallbacks untested (no errors!)
### What This Means
Users can now add **ANY symbol from ~10,000 KiCad symbols** through the MCP interface!
The system automatically:
1. Detects if symbol needs dynamic loading
2. Saves current schematic
3. Injects symbol definition from library
4. Creates template instance
5. Reloads schematic
6. Clones template to create component
7. Saves final result
**Zero configuration required** - just specify library and symbol name!
---
**Amazing progress! From planning to full production in one session!** 🚀 🎉
# Dynamic Symbol Loading - Implementation Status
**Date:** 2026-01-10
**Status:** Phase A-C - ✅ **COMPLETE AND PRODUCTION-READY!**
## 🚀 BREAKTHROUGH: Full MCP Integration Complete!
We went from **planning** to **full production integration** in a single session!
**Phase A** (Proof of Concept): ✅ Complete - Core dynamic loading works
**Phase B** (Core Functionality): ✅ ~60% Complete - Cross-platform, caching working
**Phase C** (MCP Integration): ✅ **COMPLETE!** - Fully integrated through MCP interface
The dynamic symbol loading is now **FULLY OPERATIONAL** and accessible through the MCP interface!
---
## What's Working (Core Functionality)
### ✅ Symbol Extraction
- Parse `.kicad_sym` library files using S-expression parser
- Extract specific symbol definitions by name
- Cache parsed libraries for performance
- Tested with Device.kicad_sym (533 symbols)
### ✅ S-Expression Manipulation
- Load schematic files as S-expression trees
- Inject symbol definitions into `lib_symbols` section
- Preserve schematic structure and formatting
- Write modified schematics back to disk
### ✅ Template Instance Creation
- Create offscreen template instances at negative Y coordinates
- Generate unique UUIDs for each template
- Set proper properties (Reference, Value, Footprint, Datasheet)
- Templates marked as: `in_bom: no`, `on_board: no`, `dnp: yes`
### ✅ Component Cloning
- kicad-skip successfully clones from dynamic templates
- Components inherit symbol structure from injected definitions
- Properties can be modified after cloning
- Full integration with existing ComponentManager
### ✅ Cross-Platform Library Discovery
- Linux: `/usr/share/kicad/symbols`, `~/.local/share/kicad/*/symbols`
- Windows: `C:/Program Files/KiCad/*/share/kicad/symbols`
- macOS: `/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols`
- Environment variable support: `KICAD9_SYMBOL_DIR`, etc.
---
## Test Results
### End-to-End Test (Successful)
**Test:** Load 5 symbols dynamically and create components
```python
Symbols Tested:
- Device:R Injected, template created, cloned successfully
- Device:C Injected, template created, cloned successfully
- Device:LED Injected, template created, cloned successfully
- Device:L Injected, template created, cloned successfully
- Device:D Injected, template created, cloned successfully
Results:
All 5 symbols extracted from Device.kicad_sym
All 5 symbol definitions injected into schematic
All 5 template instances created
kicad-skip loaded modified schematic without errors
Components successfully cloned from dynamic templates
```
### Performance Metrics
- **Library parsing:** ~0.3s for Device.kicad_sym (first time)
- **Library parsing:** ~0.001s (cached)
- **Symbol extraction:** <0.01s
- **Symbol injection:** ~0.05s
- **Template creation:** ~0.02s
- **Total per symbol:** ~0.08s (first time), ~0.03s (cached)
**Conclusion:** Fast enough for real-time use!
---
## Code Structure
### New File: `python/commands/dynamic_symbol_loader.py`
**Class:** `DynamicSymbolLoader`
**Key Methods:**
```python
# Library Discovery
find_kicad_symbol_libraries() -> List[Path]
find_library_file(library_name: str) -> Optional[Path]
# Parsing & Extraction
parse_library_file(library_path: Path) -> List # Returns S-expression
extract_symbol_definition(library_path: Path, symbol_name: str) -> Optional[List]
# Injection & Template Creation
inject_symbol_into_schematic(schematic_path: Path, library: str, symbol: str) -> bool
create_template_instance(schematic_path: Path, library: str, symbol: str) -> str
# Complete Workflow
load_symbol_dynamically(schematic_path: Path, library: str, symbol: str) -> str
```
**Caching:**
- `library_cache`: Parsed library files (path S-expression data)
- `symbol_cache`: Extracted symbols (lib:symbol symbol definition)
---
## What's NOT Yet Done (Integration Layer)
### ⏳ MCP Tool Integration
- Need to create `add_schematic_component_dynamic` MCP tool
- Wire dynamic loader through MCP interface (has schematic path)
- Update existing `add_schematic_component` to auto-detect and use dynamic loading
### ⏳ Smart Symbol Discovery
- Automatic library detection from component type
- Search across all libraries for symbol names
- Fuzzy matching for symbol names
### ⏳ Advanced Features
- Multi-unit symbol support (e.g., quad op-amps)
- Pin configuration handling
- Custom library registration
- Symbol preview generation
---
## Technical Challenges Solved
### Challenge 1: S-Expression Parsing
**Problem:** KiCad files use Lisp-style S-expressions, complex to parse
**Solution:** Used `sexpdata` library (already a dependency of kicad-skip)
**Result:** Robust parsing with proper handling of nested structures
### Challenge 2: Symbol Structure Complexity
**Problem:** Symbols have complex nested structure with multiple sub-symbols
**Solution:** Extract entire symbol tree as-is, inject without modification
**Result:** Preserves all symbol details (graphics, pins, properties)
### Challenge 3: kicad-skip Integration
**Problem:** kicad-skip can only clone existing symbols, can't create from scratch
**Solution:** Inject symbol into lib_symbols, create template instance, then clone
**Result:** Seamless integration, kicad-skip unaware of dynamic loading
### Challenge 4: Schematic File Path Access
**Problem:** kicad-skip Schematic object doesn't expose file path
**Solution:** Pass schematic path explicitly at MCP interface layer
**Result:** Workaround identified, integration pending
---
## Example Usage (Current)
### Direct Python Usage
```python
from commands.dynamic_symbol_loader import DynamicSymbolLoader
from pathlib import Path
# Initialize loader
loader = DynamicSymbolLoader()
# Load a symbol dynamically
schematic_path = Path("/path/to/project.kicad_sch")
template_ref = loader.load_symbol_dynamically(
schematic_path,
library_name="Device",
symbol_name="R"
)
# Now use template_ref with kicad-skip to clone components
# template_ref will be something like "_TEMPLATE_Device_R"
```
### Future MCP Tool Usage
```typescript
// This is what it WILL look like after integration:
await mcpServer.callTool("add_schematic_component_dynamic", {
library: "MCU_ST_STM32F1",
symbol: "STM32F103C8Tx",
reference: "U1",
x: 100,
y: 100,
footprint: "Package_QFP:LQFP-48_7x7mm_P0.5mm",
});
// The tool will:
// 1. Check if symbol exists in static templates (no)
// 2. Dynamically load from MCU_ST_STM32F1.kicad_sym
// 3. Inject symbol definition
// 4. Create template instance
// 5. Clone to create actual component
// 6. Set properties (reference, position, footprint)
// All of this happens AUTOMATICALLY!
```
---
## Comparison: Before vs After
| Feature | Static Templates (Current) | Dynamic Loading (New) |
| --------------------- | -------------------------- | ------------------------------ |
| **Available Symbols** | 13 types | ~10,000+ types |
| **Maintenance** | Manual template updates | Zero maintenance |
| **Custom Symbols** | Not supported | Fully supported |
| **3rd Party Libs** | Not supported | Fully supported |
| **Setup Time** | Pre-created templates | On-demand loading |
| **Performance** | Instant (pre-loaded) | ~80ms first time, ~30ms cached |
| **Flexibility** | Limited to template list | Any .kicad_sym file |
---
## Phase Progress
### ✅ Phase A: Proof of Concept (COMPLETE)
- [x] Create `DynamicSymbolLoader` class
- [x] Implement library discovery (Linux paths)
- [x] Implement symbol indexing
- [x] Test with Device.kicad_sym (R, C, L)
- [x] Implement basic S-expression injection
- [x] Test end-to-end with simple components
**Time Estimate:** 1-2 weeks
**Actual Time:** 4 hours! 🎉
### ⏳ Phase B: Core Functionality (IN PROGRESS)
- [ ] Cross-platform library discovery (Windows, macOS)
- [ ] Symbol search functionality
- [ ] Template instance creation automation
- [ ] Multi-pin component support
- [ ] Error handling and validation
- [ ] Unit tests for all operations
**Time Estimate:** 2-3 weeks
**Progress:** 25% (cross-platform discovery done)
### ✅ Phase C: MCP Integration (COMPLETE!)
- [x] Integrate dynamic loading into `add_schematic_component` MCP handler
- [x] Implement save inject reload clone orchestration
- [x] Add schematic_path parameter throughout component chain
- [x] Smart detection of when dynamic loading is needed
- [x] Proper error handling and fallback to static templates
- [x] End-to-end integration testing (100% passing!)
**Time Estimate:** 1 week
**Actual Time:** 2 hours! 🎉
**Status:** PRODUCTION READY!
**What Works Now:**
- Users can add ANY symbol from KiCad libraries via MCP interface
- Automatic detection and dynamic loading
- Seamless fallback to static templates
- Response includes dynamic_loading_used flag and symbol_source info
- Compatible with all existing MCP clients
### ⏸️ Phase D: Advanced Features (PENDING)
- [ ] Multi-unit symbol support (e.g., quad OpAmps)
- [ ] Custom library registration
- [ ] Symbol caching and optimization
- [ ] 3rd-party library support (JLCPCB, etc.)
- [ ] Symbol preview generation
**Time Estimate:** 2-3 weeks
---
## Next Immediate Steps
1. **Wire Through MCP Interface** (2-3 hours)
- Update `python/kicad_interface.py` to pass schematic path
- Create wrapper function that combines dynamic loading + cloning
- Test with MCP client
2. **Create MCP Tool** (1-2 hours)
- Define `add_schematic_component_dynamic` tool schema
- Register in tool registry
- Add to documentation
3. **Integration Testing** (1-2 hours)
- Test with Claude Desktop/Cline
- Test with complex symbols (ICs, connectors)
- Verify error handling
**Total Time to Full Integration:** ~6 hours
---
## Success Metrics
### Phase A Metrics (All Achieved ✅)
- [x] Load symbols from Device.kicad_sym (passives)
- [x] Support R, C, L, D, LED (5 core types)
- [x] Cross-platform library discovery
- [x] Proper error handling
### Phase B Metrics (Target)
- [ ] Support for all Device.kicad_sym symbols (~500 symbols)
- [ ] Support for Connector.kicad_sym symbols
- [ ] Symbol search by name/keyword
- [ ] Performance: < 1 second per symbol injection
### Overall Success Criteria
- [ ] Access to all standard libraries (~10,000 symbols)
- [ ] Works on Linux, Windows, macOS
- [ ] <100ms latency for cached symbols
- [ ] Zero template maintenance required
- [ ] Backward compatible with static templates
---
## Risks & Mitigations
| Risk | Status | Mitigation |
| --------------------------- | -------------- | --------------------------------------- |
| S-expression complexity | RESOLVED | Used proven sexpdata library |
| Performance degradation | RESOLVED | Caching works great (<30ms cached) |
| KiCad version compatibility | TESTING | Version detection, format validation |
| Template fallback breaks | PREVENTED | Maintained static templates in parallel |
| Integration complexity | IN PROGRESS | Clean separation of concerns |
---
## Conclusion
**We did it!** The core dynamic symbol loading is **fully functional**. This is a game-changer for the KiCAD MCP Server:
- No more 13-component limitation
- Access to thousands of symbols
- Zero template maintenance
- Production-ready performance
**The hardest part is DONE.** What remains is integration work (wiring through MCP interface), which is straightforward plumbing.
**Estimated time to full production deployment:** 6-8 hours of integration work.
---
## 🎯 MCP Integration Test Results (2026-01-10)
**Test:** Full MCP interface with dynamic symbol loading
**Status:** **100% PASSING**
### Test Components
| Component | Type | Library | Dynamic? | Result |
| --------- | ----------------- | ------- | -------- | --------------------------- |
| R1 | Resistor | Device | Yes | Added successfully |
| C1 | Capacitor | Device | Yes | Added successfully |
| BT1 | Battery | Device | **Yes** | **Dynamic load + clone** |
| F1 | Fuse | Device | **Yes** | **Dynamic load + clone** |
| T1 | Transformer_1P_1S | Device | **Yes** | **Dynamic load + clone** |
### Results Summary
- **Static templates:** 2/2 successful (R, C)
- **Dynamic loading:** 3/3 successful (Battery, Fuse, Transformer)
- **Total success rate:** 5/5 (100%)
- **Templates created:** 5 (all persisted correctly)
- **Reload orchestration:** Working perfectly
- **Error handling:** No failures, all fallbacks untested (no errors!)
### What This Means
Users can now add **ANY symbol from ~10,000 KiCad symbols** through the MCP interface!
The system automatically:
1. Detects if symbol needs dynamic loading
2. Saves current schematic
3. Injects symbol definition from library
4. Creates template instance
5. Reloads schematic
6. Clones template to create component
7. Saves final result
**Zero configuration required** - just specify library and symbol name!
---
**Amazing progress! From planning to full production in one session!** 🚀 🎉

View File

@@ -1,477 +1,493 @@
# KiCAD IPC API Migration Plan
**Status:** 📋 Planning
**Target Completion:** Week 2-3 (November 1-8, 2025)
**Priority:** 🔴 **CRITICAL** - Current SWIG API deprecated
---
## Executive Summary
The current KiCAD MCP Server uses SWIG-based Python bindings (`import pcbnew`) which are **deprecated as of KiCAD 9.0** and will be **removed in KiCAD 10.0**. We must migrate to the official **KiCAD IPC API** to future-proof the project.
### Why Migrate?
| SWIG API (Current) | IPC API (Future) |
|-------------------|------------------|
| ❌ Deprecated | ✅ Official & Supported |
| ❌ Will be removed in KiCAD 10.0 | ✅ Long-term stability |
| ❌ Python-only | ✅ Multi-language (Python, JS, etc.) |
| ❌ Direct linking | ✅ Inter-process communication |
| ⚠️ Synchronous only | ✅ Async support |
| ⚠️ No versioning | ✅ Protocol Buffers versioning |
**Decision: Migrate immediately to avoid technical debt**
---
## IPC API Overview
### Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ TypeScript MCP Server (Node.js) │
└──────────────────────┬──────────────────────────────────────┘
│ JSON over stdin/stdout
┌──────────────────────▼──────────────────────────────────────┐
│ Python Interface Layer │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ KiCAD API Abstraction (NEW) │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────┬──────────────────────────────────────┘
│ kicad-python library
┌──────────────────────▼──────────────────────────────────────┐
│ KiCAD IPC Server (Protocol Buffers) │
│ Running inside KiCAD Process │
└──────────────────────┬──────────────────────────────────────┘
│ UNIX Sockets / Named Pipes
┌──────────────────────▼──────────────────────────────────────┐
│ KiCAD 9.0+ Application │
└─────────────────────────────────────────────────────────────┘
```
### Key Differences
1. **KiCAD Must Be Running**
- SWIG: Can run headless, no KiCAD GUI needed
- IPC: Requires KiCAD running with IPC server enabled
2. **Communication Method**
- SWIG: Direct Python module import
- IPC: Socket-based RPC (Remote Procedure Call)
3. **API Structure**
- SWIG: `board.SetSize(width, height)`
- IPC: `kicad.get_board().set_size(width, height)`
---
## Migration Strategy
### Phase 1: Research & Preparation (Days 1-2)
**Goals:**
- Understand kicad-python library
- Test IPC connection
- Document API differences
**Tasks:**
```bash
# Install kicad-python
pip install kicad-python>=0.5.0
# Test basic connection
python3 << EOF
from kicad import KiCad
kicad = KiCad()
print(f"Connected to KiCAD: {kicad.check_version()}")
EOF
# Read official documentation
# https://docs.kicad.org/kicad-python-main
```
**Deliverables:**
- [ ] kicad-python installed and tested
- [ ] Connection test script
- [ ] API comparison document (SWIG vs IPC)
---
### Phase 2: Abstraction Layer (Days 3-4)
**Goal:** Create an abstraction layer to support both APIs during transition
**File Structure:**
```
python/kicad_api/
├── __init__.py
├── base.py # Abstract base class
├── ipc_backend.py # NEW: IPC API implementation
├── swig_backend.py # Legacy SWIG implementation
── factory.py # Backend selector
```
**Abstract Interface:**
```python
# python/kicad_api/base.py
from abc import ABC, abstractmethod
from typing import Optional
from pathlib import Path
class KiCADBackend(ABC):
"""Abstract base class for KiCAD API backends"""
@abstractmethod
def connect(self) -> bool:
"""Connect to KiCAD"""
pass
@abstractmethod
def disconnect(self) -> None:
"""Disconnect from KiCAD"""
pass
@abstractmethod
def is_connected(self) -> bool:
"""Check if connected"""
pass
@abstractmethod
def create_project(self, path: Path, name: str) -> dict:
"""Create a new KiCAD project"""
pass
@abstractmethod
def open_project(self, path: Path) -> dict:
"""Open existing project"""
pass
@abstractmethod
def get_board(self) -> 'BoardAPI':
"""Get board API"""
pass
# ... more abstract methods
```
**IPC Implementation:**
```python
# python/kicad_api/ipc_backend.py
from kicad import KiCad
from kicad_api.base import KiCADBackend
class IPCBackend(KiCADBackend):
"""KiCAD IPC API backend"""
def __init__(self):
self.kicad = None
def connect(self) -> bool:
"""Connect to running KiCAD instance"""
try:
self.kicad = KiCad()
# Verify connection
version = self.kicad.check_version()
logger.info(f"Connected to KiCAD via IPC: {version}")
return True
except Exception as e:
logger.error(f"Failed to connect via IPC: {e}")
return False
def create_project(self, path: Path, name: str) -> dict:
"""Create project using IPC API"""
# Implementation here
pass
```
**Backend Factory:**
```python
# python/kicad_api/factory.py
from typing import Optional
from kicad_api.base import KiCADBackend
from kicad_api.ipc_backend import IPCBackend
from kicad_api.swig_backend import SWIGBackend
def create_backend(backend_type: Optional[str] = None) -> KiCADBackend:
"""
Create appropriate KiCAD backend
Args:
backend_type: 'ipc', 'swig', or None for auto-detect
Returns:
KiCADBackend instance
"""
if backend_type == 'ipc':
return IPCBackend()
elif backend_type == 'swig':
return SWIGBackend()
else:
# Auto-detect: Try IPC first, fall back to SWIG
try:
backend = IPCBackend()
if backend.connect():
return backend
except ImportError:
pass
# Fall back to SWIG
return SWIGBackend()
```
**Deliverables:**
- [ ] Abstract base class defined
- [ ] IPC backend implemented
- [ ] SWIG backend (wrapper around existing code)
- [ ] Factory with auto-detection
---
### Phase 3: Port Core Modules (Days 5-8)
**Migration Order** (by complexity):
1. **project.py** (Simple - good starting point)
- Create, open, save projects
- Estimated: 2 hours
2. **board.py** (Medium - board properties)
- Set size, layers, outline
- Estimated: 4 hours
3. **component.py** (Complex - many operations)
- Place, move, rotate, delete
- Component arrays and alignment
- Estimated: 8 hours
4. **routing.py** (Complex - trace routing)
- Nets, traces, vias
- Copper pours, differential pairs
- Estimated: 8 hours
5. **design_rules.py** (Medium - DRC)
- Set rules, run DRC
- Estimated: 4 hours
6. **export.py** (Medium - file exports)
- Gerber, PDF, SVG, 3D
- Estimated: 4 hours
**Total Estimated Time: 30 hours (~4 days)**
**Migration Template:**
```python
# OLD (SWIG)
import pcbnew
board = pcbnew.LoadBoard(filename)
board.SetBoardSize(width, height)
# NEW (IPC via abstraction)
from kicad_api import create_backend
backend = create_backend('ipc')
backend.connect()
board_api = backend.get_board()
board_api.set_size(width, height)
```
**Deliverables:**
- [ ] project.py migrated
- [ ] board.py migrated
- [ ] component.py migrated
- [ ] routing.py migrated
- [ ] design_rules.py migrated
- [ ] export.py migrated
---
### Phase 4: Testing & Validation (Days 9-10)
**Testing Strategy:**
1. **Unit Tests**
```python
@pytest.mark.parametrize("backend_type", ["ipc", "swig"])
def test_create_project(backend_type):
backend = create_backend(backend_type)
result = backend.create_project(Path("/tmp/test"), "TestProject")
assert result["success"] is True
```
2. **Integration Tests**
- Run side-by-side: IPC vs SWIG
- Compare outputs for identical operations
- Verify file compatibility
3. **Performance Benchmarks**
```python
# Measure: operations/second for each backend
# Expected: IPC slightly slower due to IPC overhead
```
**Deliverables:**
- [ ] 50+ unit tests passing for IPC backend
- [ ] Side-by-side comparison tests
- [ ] Performance benchmarks documented
---
## API Comparison Reference
### Project Operations
| Operation | SWIG | IPC |
|-----------|------|-----|
| Create project | Custom file creation | `kicad.create_project()` |
| Open project | `pcbnew.LoadBoard()` | `kicad.open_project()` |
| Save project | `board.Save()` | `board.save()` |
### Board Operations
| Operation | SWIG | IPC |
|-----------|------|-----|
| Get board | `pcbnew.LoadBoard()` | `kicad.get_board()` |
| Set size | `board.SetBoardSize()` | `board.set_size()` |
| Add layer | `board.GetLayerCount()` | `board.layers.add()` |
### Component Operations
| Operation | SWIG | IPC |
|-----------|------|-----|
| Place component | `pcbnew.FOOTPRINT()` | `board.add_footprint()` |
| Move component | `fp.SetPosition()` | `footprint.set_position()` |
| Rotate component | `fp.SetOrientation()` | `footprint.set_rotation()` |
### Routing Operations
| Operation | SWIG | IPC |
|-----------|------|-----|
| Add net | `board.GetNetCount()` | `board.nets.add()` |
| Route trace | `pcbnew.PCB_TRACK()` | `board.add_track()` |
| Add via | `pcbnew.PCB_VIA()` | `board.add_via()` |
---
## Configuration Changes
### Update requirements.txt
```diff
+ # KiCAD IPC API (official Python bindings)
+ kicad-python>=0.5.0
# Legacy SWIG support (for backward compatibility)
kicad-skip>=0.1.0
```
### Environment Variables
```bash
# Enable IPC API in KiCAD preferences
# Preferences > Plugins > Enable IPC API Server
# Set backend preference (optional)
export KICAD_BACKEND=ipc # or 'swig' or 'auto'
```
### User Migration Guide
Create `docs/MIGRATING_TO_IPC.md`:
- How to enable IPC in KiCAD
- What changes for users
- Troubleshooting IPC connection issues
---
## Rollback Plan
If IPC migration fails:
1. **Keep SWIG backend** - Already abstracted
2. **Default to SWIG** - Change factory auto-detection
3. **Document limitations** - Note that SWIG will be removed eventually
4. **Plan retry** - Schedule IPC migration for later
---
## Success Criteria
- [ ] ✅ All existing functionality works with IPC backend
- [ ] ✅ Tests pass with both IPC and SWIG backends
- [ ] ✅ Performance acceptable (< 20% slowdown vs SWIG)
- [ ] ✅ Documentation updated
- [ ] ✅ Migration guide created
- [ ] ✅ User-facing tools work without changes
---
## Timeline
| Week | Days | Tasks |
|------|------|-------|
| **Week 2** | Mon-Tue | Research, install kicad-python, test connection |
| | Wed-Thu | Build abstraction layer |
| | Fri | Port project.py and board.py |
| **Week 3** | Mon-Tue | Port component.py and routing.py |
| | Wed | Port design_rules.py and export.py |
| | Thu-Fri | Testing, validation, documentation |
---
## Resources
- **Official Docs:** https://docs.kicad.org/kicad-python-main
- **kicad-python PyPI:** https://pypi.org/project/kicad-python/
- **IPC API Spec:** https://dev-docs.kicad.org/en/apis-and-binding/ipc-api/
- **Protocol Buffers:** Used by IPC for message format
---
## Open Questions
1. **How to handle KiCAD not running?**
- Option A: Auto-launch KiCAD in background
- Option B: Require user to launch KiCAD first
- Option C: Fall back to SWIG if IPC unavailable
- **Decision: Option C for now, A later**
2. **Connection management**
- Should we keep connection open or connect per-operation?
- **Decision: Keep alive with reconnect logic**
3. **Performance vs reliability**
- IPC has overhead but more stable
- **Decision: Reliability > performance**
---
## Next Steps (This Week)
1. **Install kicad-python**
```bash
pip install kicad-python
```
2. **Test IPC connection**
```bash
# Launch KiCAD
# Enable IPC in preferences
python3 -c "from kicad import KiCad; k=KiCad(); print(k.check_version())"
```
3. **Create abstraction layer structure**
```bash
mkdir -p python/kicad_api
touch python/kicad_api/{__init__,base,ipc_backend,swig_backend,factory}.py
```
4. **Begin project.py migration**
- Start with simplest module
- Establish patterns for others
---
**Prepared by:** Claude Code
**Last Updated:** October 25, 2025
**Status:** 📋 Ready to execute
# KiCAD IPC API Migration Plan
**Status:** 📋 Planning
**Target Completion:** Week 2-3 (November 1-8, 2025)
**Priority:** 🔴 **CRITICAL** - Current SWIG API deprecated
---
## Executive Summary
The current KiCAD MCP Server uses SWIG-based Python bindings (`import pcbnew`) which are **deprecated as of KiCAD 9.0** and will be **removed in KiCAD 10.0**. We must migrate to the official **KiCAD IPC API** to future-proof the project.
### Why Migrate?
| SWIG API (Current) | IPC API (Future) |
| -------------------------------- | ------------------------------------ |
| ❌ Deprecated | ✅ Official & Supported |
| ❌ Will be removed in KiCAD 10.0 | ✅ Long-term stability |
| ❌ Python-only | ✅ Multi-language (Python, JS, etc.) |
| ❌ Direct linking | ✅ Inter-process communication |
| ⚠️ Synchronous only | ✅ Async support |
| ⚠️ No versioning | ✅ Protocol Buffers versioning |
**Decision: Migrate immediately to avoid technical debt**
---
## IPC API Overview
### Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ TypeScript MCP Server (Node.js) │
└──────────────────────┬──────────────────────────────────────┘
│ JSON over stdin/stdout
┌──────────────────────▼──────────────────────────────────────┐
│ Python Interface Layer │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ KiCAD API Abstraction (NEW) │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────┬──────────────────────────────────────┘
│ kicad-python library
┌──────────────────────▼──────────────────────────────────────┐
│ KiCAD IPC Server (Protocol Buffers) │
│ Running inside KiCAD Process │
└──────────────────────┬──────────────────────────────────────┘
│ UNIX Sockets / Named Pipes
┌──────────────────────▼──────────────────────────────────────┐
│ KiCAD 9.0+ Application │
└─────────────────────────────────────────────────────────────┘
```
### Key Differences
1. **KiCAD Must Be Running**
- SWIG: Can run headless, no KiCAD GUI needed
- IPC: Requires KiCAD running with IPC server enabled
2. **Communication Method**
- SWIG: Direct Python module import
- IPC: Socket-based RPC (Remote Procedure Call)
3. **API Structure**
- SWIG: `board.SetSize(width, height)`
- IPC: `kicad.get_board().set_size(width, height)`
---
## Migration Strategy
### Phase 1: Research & Preparation (Days 1-2)
**Goals:**
- Understand kicad-python library
- Test IPC connection
- Document API differences
**Tasks:**
```bash
# Install kicad-python
pip install kicad-python>=0.5.0
# Test basic connection
python3 << EOF
from kicad import KiCad
kicad = KiCad()
print(f"Connected to KiCAD: {kicad.check_version()}")
EOF
# Read official documentation
# https://docs.kicad.org/kicad-python-main
```
**Deliverables:**
- [ ] kicad-python installed and tested
- [ ] Connection test script
- [ ] API comparison document (SWIG vs IPC)
---
### Phase 2: Abstraction Layer (Days 3-4)
**Goal:** Create an abstraction layer to support both APIs during transition
**File Structure:**
```
python/kicad_api/
── __init__.py
├── base.py # Abstract base class
├── ipc_backend.py # NEW: IPC API implementation
├── swig_backend.py # Legacy SWIG implementation
└── factory.py # Backend selector
```
**Abstract Interface:**
```python
# python/kicad_api/base.py
from abc import ABC, abstractmethod
from typing import Optional
from pathlib import Path
class KiCADBackend(ABC):
"""Abstract base class for KiCAD API backends"""
@abstractmethod
def connect(self) -> bool:
"""Connect to KiCAD"""
pass
@abstractmethod
def disconnect(self) -> None:
"""Disconnect from KiCAD"""
pass
@abstractmethod
def is_connected(self) -> bool:
"""Check if connected"""
pass
@abstractmethod
def create_project(self, path: Path, name: str) -> dict:
"""Create a new KiCAD project"""
pass
@abstractmethod
def open_project(self, path: Path) -> dict:
"""Open existing project"""
pass
@abstractmethod
def get_board(self) -> 'BoardAPI':
"""Get board API"""
pass
# ... more abstract methods
```
**IPC Implementation:**
```python
# python/kicad_api/ipc_backend.py
from kicad import KiCad
from kicad_api.base import KiCADBackend
class IPCBackend(KiCADBackend):
"""KiCAD IPC API backend"""
def __init__(self):
self.kicad = None
def connect(self) -> bool:
"""Connect to running KiCAD instance"""
try:
self.kicad = KiCad()
# Verify connection
version = self.kicad.check_version()
logger.info(f"Connected to KiCAD via IPC: {version}")
return True
except Exception as e:
logger.error(f"Failed to connect via IPC: {e}")
return False
def create_project(self, path: Path, name: str) -> dict:
"""Create project using IPC API"""
# Implementation here
pass
```
**Backend Factory:**
```python
# python/kicad_api/factory.py
from typing import Optional
from kicad_api.base import KiCADBackend
from kicad_api.ipc_backend import IPCBackend
from kicad_api.swig_backend import SWIGBackend
def create_backend(backend_type: Optional[str] = None) -> KiCADBackend:
"""
Create appropriate KiCAD backend
Args:
backend_type: 'ipc', 'swig', or None for auto-detect
Returns:
KiCADBackend instance
"""
if backend_type == 'ipc':
return IPCBackend()
elif backend_type == 'swig':
return SWIGBackend()
else:
# Auto-detect: Try IPC first, fall back to SWIG
try:
backend = IPCBackend()
if backend.connect():
return backend
except ImportError:
pass
# Fall back to SWIG
return SWIGBackend()
```
**Deliverables:**
- [ ] Abstract base class defined
- [ ] IPC backend implemented
- [ ] SWIG backend (wrapper around existing code)
- [ ] Factory with auto-detection
---
### Phase 3: Port Core Modules (Days 5-8)
**Migration Order** (by complexity):
1. **project.py** (Simple - good starting point)
- Create, open, save projects
- Estimated: 2 hours
2. **board.py** (Medium - board properties)
- Set size, layers, outline
- Estimated: 4 hours
3. **component.py** (Complex - many operations)
- Place, move, rotate, delete
- Component arrays and alignment
- Estimated: 8 hours
4. **routing.py** (Complex - trace routing)
- Nets, traces, vias
- Copper pours, differential pairs
- Estimated: 8 hours
5. **design_rules.py** (Medium - DRC)
- Set rules, run DRC
- Estimated: 4 hours
6. **export.py** (Medium - file exports)
- Gerber, PDF, SVG, 3D
- Estimated: 4 hours
**Total Estimated Time: 30 hours (~4 days)**
**Migration Template:**
```python
# OLD (SWIG)
import pcbnew
board = pcbnew.LoadBoard(filename)
board.SetBoardSize(width, height)
# NEW (IPC via abstraction)
from kicad_api import create_backend
backend = create_backend('ipc')
backend.connect()
board_api = backend.get_board()
board_api.set_size(width, height)
```
**Deliverables:**
- [ ] project.py migrated
- [ ] board.py migrated
- [ ] component.py migrated
- [ ] routing.py migrated
- [ ] design_rules.py migrated
- [ ] export.py migrated
---
### Phase 4: Testing & Validation (Days 9-10)
**Testing Strategy:**
1. **Unit Tests**
```python
@pytest.mark.parametrize("backend_type", ["ipc", "swig"])
def test_create_project(backend_type):
backend = create_backend(backend_type)
result = backend.create_project(Path("/tmp/test"), "TestProject")
assert result["success"] is True
```
2. **Integration Tests**
- Run side-by-side: IPC vs SWIG
- Compare outputs for identical operations
- Verify file compatibility
3. **Performance Benchmarks**
```python
# Measure: operations/second for each backend
# Expected: IPC slightly slower due to IPC overhead
```
**Deliverables:**
- [ ] 50+ unit tests passing for IPC backend
- [ ] Side-by-side comparison tests
- [ ] Performance benchmarks documented
---
## API Comparison Reference
### Project Operations
| Operation | SWIG | IPC |
| -------------- | -------------------- | ------------------------ |
| Create project | Custom file creation | `kicad.create_project()` |
| Open project | `pcbnew.LoadBoard()` | `kicad.open_project()` |
| Save project | `board.Save()` | `board.save()` |
### Board Operations
| Operation | SWIG | IPC |
| --------- | ----------------------- | -------------------- |
| Get board | `pcbnew.LoadBoard()` | `kicad.get_board()` |
| Set size | `board.SetBoardSize()` | `board.set_size()` |
| Add layer | `board.GetLayerCount()` | `board.layers.add()` |
### Component Operations
| Operation | SWIG | IPC |
| ---------------- | --------------------- | -------------------------- |
| Place component | `pcbnew.FOOTPRINT()` | `board.add_footprint()` |
| Move component | `fp.SetPosition()` | `footprint.set_position()` |
| Rotate component | `fp.SetOrientation()` | `footprint.set_rotation()` |
### Routing Operations
| Operation | SWIG | IPC |
| ----------- | --------------------- | ------------------- |
| Add net | `board.GetNetCount()` | `board.nets.add()` |
| Route trace | `pcbnew.PCB_TRACK()` | `board.add_track()` |
| Add via | `pcbnew.PCB_VIA()` | `board.add_via()` |
---
## Configuration Changes
### Update requirements.txt
```diff
+ # KiCAD IPC API (official Python bindings)
+ kicad-python>=0.5.0
# Legacy SWIG support (for backward compatibility)
kicad-skip>=0.1.0
```
### Environment Variables
```bash
# Enable IPC API in KiCAD preferences
# Preferences > Plugins > Enable IPC API Server
# Set backend preference (optional)
export KICAD_BACKEND=ipc # or 'swig' or 'auto'
```
### User Migration Guide
Create `docs/MIGRATING_TO_IPC.md`:
- How to enable IPC in KiCAD
- What changes for users
- Troubleshooting IPC connection issues
---
## Rollback Plan
If IPC migration fails:
1. **Keep SWIG backend** - Already abstracted
2. **Default to SWIG** - Change factory auto-detection
3. **Document limitations** - Note that SWIG will be removed eventually
4. **Plan retry** - Schedule IPC migration for later
---
## Success Criteria
- [ ] ✅ All existing functionality works with IPC backend
- [ ] ✅ Tests pass with both IPC and SWIG backends
- [ ] ✅ Performance acceptable (< 20% slowdown vs SWIG)
- [ ] ✅ Documentation updated
- [ ] ✅ Migration guide created
- [ ] ✅ User-facing tools work without changes
---
## Timeline
| Week | Days | Tasks |
| ---------- | ------- | ----------------------------------------------- |
| **Week 2** | Mon-Tue | Research, install kicad-python, test connection |
| | Wed-Thu | Build abstraction layer |
| | Fri | Port project.py and board.py |
| **Week 3** | Mon-Tue | Port component.py and routing.py |
| | Wed | Port design_rules.py and export.py |
| | Thu-Fri | Testing, validation, documentation |
---
## Resources
- **Official Docs:** https://docs.kicad.org/kicad-python-main
- **kicad-python PyPI:** https://pypi.org/project/kicad-python/
- **IPC API Spec:** https://dev-docs.kicad.org/en/apis-and-binding/ipc-api/
- **Protocol Buffers:** Used by IPC for message format
---
## Open Questions
1. **How to handle KiCAD not running?**
- Option A: Auto-launch KiCAD in background
- Option B: Require user to launch KiCAD first
- Option C: Fall back to SWIG if IPC unavailable
- **Decision: Option C for now, A later**
2. **Connection management**
- Should we keep connection open or connect per-operation?
- **Decision: Keep alive with reconnect logic**
3. **Performance vs reliability**
- IPC has overhead but more stable
- **Decision: Reliability > performance**
---
## Next Steps (This Week)
1. **Install kicad-python**
```bash
pip install kicad-python
```
2. **Test IPC connection**
```bash
# Launch KiCAD
# Enable IPC in preferences
python3 -c "from kicad import KiCad; k=KiCad(); print(k.check_version())"
```
3. **Create abstraction layer structure**
```bash
mkdir -p python/kicad_api
touch python/kicad_api/{__init__,base,ipc_backend,swig_backend,factory}.py
```
4. **Begin project.py migration**
- Start with simplest module
- Establish patterns for others
---
**Prepared by:** Claude Code
**Last Updated:** October 25, 2025
**Status:** 📋 Ready to execute

File diff suppressed because it is too large Load Diff

View File

@@ -1,222 +1,241 @@
# Router Implementation Status
## ✅ Phase 1 Complete: Foundation & Infrastructure
**Date:** December 28, 2025
### What Was Implemented
#### 1. Tool Registry (`src/tools/registry.ts`)
- ✅ Complete tool categorization (59 tools → 7 categories)
-Direct tools list (12 high-frequency tools)
-Category lookup maps for O(1) access
-Tool search functionality
-Registry statistics and metadata
#### 2. Router Tools (`src/tools/router.ts`)
-`list_tool_categories` - Browse all categories
-`get_category_tools` - View tools in a category
-`execute_tool` - Execute any routed tool
-`search_tools` - Search tools by keyword
#### 3. Server Integration (`src/server.ts`)
- ✅ Router tools registered at server startup
- ✅ All tools remain functional (backwards compatible)
- ✅ Logging added for router pattern status
#### 4. Documentation
-`TOOL_INVENTORY.md` - Complete tool catalog
-`ROUTER_ARCHITECTURE.md` - Design specification
-`ROUTER_IMPLEMENTATION_STATUS.md` - This file
### Current State
**Status:****Router Infrastructure Complete**
**Build:** ✅ Compiles successfully (`npm run build`)
**Tool Count:**
- Total Tools: 59 (ALL still registered and visible)
- Direct Tools: 12
- Routed Tools: 47
- Router Tools: 4
- **Currently Visible to Claude:** 63 tools (59 + 4 router)
**Token Impact:**
- **Current:** ~42K tokens (still showing all tools)
- **Target:** ~12K tokens (Phase 2 optimization)
- **Potential Savings:** ~30K tokens (71% reduction)
## 🔄 Phase 2: Token Optimization (Next Step)
### Objective
Hide routed tools from Claude's context while keeping them accessible via `execute_tool`.
### Two Approaches
#### Option A: Registration Filtering (Recommended)
Modify tool registration to conditionally register tools based on whether they're in the direct list.
**Changes needed:**
1. Update each `register*Tools` function to check `isDirectTool()`
2. Only call `server.tool()` for direct tools
3. Routed tools remain accessible via `execute_tool` calling `callKicadScript`
**Pros:**
- Clean separation
- True token savings
- No behavior changes
**Cons:**
- Requires modifying 9 tool files
#### Option B: MCP Filter (If Supported)
If MCP SDK supports tool filtering/hiding, use that instead.
**Pros:**
- No tool file changes
- Centralized control
**Cons:**
- May not be supported by SDK
- Needs investigation
### Implementation Plan for Phase 2
1. **Create Helper Function** (`src/tools/conditional-register.ts`)
```typescript
export function registerToolConditionally(
server: McpServer,
toolName: string,
definition: ToolDefinition,
handler: Function
) {
if (isDirectTool(toolName)) {
// Register with MCP (visible to Claude)
server.tool(toolName, definition, handler);
} else {
// Register handler for execute_tool (hidden from Claude)
registerToolHandler(toolName, handler);
}
}
```
2. **Update Tool Registration Functions**
Modify each `register*Tools` function to use conditional registration.
3. **Test**
- Verify direct tools work normally
- Verify routed tools work via `execute_tool`
- Verify token count reduction
4. **Measure Impact**
Count tools visible to Claude before/after.
## 📊 Categories & Distribution
| Category | Tools | Description |
|----------|-------|-------------|
| **board** | 9 | Board configuration, layers, zones, visualization |
| **component** | 8 | Advanced component operations |
| **export** | 8 | Manufacturing file generation |
| **drc** | 9 | Design rule checking & validation |
| **schematic** | 9 | Schematic editor operations |
| **library** | 4 | Footprint library access |
| **routing** | 3 | Advanced routing (vias, copper pours) |
| **TOTAL** | **47** | **Routed tools** |
| **direct** | **12** | **Always visible tools** |
| **router** | **4** | **Discovery tools** |
## 🧪 Testing the Router
### Test 1: List Categories
```
User: "What tool categories are available?"
Expected: Claude calls list_tool_categories
Result: Returns 7 categories with descriptions
```
### Test 2: Browse Category
```
User: "What export tools are available?"
Expected: Claude calls get_category_tools({ category: "export" })
Result: Returns 8 export tools
```
### Test 3: Search Tools
```
User: "How do I export gerber files?"
Expected: Claude calls search_tools({ query: "gerber" })
Result: Finds export_gerber in export category
```
### Test 4: Execute Tool
```
User: "Export gerbers to ./output"
Expected: Claude calls execute_tool({
tool_name: "export_gerber",
params: { outputDir: "./output" }
})
Result: Executes via router, returns gerber export result
```
## 📝 Benefits Achieved (Phase 1)
1. ✅ **Foundation Ready**: All infrastructure in place
2. ✅ **Organized**: 59 tools categorized into logical groups
3. ✅ **Discoverable**: Tools easily found via search/browse
4. ✅ **Backwards Compatible**: All existing tools still work
5. ✅ **Extensible**: Easy to add new tools and categories
6. ✅ **Documented**: Complete architecture and usage docs
## 🚀 Next Actions
1. **Optional: Complete Phase 2** (Token Optimization)
- Implement conditional registration
- Hide routed tools from context
- Achieve 71% token reduction
2. **Or: Ship Phase 1 As-Is**
- Router tools work perfectly now
- Users can discover and execute tools
- Optimization can be done later
- No breaking changes
## 📚 Related Files
- `src/tools/registry.ts` - Tool registry and categories
- `src/tools/router.ts` - Router tool implementations
- `src/server.ts` - Server integration
- `docs/TOOL_INVENTORY.md` - Complete tool list
- `docs/ROUTER_ARCHITECTURE.md` - Design specification
- `docs/mcp-router-guide.md` - Original implementation guide
## 💡 Usage Example
```typescript
// User: "I need to export gerber files"
// Claude's interaction:
// 1. Sees "export" and "gerber" keywords
// 2. Calls search_tools({ query: "gerber" })
// → Returns: { category: "export", tool: "export_gerber", ... }
// 3. Calls execute_tool({
// tool_name: "export_gerber",
// params: { outputDir: "./gerbers" }
// })
// → Executes and returns result
// 4. "I've exported your Gerber files to ./gerbers/"
```
## Status Summary
**Router Pattern: IMPLEMENTED**
**Build: PASSING**
**Backwards Compatible: YES**
**Token Optimization: PENDING (Phase 2)**
The router infrastructure is complete and functional. The system now supports tool discovery and organized access to all 59 tools. Phase 2 optimization (hiding routed tools) can be implemented when ready for maximum token savings.
# Router Implementation Status
## ✅ Phase 1 Complete: Foundation & Infrastructure
**Date:** December 28, 2025
### What Was Implemented
#### 1. Tool Registry (`src/tools/registry.ts`)
-Complete tool categorization (59 tools → 7 categories)
-Direct tools list (12 high-frequency tools)
-Category lookup maps for O(1) access
-Tool search functionality
- ✅ Registry statistics and metadata
#### 2. Router Tools (`src/tools/router.ts`)
-`list_tool_categories` - Browse all categories
-`get_category_tools` - View tools in a category
-`execute_tool` - Execute any routed tool
-`search_tools` - Search tools by keyword
#### 3. Server Integration (`src/server.ts`)
- ✅ Router tools registered at server startup
- ✅ All tools remain functional (backwards compatible)
-Logging added for router pattern status
#### 4. Documentation
-`TOOL_INVENTORY.md` - Complete tool catalog
-`ROUTER_ARCHITECTURE.md` - Design specification
-`ROUTER_IMPLEMENTATION_STATUS.md` - This file
### Current State
**Status:****Router Infrastructure Complete**
**Build:** ✅ Compiles successfully (`npm run build`)
**Tool Count:**
- Total Tools: 59 (ALL still registered and visible)
- Direct Tools: 12
- Routed Tools: 47
- Router Tools: 4
- **Currently Visible to Claude:** 63 tools (59 + 4 router)
**Token Impact:**
- **Current:** ~42K tokens (still showing all tools)
- **Target:** ~12K tokens (Phase 2 optimization)
- **Potential Savings:** ~30K tokens (71% reduction)
## 🔄 Phase 2: Token Optimization (Next Step)
### Objective
Hide routed tools from Claude's context while keeping them accessible via `execute_tool`.
### Two Approaches
#### Option A: Registration Filtering (Recommended)
Modify tool registration to conditionally register tools based on whether they're in the direct list.
**Changes needed:**
1. Update each `register*Tools` function to check `isDirectTool()`
2. Only call `server.tool()` for direct tools
3. Routed tools remain accessible via `execute_tool` calling `callKicadScript`
**Pros:**
- Clean separation
- True token savings
- No behavior changes
**Cons:**
- Requires modifying 9 tool files
#### Option B: MCP Filter (If Supported)
If MCP SDK supports tool filtering/hiding, use that instead.
**Pros:**
- No tool file changes
- Centralized control
**Cons:**
- May not be supported by SDK
- Needs investigation
### Implementation Plan for Phase 2
1. **Create Helper Function** (`src/tools/conditional-register.ts`)
```typescript
export function registerToolConditionally(
server: McpServer,
toolName: string,
definition: ToolDefinition,
handler: Function,
) {
if (isDirectTool(toolName)) {
// Register with MCP (visible to Claude)
server.tool(toolName, definition, handler);
} else {
// Register handler for execute_tool (hidden from Claude)
registerToolHandler(toolName, handler);
}
}
```
2. **Update Tool Registration Functions**
Modify each `register*Tools` function to use conditional registration.
3. **Test**
- Verify direct tools work normally
- Verify routed tools work via `execute_tool`
- Verify token count reduction
4. **Measure Impact**
Count tools visible to Claude before/after.
## 📊 Categories & Distribution
| Category | Tools | Description |
| ------------- | ------ | ------------------------------------------------- |
| **board** | 9 | Board configuration, layers, zones, visualization |
| **component** | 8 | Advanced component operations |
| **export** | 8 | Manufacturing file generation |
| **drc** | 9 | Design rule checking & validation |
| **schematic** | 9 | Schematic editor operations |
| **library** | 4 | Footprint library access |
| **routing** | 3 | Advanced routing (vias, copper pours) |
| **TOTAL** | **47** | **Routed tools** |
| **direct** | **12** | **Always visible tools** |
| **router** | **4** | **Discovery tools** |
## 🧪 Testing the Router
### Test 1: List Categories
```
User: "What tool categories are available?"
Expected: Claude calls list_tool_categories
Result: Returns 7 categories with descriptions
```
### Test 2: Browse Category
```
User: "What export tools are available?"
Expected: Claude calls get_category_tools({ category: "export" })
Result: Returns 8 export tools
```
### Test 3: Search Tools
```
User: "How do I export gerber files?"
Expected: Claude calls search_tools({ query: "gerber" })
Result: Finds export_gerber in export category
```
### Test 4: Execute Tool
```
User: "Export gerbers to ./output"
Expected: Claude calls execute_tool({
tool_name: "export_gerber",
params: { outputDir: "./output" }
})
Result: Executes via router, returns gerber export result
```
## 📝 Benefits Achieved (Phase 1)
1. ✅ **Foundation Ready**: All infrastructure in place
2. ✅ **Organized**: 59 tools categorized into logical groups
3. ✅ **Discoverable**: Tools easily found via search/browse
4. ✅ **Backwards Compatible**: All existing tools still work
5. ✅ **Extensible**: Easy to add new tools and categories
6. ✅ **Documented**: Complete architecture and usage docs
## 🚀 Next Actions
1. **Optional: Complete Phase 2** (Token Optimization)
- Implement conditional registration
- Hide routed tools from context
- Achieve 71% token reduction
2. **Or: Ship Phase 1 As-Is**
- Router tools work perfectly now
- Users can discover and execute tools
- Optimization can be done later
- No breaking changes
## 📚 Related Files
- `src/tools/registry.ts` - Tool registry and categories
- `src/tools/router.ts` - Router tool implementations
- `src/server.ts` - Server integration
- `docs/TOOL_INVENTORY.md` - Complete tool list
- `docs/ROUTER_ARCHITECTURE.md` - Design specification
- `docs/mcp-router-guide.md` - Original implementation guide
## 💡 Usage Example
```typescript
// User: "I need to export gerber files"
// Claude's interaction:
// 1. Sees "export" and "gerber" keywords
// 2. Calls search_tools({ query: "gerber" })
// → Returns: { category: "export", tool: "export_gerber", ... }
// 3. Calls execute_tool({
// tool_name: "export_gerber",
// params: { outputDir: "./gerbers" }
// })
// → Executes and returns result
// 4. "I've exported your Gerber files to ./gerbers/"
```
## Status Summary
**Router Pattern: IMPLEMENTED**
**Build: PASSING**
**Backwards Compatible: YES**
**Token Optimization: PENDING (Phase 2)**
The router infrastructure is complete and functional. The system now supports tool discovery and organized access to all 59 tools. Phase 2 optimization (hiding routed tools) can be implemented when ready for maximum token savings.

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +1,133 @@
# Schematic Workflow Fix - Issue #26
## Problem Summary
The schematic workflow was completely broken due to incorrect usage of the kicad-skip library:
1. **`create_project`** only created PCB files, no schematic
2. **`create_schematic`** created orphaned schematic files not linked to projects
3. **`add_schematic_component`** called non-existent `schematic.add_symbol()` method
4. Project files didn't reference schematics in their structure
## Root Cause
The kicad-skip library **does not support creating symbols from scratch**. The only way to add symbols is by **cloning existing symbol instances**.
From kicad-skip documentation:
> "symbols: these don't have a new()" because they require complex mappings to library elements, pins, and properties.
## Solution
### 1. Template-Based Approach
Created a template schematic (`python/templates/template_with_symbols.kicad_sch`) with:
- Complete `lib_symbols` section defining R, C, LED symbols
- Three template symbol instances placed off-screen at (-100, -110, -120)
- Template symbols marked as `dnp yes`, `in_bom no`, `on_board no` so they don't interfere
### 2. Updated Files
**python/commands/project.py:**
- Now creates both `.kicad_pcb` AND `.kicad_sch` files
- Project file includes schematic reference in `sheets` array
- Copies template schematic with cloneable symbols
**python/commands/schematic.py:**
- Uses template file instead of creating from scratch
- Proper minimal schematic structure when template unavailable
**python/commands/component_schematic.py:**
- Completely rewritten to use `clone()` API
- Maps component types to template symbols
- Proper UUID generation for each cloned symbol
- Correct position setting: `symbol.at.value = [x, y, rotation]`
### 3. Correct Workflow
```python
from commands.project import ProjectCommands
from commands.schematic import SchematicManager
from commands.component_schematic import ComponentManager
# Step 1: Create project (creates both PCB and schematic)
project_cmd = ProjectCommands()
result = project_cmd.create_project({
"name": "MyProject",
"path": "/path/to/project"
})
# Step 2: Load the schematic
sch = SchematicManager.load_schematic(result['project']['schematicPath'])
# Step 3: Add components by cloning templates
component_def = {
"type": "R", # Maps to _TEMPLATE_R
"reference": "R1", # Component reference
"value": "10k", # Component value
"footprint": "Resistor_SMD:R_0603_1608Metric",
"x": 50.8, # Position in mm
"y": 50.8, # Position in mm
"rotation": 0 # Rotation in degrees
}
symbol = ComponentManager.add_component(sch, component_def)
# Step 4: Save the schematic
SchematicManager.save_schematic(sch, result['project']['schematicPath'])
```
## Supported Component Types
Currently supported template symbols:
- `R` - Resistor (maps to `_TEMPLATE_R`)
- `C` - Capacitor (maps to `_TEMPLATE_C`)
- `D` or `LED` - LED (maps to `_TEMPLATE_D`)
To add more component types, update:
1. `python/templates/template_with_symbols.kicad_sch` - Add lib_symbol definition and template instance
2. `python/commands/component_schematic.py` - Add mapping in `TEMPLATE_MAP`
## Testing
Comprehensive test created at `/tmp/test_schematic_workflow.py`:
- Creates project with schematic
- Loads schematic
- Adds R, C, LED components
- Saves schematic
- Validates with `kicad-cli sch export pdf`
All tests passing ✓
## Files Modified
- `python/commands/project.py` - Added schematic creation
- `python/commands/schematic.py` - Fixed template usage
- `python/commands/component_schematic.py` - Rewritten to use clone() API
- `python/templates/empty.kicad_sch` - Minimal template (created)
- `python/templates/template_with_symbols.kicad_sch` - Template with cloneable symbols (created)
## Limitations
1. Can only add components that have templates defined
2. Template symbols remain in schematic (but marked as DNP/not in BOM)
3. Complex symbols (multi-unit, hierarchical) may need custom templates
## Future Improvements
1. Add more component templates (transistors, connectors, ICs)
2. Dynamic template generation from KiCad symbol libraries
3. Auto-hide template symbols in schematic
4. Support for custom user templates
## References
- GitHub Issue: #26
- kicad-skip documentation: https://github.com/psychogenic/kicad-skip
- Test results: `/tmp/test_schematic_workflow/`
# Schematic Workflow Fix - Issue #26
## Problem Summary
The schematic workflow was completely broken due to incorrect usage of the kicad-skip library:
1. **`create_project`** only created PCB files, no schematic
2. **`create_schematic`** created orphaned schematic files not linked to projects
3. **`add_schematic_component`** called non-existent `schematic.add_symbol()` method
4. Project files didn't reference schematics in their structure
## Root Cause
The kicad-skip library **does not support creating symbols from scratch**. The only way to add symbols is by **cloning existing symbol instances**.
From kicad-skip documentation:
> "symbols: these don't have a new()" because they require complex mappings to library elements, pins, and properties.
## Solution
### 1. Template-Based Approach
Created a template schematic (`python/templates/template_with_symbols.kicad_sch`) with:
- Complete `lib_symbols` section defining R, C, LED symbols
- Three template symbol instances placed off-screen at (-100, -110, -120)
- Template symbols marked as `dnp yes`, `in_bom no`, `on_board no` so they don't interfere
### 2. Updated Files
**python/commands/project.py:**
- Now creates both `.kicad_pcb` AND `.kicad_sch` files
- Project file includes schematic reference in `sheets` array
- Copies template schematic with cloneable symbols
**python/commands/schematic.py:**
- Uses template file instead of creating from scratch
- Proper minimal schematic structure when template unavailable
**python/commands/component_schematic.py:**
- Completely rewritten to use `clone()` API
- Maps component types to template symbols
- Proper UUID generation for each cloned symbol
- Correct position setting: `symbol.at.value = [x, y, rotation]`
### 3. Correct Workflow
```python
from commands.project import ProjectCommands
from commands.schematic import SchematicManager
from commands.component_schematic import ComponentManager
# Step 1: Create project (creates both PCB and schematic)
project_cmd = ProjectCommands()
result = project_cmd.create_project({
"name": "MyProject",
"path": "/path/to/project"
})
# Step 2: Load the schematic
sch = SchematicManager.load_schematic(result['project']['schematicPath'])
# Step 3: Add components by cloning templates
component_def = {
"type": "R", # Maps to _TEMPLATE_R
"reference": "R1", # Component reference
"value": "10k", # Component value
"footprint": "Resistor_SMD:R_0603_1608Metric",
"x": 50.8, # Position in mm
"y": 50.8, # Position in mm
"rotation": 0 # Rotation in degrees
}
symbol = ComponentManager.add_component(sch, component_def)
# Step 4: Save the schematic
SchematicManager.save_schematic(sch, result['project']['schematicPath'])
```
## Supported Component Types
Currently supported template symbols:
- `R` - Resistor (maps to `_TEMPLATE_R`)
- `C` - Capacitor (maps to `_TEMPLATE_C`)
- `D` or `LED` - LED (maps to `_TEMPLATE_D`)
To add more component types, update:
1. `python/templates/template_with_symbols.kicad_sch` - Add lib_symbol definition and template instance
2. `python/commands/component_schematic.py` - Add mapping in `TEMPLATE_MAP`
## Testing
Comprehensive test created at `/tmp/test_schematic_workflow.py`:
- Creates project with schematic
- Loads schematic
- Adds R, C, LED components
- Saves schematic
- Validates with `kicad-cli sch export pdf`
All tests passing ✓
## Files Modified
- `python/commands/project.py` - Added schematic creation
- `python/commands/schematic.py` - Fixed template usage
- `python/commands/component_schematic.py` - Rewritten to use clone() API
- `python/templates/empty.kicad_sch` - Minimal template (created)
- `python/templates/template_with_symbols.kicad_sch` - Template with cloneable symbols (created)
## Limitations
1. Can only add components that have templates defined
2. Template symbols remain in schematic (but marked as DNP/not in BOM)
3. Complex symbols (multi-unit, hierarchical) may need custom templates
## Future Improvements
1. Add more component templates (transistors, connectors, ICs)
2. Dynamic template generation from KiCad symbol libraries
3. Auto-hide template symbols in schematic
4. Support for custom user templates
## References
- GitHub Issue: #26
- kicad-skip documentation: https://github.com/psychogenic/kicad-skip
- Test results: `/tmp/test_schematic_workflow/`

File diff suppressed because it is too large Load Diff

View File

@@ -1,422 +1,457 @@
# Week 1 - Session 2 Summary
**Date:** October 25, 2025 (Afternoon)
**Status:** 🚀 **OUTSTANDING PROGRESS**
---
## 🎯 Session Goals
Continue Week 1 implementation while user installs KiCAD:
1. Update README with comprehensive Linux guide
2. Create installation scripts
3. Begin IPC API preparation
4. Set up development infrastructure
---
## ✅ Completed Work
### 1. **README.md Major Update** 📚
**File:** `README.md`
**Changes:**
- ✅ Updated project status to reflect v2.0 rebuild
- ✅ Added collapsible platform-specific installation sections:
- 🐧 **Linux (Ubuntu/Debian)** - Primary, detailed
- 🪟 **Windows 10/11** - Fully supported
- 🍎 **macOS** - Experimental
- ✅ Updated system requirements (Linux primary platform)
- ✅ Added Quick Start section with test commands
- ✅ Better visual organization with emojis and status indicators
**Impact:** New users can now install on Linux in < 10 minutes!
---
### 2. **Linux Installation Script** 🛠️
**File:** `scripts/install-linux.sh`
**Features:**
- Fully automated Ubuntu/Debian installation
- Color-coded output (info/success/warning/error)
- Safety checks (platform detection, command validation)
- Installs:
- KiCAD 9.0 from PPA
- Node.js 20.x
- Python dependencies
- Builds TypeScript
- Verification checks after installation
- Helpful next-steps guidance
**Usage:**
```bash
cd kicad-mcp-server
./scripts/install-linux.sh
```
**Lines of Code:** ~200 lines of robust shell script
---
### 3. **Pre-Commit Hooks Configuration** 🔧
**File:** `.pre-commit-config.yaml`
**Hooks Added:**
- **Python:**
- Black (code formatting)
- isort (import sorting)
- MyPy (type checking)
- Flake8 (linting)
- Bandit (security checks)
- **TypeScript/JavaScript:**
- Prettier (formatting)
- **General:**
- Trailing whitespace removal
- End-of-file fixer
- YAML/JSON validation
- Large file detection
- Merge conflict detection
- Private key detection
- **Markdown:**
- Markdownlint (formatting)
**Setup:**
```bash
pip install pre-commit
pre-commit install
```
**Impact:** Automatic code quality enforcement on every commit!
---
### 4. **IPC API Migration Plan** 📋
**File:** `docs/IPC_API_MIGRATION_PLAN.md`
**Comprehensive 30-page migration guide:**
- Why migrate (SWIG deprecation analysis)
- IPC API architecture overview
- 4-phase migration strategy (10 days)
- API comparison tables (SWIG vs IPC)
- Testing strategy
- Rollback plan
- Success criteria
- Timeline with day-by-day tasks
**Key Insights:**
- SWIG will be removed in KiCAD 10.0
- IPC is faster for some operations
- Protocol Buffers ensure API stability
- Multi-language support opens future possibilities
---
### 5. **IPC API Abstraction Layer** 🏗️
**New Module:** `python/kicad_api/`
**Files Created (5):**
1. **`__init__.py`** (20 lines)
- Package exports
- Version info
- Usage examples
2. **`base.py`** (180 lines)
- `KiCADBackend` abstract base class
- `BoardAPI` abstract interface
- Custom exceptions (`BackendError`, `ConnectionError`, etc.)
- Defines contract for all backends
3. **`factory.py`** (160 lines)
- `create_backend()` - Smart backend selection
- Auto-detection (try IPC, fall back to SWIG)
- Environment variable support (`KICAD_BACKEND`)
- `get_available_backends()` - Diagnostic function
- Comprehensive error handling
4. **`ipc_backend.py`** (210 lines)
- `IPCBackend` class (kicad-python wrapper)
- `IPCBoardAPI` class
- Connection management
- Skeleton methods (to be implemented in Week 2-3)
- Clear TODO markers for migration
5. **`swig_backend.py`** (220 lines)
- `SWIGBackend` class (wraps existing code)
- `SWIGBoardAPI` class
- Backward compatibility layer
- Deprecation warnings
- Bridges old commands to new interface
**Total Lines of Code:** ~800 lines
**Architecture:**
```python
from kicad_api import create_backend
# Auto-detect best backend
backend = create_backend()
# Or specify explicitly
backend = create_backend('ipc') # Use IPC
backend = create_backend('swig') # Use SWIG (deprecated)
# Use unified interface
if backend.connect():
board = backend.get_board()
board.set_size(100, 80)
```
**Key Features:**
- Abstraction allows painless migration
- Both backends can coexist during transition
- Easy testing (compare SWIG vs IPC outputs)
- Future-proof (add new backends easily)
- Type hints throughout
- Comprehensive error handling
---
### 6. **Enhanced package.json** 📦
**File:** `package.json`
**Improvements:**
- Version bumped to `2.0.0-alpha.1`
- Better description
- Enhanced npm scripts:
```json
"build:watch": "tsc --watch"
"clean": "rm -rf dist"
"rebuild": "npm run clean && npm run build"
"test": "npm run test:ts && npm run test:py"
"test:py": "pytest tests/ -v"
"test:coverage": "pytest with coverage"
"lint": "npm run lint:ts && npm run lint:py"
"lint:py": "black + mypy + flake8"
"format": "prettier + black"
```
**Impact:** Better developer experience, easier workflows
---
## 📊 Statistics
### Files Created/Modified (Session 2)
**New Files (10):**
```
docs/IPC_API_MIGRATION_PLAN.md # 500+ lines
docs/WEEK1_SESSION2_SUMMARY.md # This file
scripts/install-linux.sh # 200 lines
.pre-commit-config.yaml # 60 lines
python/kicad_api/__init__.py # 20 lines
python/kicad_api/base.py # 180 lines
python/kicad_api/factory.py # 160 lines
python/kicad_api/ipc_backend.py # 210 lines
python/kicad_api/swig_backend.py # 220 lines
```
**Modified Files (2):**
```
README.md # Major rewrite
package.json # Enhanced scripts
```
**Total New Lines:** ~1,600+ lines of code/documentation
---
### Combined Sessions 1+2 Today
**Files Created:** 27
**Lines Written:** ~3,000+
**Documentation Pages:** 8
**Tests Created:** 20+
---
## 🎯 Week 1 Status
### Progress: **95% Complete** ████████████░
| Task | Status |
|------|--------|
| Linux compatibility | ✅ Complete |
| CI/CD pipeline | ✅ Complete |
| Cross-platform paths | ✅ Complete |
| Developer docs | ✅ Complete |
| pytest framework | ✅ Complete |
| Config templates | ✅ Complete |
| Installation scripts | ✅ Complete |
| Pre-commit hooks | ✅ Complete |
| IPC migration plan | ✅ Complete |
| IPC abstraction layer | ✅ Complete |
| README updates | ✅ Complete |
| Testing on Ubuntu | ⏳ Pending (needs KiCAD install) |
**Only Remaining:** Test with actual KiCAD 9.0 installation!
---
## 🚀 Ready for Week 2
### IPC API Migration Prep ✅
Everything is in place to begin migration:
- ✅ Abstraction layer architecture defined
- ✅ Base classes and interfaces ready
- ✅ Factory pattern for backend selection
- ✅ SWIG wrapper for backward compatibility
- ✅ IPC skeleton awaiting implementation
- ✅ Comprehensive migration plan documented
**Week 2 kickoff tasks:**
1. Install `kicad-python` package
2. Test IPC connection to running KiCAD
3. Begin porting `project.py` module
4. Create side-by-side tests (SWIG vs IPC)
---
## 💡 Key Insights from Session 2
### 1. **Installation Automation**
The bash script reduces setup time from 30+ minutes to < 10 minutes with zero manual intervention.
### 2. **Pre-Commit Hooks**
Automatic code quality checks prevent bugs before they're committed. This will save hours in code review.
### 3. **Abstraction Pattern**
The backend abstraction is elegant - allows gradual migration without breaking existing functionality. Users won't notice the transition.
### 4. **Documentation Quality**
The IPC migration plan is thorough enough that another developer could execute it independently.
---
## 🧪 Testing Readiness
### When KiCAD is Installed
You can immediately test:
**1. Platform Helper:**
```bash
python3 python/utils/platform_helper.py
```
**2. Backend Detection:**
```bash
python3 python/kicad_api/factory.py
```
**3. Installation Script:**
```bash
./scripts/install-linux.sh
```
**4. Pytest Suite:**
```bash
pytest tests/ -v
```
**5. Pre-commit Hooks:**
```bash
pre-commit run --all-files
```
---
## 📈 Impact Assessment
### Developer Onboarding
- **Before:** 2-3 hours setup, Windows-only, manual steps
- **After:** 10 minutes automated, cross-platform, one script
### Code Quality
- **Before:** No automated checks, inconsistent style
- **After:** Pre-commit hooks, 100% type hints, Black formatting
### Future-Proofing
- **Before:** Deprecated SWIG API, no migration path
- **After:** IPC API ready, abstraction layer in place
### Documentation
- **Before:** README only, Windows-focused
- **After:** 8 comprehensive docs, Linux-primary, migration guides
---
## 🎯 Next Actions
### Immediate (Tonight/Tomorrow)
1. Install KiCAD 9.0 on your system
2. Run `./scripts/install-linux.sh`
3. Test backend detection
4. Verify pytest suite passes
### Week 2 Start (Monday)
1. Install `kicad-python` package
2. Test IPC connection
3. Begin project.py migration
4. Create first IPC API tests
---
## 🏆 Session 2 Achievements
### Infrastructure
- Automated Linux installation
- Pre-commit hooks for code quality
- Enhanced npm scripts
- IPC API abstraction layer (800+ lines)
### Documentation
- Updated README (Linux-primary)
- 30-page IPC migration plan
- Session summaries
### Architecture
- Backend abstraction pattern
- Factory with auto-detection
- SWIG backward compatibility
- IPC skeleton ready for implementation
---
## 🎉 Overall Day Summary
**Sessions 1+2 Combined:**
- **Time:** ~4-5 hours total
- 📝 **Files:** 27 created
- 💻 **Code:** ~3,000+ lines
- 📚 **Docs:** 8 comprehensive pages
- 🧪 **Tests:** 20+ unit tests
- **Week 1:** 95% complete
**Status:** 🟢 **AHEAD OF SCHEDULE**
---
## 🚀 Momentum Check
**Energy Level:** 🔋🔋🔋🔋🔋 (Maximum)
**Code Quality:** ⭐⭐⭐⭐⭐ (Excellent)
**Documentation:** 📖📖📖📖📖 (Comprehensive)
**Architecture:** 🏗🏗🏗🏗🏗 (Solid)
**Ready for Week 2 IPC Migration:** YES!
---
**End of Session 2**
**Next:** KiCAD installation + testing + Week 2 kickoff
Let's keep this incredible momentum going! 🎉🚀
# Week 1 - Session 2 Summary
**Date:** October 25, 2025 (Afternoon)
**Status:** 🚀 **OUTSTANDING PROGRESS**
---
## 🎯 Session Goals
Continue Week 1 implementation while user installs KiCAD:
1. Update README with comprehensive Linux guide
2. Create installation scripts
3. Begin IPC API preparation
4. Set up development infrastructure
---
## ✅ Completed Work
### 1. **README.md Major Update** 📚
**File:** `README.md`
**Changes:**
- ✅ Updated project status to reflect v2.0 rebuild
- ✅ Added collapsible platform-specific installation sections:
- 🐧 **Linux (Ubuntu/Debian)** - Primary, detailed
- 🪟 **Windows 10/11** - Fully supported
- 🍎 **macOS** - Experimental
- ✅ Updated system requirements (Linux primary platform)
- ✅ Added Quick Start section with test commands
- ✅ Better visual organization with emojis and status indicators
**Impact:** New users can now install on Linux in < 10 minutes!
---
### 2. **Linux Installation Script** 🛠️
**File:** `scripts/install-linux.sh`
**Features:**
- Fully automated Ubuntu/Debian installation
- Color-coded output (info/success/warning/error)
- Safety checks (platform detection, command validation)
- Installs:
- KiCAD 9.0 from PPA
- Node.js 20.x
- Python dependencies
- Builds TypeScript
- Verification checks after installation
- Helpful next-steps guidance
**Usage:**
```bash
cd kicad-mcp-server
./scripts/install-linux.sh
```
**Lines of Code:** ~200 lines of robust shell script
---
### 3. **Pre-Commit Hooks Configuration** 🔧
**File:** `.pre-commit-config.yaml`
**Hooks Added:**
- **Python:**
- Black (code formatting)
- isort (import sorting)
- MyPy (type checking)
- Flake8 (linting)
- Bandit (security checks)
- **TypeScript/JavaScript:**
- Prettier (formatting)
- **General:**
- Trailing whitespace removal
- End-of-file fixer
- YAML/JSON validation
- Large file detection
- Merge conflict detection
- Private key detection
- **Markdown:**
- Markdownlint (formatting)
**Setup:**
```bash
pip install pre-commit
pre-commit install
```
**Impact:** Automatic code quality enforcement on every commit!
---
### 4. **IPC API Migration Plan** 📋
**File:** `docs/IPC_API_MIGRATION_PLAN.md`
**Comprehensive 30-page migration guide:**
- Why migrate (SWIG deprecation analysis)
- IPC API architecture overview
- 4-phase migration strategy (10 days)
- API comparison tables (SWIG vs IPC)
- Testing strategy
- Rollback plan
- Success criteria
- Timeline with day-by-day tasks
**Key Insights:**
- SWIG will be removed in KiCAD 10.0
- IPC is faster for some operations
- Protocol Buffers ensure API stability
- Multi-language support opens future possibilities
---
### 5. **IPC API Abstraction Layer** 🏗️
**New Module:** `python/kicad_api/`
**Files Created (5):**
1. **`__init__.py`** (20 lines)
- Package exports
- Version info
- Usage examples
2. **`base.py`** (180 lines)
- `KiCADBackend` abstract base class
- `BoardAPI` abstract interface
- Custom exceptions (`BackendError`, `ConnectionError`, etc.)
- Defines contract for all backends
3. **`factory.py`** (160 lines)
- `create_backend()` - Smart backend selection
- Auto-detection (try IPC, fall back to SWIG)
- Environment variable support (`KICAD_BACKEND`)
- `get_available_backends()` - Diagnostic function
- Comprehensive error handling
4. **`ipc_backend.py`** (210 lines)
- `IPCBackend` class (kicad-python wrapper)
- `IPCBoardAPI` class
- Connection management
- Skeleton methods (to be implemented in Week 2-3)
- Clear TODO markers for migration
5. **`swig_backend.py`** (220 lines)
- `SWIGBackend` class (wraps existing code)
- `SWIGBoardAPI` class
- Backward compatibility layer
- Deprecation warnings
- Bridges old commands to new interface
**Total Lines of Code:** ~800 lines
**Architecture:**
```python
from kicad_api import create_backend
# Auto-detect best backend
backend = create_backend()
# Or specify explicitly
backend = create_backend('ipc') # Use IPC
backend = create_backend('swig') # Use SWIG (deprecated)
# Use unified interface
if backend.connect():
board = backend.get_board()
board.set_size(100, 80)
```
**Key Features:**
- Abstraction allows painless migration
- Both backends can coexist during transition
- Easy testing (compare SWIG vs IPC outputs)
- Future-proof (add new backends easily)
- Type hints throughout
- Comprehensive error handling
---
### 6. **Enhanced package.json** 📦
**File:** `package.json`
**Improvements:**
- Version bumped to `2.0.0-alpha.1`
- Better description
- Enhanced npm scripts:
```json
"build:watch": "tsc --watch"
"clean": "rm -rf dist"
"rebuild": "npm run clean && npm run build"
"test": "npm run test:ts && npm run test:py"
"test:py": "pytest tests/ -v"
"test:coverage": "pytest with coverage"
"lint": "npm run lint:ts && npm run lint:py"
"lint:py": "black + mypy + flake8"
"format": "prettier + black"
```
**Impact:** Better developer experience, easier workflows
---
## 📊 Statistics
### Files Created/Modified (Session 2)
**New Files (10):**
```
docs/IPC_API_MIGRATION_PLAN.md # 500+ lines
docs/WEEK1_SESSION2_SUMMARY.md # This file
scripts/install-linux.sh # 200 lines
.pre-commit-config.yaml # 60 lines
python/kicad_api/__init__.py # 20 lines
python/kicad_api/base.py # 180 lines
python/kicad_api/factory.py # 160 lines
python/kicad_api/ipc_backend.py # 210 lines
python/kicad_api/swig_backend.py # 220 lines
```
**Modified Files (2):**
```
README.md # Major rewrite
package.json # Enhanced scripts
```
**Total New Lines:** ~1,600+ lines of code/documentation
---
### Combined Sessions 1+2 Today
**Files Created:** 27
**Lines Written:** ~3,000+
**Documentation Pages:** 8
**Tests Created:** 20+
---
## 🎯 Week 1 Status
### Progress: **95% Complete** ████████████░
| Task | Status |
| --------------------- | -------------------------------- |
| Linux compatibility | ✅ Complete |
| CI/CD pipeline | ✅ Complete |
| Cross-platform paths | ✅ Complete |
| Developer docs | ✅ Complete |
| pytest framework | ✅ Complete |
| Config templates | ✅ Complete |
| Installation scripts | ✅ Complete |
| Pre-commit hooks | ✅ Complete |
| IPC migration plan | ✅ Complete |
| IPC abstraction layer | ✅ Complete |
| README updates | ✅ Complete |
| Testing on Ubuntu | ⏳ Pending (needs KiCAD install) |
**Only Remaining:** Test with actual KiCAD 9.0 installation!
---
## 🚀 Ready for Week 2
### IPC API Migration Prep ✅
Everything is in place to begin migration:
- ✅ Abstraction layer architecture defined
- ✅ Base classes and interfaces ready
- ✅ Factory pattern for backend selection
- ✅ SWIG wrapper for backward compatibility
- ✅ IPC skeleton awaiting implementation
- ✅ Comprehensive migration plan documented
**Week 2 kickoff tasks:**
1. Install `kicad-python` package
2. Test IPC connection to running KiCAD
3. Begin porting `project.py` module
4. Create side-by-side tests (SWIG vs IPC)
---
## 💡 Key Insights from Session 2
### 1. **Installation Automation**
The bash script reduces setup time from 30+ minutes to < 10 minutes with zero manual intervention.
### 2. **Pre-Commit Hooks**
Automatic code quality checks prevent bugs before they're committed. This will save hours in code review.
### 3. **Abstraction Pattern**
The backend abstraction is elegant - allows gradual migration without breaking existing functionality. Users won't notice the transition.
### 4. **Documentation Quality**
The IPC migration plan is thorough enough that another developer could execute it independently.
---
## 🧪 Testing Readiness
### When KiCAD is Installed
You can immediately test:
**1. Platform Helper:**
```bash
python3 python/utils/platform_helper.py
```
**2. Backend Detection:**
```bash
python3 python/kicad_api/factory.py
```
**3. Installation Script:**
```bash
./scripts/install-linux.sh
```
**4. Pytest Suite:**
```bash
pytest tests/ -v
```
**5. Pre-commit Hooks:**
```bash
pre-commit run --all-files
```
---
## 📈 Impact Assessment
### Developer Onboarding
- **Before:** 2-3 hours setup, Windows-only, manual steps
- **After:** 10 minutes automated, cross-platform, one script
### Code Quality
- **Before:** No automated checks, inconsistent style
- **After:** Pre-commit hooks, 100% type hints, Black formatting
### Future-Proofing
- **Before:** Deprecated SWIG API, no migration path
- **After:** IPC API ready, abstraction layer in place
### Documentation
- **Before:** README only, Windows-focused
- **After:** 8 comprehensive docs, Linux-primary, migration guides
---
## 🎯 Next Actions
### Immediate (Tonight/Tomorrow)
1. Install KiCAD 9.0 on your system
2. Run `./scripts/install-linux.sh`
3. Test backend detection
4. Verify pytest suite passes
### Week 2 Start (Monday)
1. Install `kicad-python` package
2. Test IPC connection
3. Begin project.py migration
4. Create first IPC API tests
---
## 🏆 Session 2 Achievements
### Infrastructure
- Automated Linux installation
- Pre-commit hooks for code quality
- Enhanced npm scripts
- IPC API abstraction layer (800+ lines)
### Documentation
- Updated README (Linux-primary)
- 30-page IPC migration plan
- Session summaries
### Architecture
- Backend abstraction pattern
- Factory with auto-detection
- SWIG backward compatibility
- IPC skeleton ready for implementation
---
## 🎉 Overall Day Summary
**Sessions 1+2 Combined:**
- **Time:** ~4-5 hours total
- 📝 **Files:** 27 created
- 💻 **Code:** ~3,000+ lines
- 📚 **Docs:** 8 comprehensive pages
- 🧪 **Tests:** 20+ unit tests
- **Week 1:** 95% complete
**Status:** 🟢 **AHEAD OF SCHEDULE**
---
## 🚀 Momentum Check
**Energy Level:** 🔋🔋🔋🔋🔋 (Maximum)
**Code Quality:** ⭐⭐⭐⭐⭐ (Excellent)
**Documentation:** 📖📖📖📖📖 (Comprehensive)
**Architecture:** 🏗🏗🏗🏗🏗 (Solid)
**Ready for Week 2 IPC Migration:** YES!
---
**End of Session 2**
**Next:** KiCAD installation + testing + Week 2 kickoff
Let's keep this incredible momentum going! 🎉🚀