kicad-mcp/kicad_mcp/tools/advanced_drc_tools.py
Ryan Malloy bc0f3db97c
Some checks are pending
CI / Lint and Format (push) Waiting to run
CI / Test Python 3.11 on macos-latest (push) Waiting to run
CI / Test Python 3.12 on macos-latest (push) Waiting to run
CI / Test Python 3.13 on macos-latest (push) Waiting to run
CI / Test Python 3.10 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.11 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.12 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.13 on ubuntu-latest (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / Build Package (push) Blocked by required conditions
Implement comprehensive AI/LLM integration for KiCad MCP server
Add intelligent analysis and recommendation tools for KiCad designs:

## New AI Tools (kicad_mcp/tools/ai_tools.py)
- suggest_components_for_circuit: Smart component suggestions based on circuit analysis
- recommend_design_rules: Automated design rule recommendations for different technologies
- optimize_pcb_layout: PCB layout optimization for signal integrity, thermal, and cost
- analyze_design_completeness: Comprehensive design completeness analysis

## Enhanced Utilities
- component_utils.py: Add ComponentType enum and component classification functions
- pattern_recognition.py: Enhanced circuit pattern analysis and recommendations
- netlist_parser.py: Implement missing parse_netlist_file function for AI tools

## Key Features
- Circuit pattern recognition for power supplies, amplifiers, microcontrollers
- Technology-specific design rules (standard, HDI, RF, automotive)
- Layout optimization suggestions with implementation steps
- Component suggestion system with standard values and examples
- Design completeness scoring with actionable recommendations

## Server Integration
- Register AI tools in FastMCP server
- Integrate with existing KiCad utilities and file parsers
- Error handling and graceful fallbacks for missing data

Fixes ImportError that prevented server startup and enables advanced
AI-powered design assistance for KiCad projects.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 16:15:58 -06:00

441 lines
16 KiB
Python

"""
Advanced DRC Tools for KiCad MCP Server.
Provides MCP tools for advanced Design Rule Check (DRC) functionality including
custom rule creation, specialized rule sets, and manufacturing constraint validation.
"""
from typing import Any
from fastmcp import FastMCP
from kicad_mcp.utils.advanced_drc import RuleSeverity, RuleType, create_drc_manager
from kicad_mcp.utils.path_validator import validate_kicad_file
def register_advanced_drc_tools(mcp: FastMCP) -> None:
"""Register advanced DRC tools with the MCP server."""
@mcp.tool()
def create_drc_rule_set(name: str, technology: str = "standard",
description: str = "") -> dict[str, Any]:
"""
Create a new DRC rule set for a specific technology or application.
Generates optimized rule sets for different PCB technologies including
standard PCB, HDI, RF/microwave, and automotive applications.
Args:
name: Name for the rule set (e.g., "MyProject_Rules")
technology: Technology type - one of: "standard", "hdi", "rf", "automotive"
description: Optional description of the rule set
Returns:
Dictionary containing the created rule set information with rules list
Examples:
create_drc_rule_set("RF_Design", "rf", "Rules for RF circuit board")
create_drc_rule_set("Auto_ECU", "automotive", "Automotive ECU design rules")
"""
try:
manager = create_drc_manager()
# Create rule set based on technology
if technology.lower() == "hdi":
rule_set = manager.create_high_density_rules()
elif technology.lower() == "rf":
rule_set = manager.create_rf_rules()
elif technology.lower() == "automotive":
rule_set = manager.create_automotive_rules()
else:
# Create standard rules with custom name
rule_set = manager.rule_sets["standard"]
rule_set.name = name
rule_set.description = description or f"Standard PCB rules for {name}"
if name:
rule_set.name = name
if description:
rule_set.description = description
manager.add_rule_set(rule_set)
return {
"success": True,
"rule_set_name": rule_set.name,
"technology": technology,
"rule_count": len(rule_set.rules),
"description": rule_set.description,
"rules": [
{
"name": rule.name,
"type": rule.rule_type.value,
"severity": rule.severity.value,
"constraint": rule.constraint,
"enabled": rule.enabled
}
for rule in rule_set.rules
]
}
except Exception as e:
return {
"success": False,
"error": str(e),
"rule_set_name": name
}
@mcp.tool()
def create_custom_drc_rule(rule_name: str, rule_type: str, constraint: dict[str, Any],
severity: str = "error", condition: str = None,
description: str = None) -> dict[str, Any]:
"""
Create a custom DRC rule with specific constraints and conditions.
Allows creation of specialized DRC rules for unique design requirements
beyond standard manufacturing constraints.
Args:
rule_name: Name for the new rule
rule_type: Type of rule (clearance, track_width, via_size, etc.)
constraint: Dictionary of constraint parameters
severity: Rule severity (error, warning, info, ignore)
condition: Optional condition expression for when rule applies
description: Optional description of the rule
Returns:
Dictionary containing the created rule information and validation results
"""
try:
manager = create_drc_manager()
# Convert string enums
try:
rule_type_enum = RuleType(rule_type.lower())
except ValueError:
return {
"success": False,
"error": f"Invalid rule type: {rule_type}. Valid types: {[rt.value for rt in RuleType]}"
}
try:
severity_enum = RuleSeverity(severity.lower())
except ValueError:
return {
"success": False,
"error": f"Invalid severity: {severity}. Valid severities: {[s.value for s in RuleSeverity]}"
}
# Create the rule
rule = manager.create_custom_rule(
name=rule_name,
rule_type=rule_type_enum,
constraint=constraint,
severity=severity_enum,
condition=condition,
description=description
)
# Validate rule syntax
validation_errors = manager.validate_rule_syntax(rule)
return {
"success": True,
"rule": {
"name": rule.name,
"type": rule.rule_type.value,
"severity": rule.severity.value,
"constraint": rule.constraint,
"condition": rule.condition,
"description": rule.description,
"enabled": rule.enabled
},
"validation": {
"valid": len(validation_errors) == 0,
"errors": validation_errors
}
}
except Exception as e:
return {
"success": False,
"error": str(e),
"rule_name": rule_name
}
@mcp.tool()
def export_kicad_drc_rules(rule_set_name: str = "standard") -> dict[str, Any]:
"""
Export DRC rules in KiCad-compatible format.
Converts internal rule set to KiCad DRC rule format that can be
imported into KiCad projects for automated checking.
Args:
rule_set_name: Name of the rule set to export (default: standard)
Returns:
Dictionary containing exported rules and KiCad-compatible rule text
"""
try:
manager = create_drc_manager()
# Export to KiCad format
kicad_rules = manager.export_kicad_drc_rules(rule_set_name)
rule_set = manager.rule_sets[rule_set_name]
return {
"success": True,
"rule_set_name": rule_set_name,
"kicad_rules": kicad_rules,
"rule_count": len(rule_set.rules),
"active_rules": len([r for r in rule_set.rules if r.enabled]),
"export_info": {
"format": "KiCad DRC Rules",
"version": rule_set.version,
"technology": rule_set.technology or "General",
"usage": "Copy the kicad_rules text to your KiCad project's custom DRC rules"
}
}
except Exception as e:
return {
"success": False,
"error": str(e),
"rule_set_name": rule_set_name
}
@mcp.tool()
def analyze_pcb_drc_violations(pcb_file_path: str, rule_set_name: str = "standard") -> dict[str, Any]:
"""
Analyze a PCB file against advanced DRC rules and report violations.
Performs comprehensive DRC analysis using custom rule sets to identify
design issues beyond basic KiCad DRC checking.
Args:
pcb_file_path: Full path to the .kicad_pcb file to analyze
rule_set_name: Name of rule set to use ("standard", "hdi", "rf", "automotive", or custom)
Returns:
Dictionary with violation details, severity levels, and recommendations
Examples:
analyze_pcb_drc_violations("/path/to/project.kicad_pcb", "rf")
analyze_pcb_drc_violations("/path/to/board.kicad_pcb") # uses standard rules
"""
try:
validated_path = validate_kicad_file(pcb_file_path, "pcb")
manager = create_drc_manager()
# Perform DRC analysis
analysis = manager.analyze_pcb_for_rule_violations(validated_path, rule_set_name)
# Get rule set info
rule_set = manager.rule_sets.get(rule_set_name)
return {
"success": True,
"pcb_file": validated_path,
"analysis": analysis,
"rule_set_info": {
"name": rule_set.name if rule_set else "Unknown",
"technology": rule_set.technology if rule_set else None,
"description": rule_set.description if rule_set else None,
"total_rules": len(rule_set.rules) if rule_set else 0
}
}
except Exception as e:
return {
"success": False,
"error": str(e),
"pcb_file": pcb_file_path
}
@mcp.tool()
def get_manufacturing_constraints(technology: str = "standard") -> dict[str, Any]:
"""
Get manufacturing constraints for a specific PCB technology.
Provides manufacturing limits and guidelines for different PCB
technologies to help with design rule creation.
Args:
technology: Technology type (standard, hdi, rf, automotive)
Returns:
Dictionary containing manufacturing constraints and recommendations
"""
try:
manager = create_drc_manager()
constraints = manager.generate_manufacturing_constraints(technology)
# Add recommendations based on technology
recommendations = {
"standard": [
"Maintain 0.1mm minimum track width for cost-effective manufacturing",
"Use 0.2mm clearance for reliable production yields",
"Consider 6-layer maximum for standard processes"
],
"hdi": [
"Use microvias for high-density routing",
"Maintain controlled impedance for signal integrity",
"Consider sequential build-up for complex designs"
],
"rf": [
"Maintain consistent dielectric properties",
"Use ground via stitching for EMI control",
"Control trace geometry for impedance matching"
],
"automotive": [
"Design for extended temperature range operation",
"Increase clearances for vibration resistance",
"Use thermal management for high-power components"
]
}
return {
"success": True,
"technology": technology,
"constraints": constraints,
"recommendations": recommendations.get(technology, recommendations["standard"]),
"applicable_standards": {
"automotive": ["ISO 26262", "AEC-Q100"],
"rf": ["IPC-2221", "IPC-2141"],
"hdi": ["IPC-2226", "IPC-6016"],
"standard": ["IPC-2221", "IPC-2222"]
}.get(technology, [])
}
except Exception as e:
return {
"success": False,
"error": str(e),
"technology": technology
}
@mcp.tool()
def list_available_rule_sets() -> dict[str, Any]:
"""
List all available DRC rule sets and their properties.
Provides information about built-in and custom rule sets available
for DRC analysis and export.
Returns:
Dictionary containing all available rule sets with their metadata
"""
try:
manager = create_drc_manager()
rule_set_names = manager.get_rule_set_names()
rule_sets_info = []
for name in rule_set_names:
rule_set = manager.rule_sets[name]
rule_sets_info.append({
"name": rule_set.name,
"key": name,
"version": rule_set.version,
"description": rule_set.description,
"technology": rule_set.technology,
"rule_count": len(rule_set.rules),
"active_rules": len([r for r in rule_set.rules if r.enabled]),
"rule_types": list(set(r.rule_type.value for r in rule_set.rules))
})
return {
"success": True,
"rule_sets": rule_sets_info,
"total_rule_sets": len(rule_set_names),
"active_rule_set": manager.active_rule_set,
"supported_technologies": ["standard", "hdi", "rf", "automotive"]
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
@mcp.tool()
def validate_drc_rule_syntax(rule_definition: dict[str, Any]) -> dict[str, Any]:
"""
Validate the syntax and parameters of a DRC rule definition.
Checks rule definition for proper syntax, valid constraints,
and logical consistency before rule creation.
Args:
rule_definition: Dictionary containing rule parameters to validate
Returns:
Dictionary containing validation results and error details
"""
try:
manager = create_drc_manager()
# Extract rule parameters
rule_name = rule_definition.get("name", "")
rule_type = rule_definition.get("type", "")
constraint = rule_definition.get("constraint", {})
severity = rule_definition.get("severity", "error")
condition = rule_definition.get("condition")
description = rule_definition.get("description")
# Validate required fields
validation_errors = []
if not rule_name:
validation_errors.append("Rule name is required")
if not rule_type:
validation_errors.append("Rule type is required")
elif rule_type not in [rt.value for rt in RuleType]:
validation_errors.append(f"Invalid rule type: {rule_type}")
if not constraint:
validation_errors.append("Constraint parameters are required")
if severity not in [s.value for s in RuleSeverity]:
validation_errors.append(f"Invalid severity: {severity}")
# If basic validation passes, create temporary rule for detailed validation
if not validation_errors:
try:
temp_rule = manager.create_custom_rule(
name=rule_name,
rule_type=RuleType(rule_type),
constraint=constraint,
severity=RuleSeverity(severity),
condition=condition,
description=description
)
# Validate rule syntax
syntax_errors = manager.validate_rule_syntax(temp_rule)
validation_errors.extend(syntax_errors)
except Exception as e:
validation_errors.append(f"Rule creation failed: {str(e)}")
return {
"success": True,
"valid": len(validation_errors) == 0,
"errors": validation_errors,
"rule_definition": rule_definition,
"validation_summary": {
"total_errors": len(validation_errors),
"critical_errors": len([e for e in validation_errors if "required" in e.lower()]),
"syntax_errors": len([e for e in validation_errors if "syntax" in e.lower() or "condition" in e.lower()])
}
}
except Exception as e:
return {
"success": False,
"error": str(e),
"rule_definition": rule_definition
}