feat: Enhance schematic functionality with pin-to-pin connections and netlist generation

Major improvements to schematic editing capabilities:

## Python Implementation (connection_schematic.py)
- Implemented pin-to-pin connection logic using kicad-skip
- Added get_pin_location() to find absolute pin positions
- Implemented add_connection() for wire connections between component pins
- Added add_net_label() for creating net labels
- Added connect_to_net() to connect pins to named nets
- Implemented get_net_connections() to query net connectivity
- Added generate_netlist() for schematic netlist extraction

## MCP Handlers (kicad_interface.py)
- Added 5 new command handlers:
  - add_schematic_connection - Pin-to-pin wiring
  - add_schematic_net_label - Net label placement
  - connect_to_net - Connect pin to named net
  - get_net_connections - Query net connectivity
  - generate_netlist - Export netlist data

## TypeScript Tools (schematic.ts)
- Added 5 new MCP tools with proper schemas and validation
- Enhanced user feedback with descriptive messages
- Total schematic tools increased from 3 to 8

## Features
- Pin location calculation with symbol rotation support
- Automatic wire stub creation for net labels
- Comprehensive netlist generation with component and net info
- Full logging for debugging connection issues

This resolves the schematic editing limitations and enables users to:
- Wire component pins together directly
- Use net labels for cleaner schematics
- Query schematic connectivity
- Generate netlists for manufacturing

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KiCAD MCP Bot
2025-11-29 10:29:02 -05:00
parent 34ccdb8822
commit dd12d21f46
3 changed files with 613 additions and 41 deletions

View File

@@ -272,6 +272,11 @@ class KiCADInterface:
"load_schematic": self._handle_load_schematic,
"add_schematic_component": self._handle_add_schematic_component,
"add_schematic_wire": self._handle_add_schematic_wire,
"add_schematic_connection": self._handle_add_schematic_connection,
"add_schematic_net_label": self._handle_add_schematic_net_label,
"connect_to_net": self._handle_connect_to_net,
"get_net_connections": self._handle_get_net_connections,
"generate_netlist": self._handle_generate_netlist,
"list_schematic_libraries": self._handle_list_schematic_libraries,
"export_schematic_pdf": self._handle_export_schematic_pdf,
@@ -471,6 +476,126 @@ class KiCADInterface:
logger.error(f"Error exporting schematic to PDF: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_add_schematic_connection(self, params):
"""Add a pin-to-pin connection in schematic"""
logger.info("Adding pin-to-pin connection in schematic")
try:
schematic_path = params.get("schematicPath")
source_ref = params.get("sourceRef")
source_pin = params.get("sourcePin")
target_ref = params.get("targetRef")
target_pin = params.get("targetPin")
if not all([schematic_path, source_ref, source_pin, target_ref, target_pin]):
return {"success": False, "message": "Missing required parameters"}
schematic = SchematicManager.load_schematic(schematic_path)
if not schematic:
return {"success": False, "message": "Failed to load schematic"}
success = ConnectionManager.add_connection(schematic, source_ref, source_pin, target_ref, target_pin)
if success:
SchematicManager.save_schematic(schematic, schematic_path)
return {"success": True}
else:
return {"success": False, "message": "Failed to add connection"}
except Exception as e:
logger.error(f"Error adding schematic connection: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_add_schematic_net_label(self, params):
"""Add a net label to schematic"""
logger.info("Adding net label to schematic")
try:
schematic_path = params.get("schematicPath")
net_name = params.get("netName")
position = params.get("position")
if not all([schematic_path, net_name, position]):
return {"success": False, "message": "Missing required parameters"}
schematic = SchematicManager.load_schematic(schematic_path)
if not schematic:
return {"success": False, "message": "Failed to load schematic"}
label = ConnectionManager.add_net_label(schematic, net_name, position)
if label:
SchematicManager.save_schematic(schematic, schematic_path)
return {"success": True}
else:
return {"success": False, "message": "Failed to add net label"}
except Exception as e:
logger.error(f"Error adding net label: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_connect_to_net(self, params):
"""Connect a component pin to a named net"""
logger.info("Connecting component pin to net")
try:
schematic_path = params.get("schematicPath")
component_ref = params.get("componentRef")
pin_name = params.get("pinName")
net_name = params.get("netName")
if not all([schematic_path, component_ref, pin_name, net_name]):
return {"success": False, "message": "Missing required parameters"}
schematic = SchematicManager.load_schematic(schematic_path)
if not schematic:
return {"success": False, "message": "Failed to load schematic"}
success = ConnectionManager.connect_to_net(schematic, component_ref, pin_name, net_name)
if success:
SchematicManager.save_schematic(schematic, schematic_path)
return {"success": True}
else:
return {"success": False, "message": "Failed to connect to net"}
except Exception as e:
logger.error(f"Error connecting to net: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_get_net_connections(self, params):
"""Get all connections for a named net"""
logger.info("Getting net connections")
try:
schematic_path = params.get("schematicPath")
net_name = params.get("netName")
if not all([schematic_path, net_name]):
return {"success": False, "message": "Missing required parameters"}
schematic = SchematicManager.load_schematic(schematic_path)
if not schematic:
return {"success": False, "message": "Failed to load schematic"}
connections = ConnectionManager.get_net_connections(schematic, net_name)
return {"success": True, "connections": connections}
except Exception as e:
logger.error(f"Error getting net connections: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_generate_netlist(self, params):
"""Generate netlist from schematic"""
logger.info("Generating netlist from schematic")
try:
schematic_path = params.get("schematicPath")
if not schematic_path:
return {"success": False, "message": "Schematic path is required"}
schematic = SchematicManager.load_schematic(schematic_path)
if not schematic:
return {"success": False, "message": "Failed to load schematic"}
netlist = ConnectionManager.generate_netlist(schematic)
return {"success": True, "netlist": netlist}
except Exception as e:
logger.error(f"Error generating netlist: {str(e)}")
return {"success": False, "message": str(e)}
def _handle_check_kicad_ui(self, params):
"""Check if KiCAD UI is running"""
logger.info("Checking if KiCAD UI is running")