- Implement 3D model analysis and mechanical constraints checking - Add advanced DRC rule customization for HDI, RF, and automotive applications - Create symbol library management with analysis and validation tools - Implement PCB layer stack-up analysis with impedance calculations - Fix Context parameter validation errors causing client failures - Add enhanced tool annotations with examples for better LLM compatibility - Include comprehensive test coverage improvements (22.21% coverage) - Add CLAUDE.md documentation for development guidance New Advanced Tools: • 3D model analysis: analyze_3d_models, check_mechanical_constraints • Advanced DRC: create_drc_rule_set, analyze_pcb_drc_violations • Symbol management: analyze_symbol_library, validate_symbol_library • Layer analysis: analyze_pcb_stackup, calculate_trace_impedance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
446 lines
17 KiB
Python
446 lines
17 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.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any, Dict, List
|
|
|
|
from fastmcp import FastMCP
|
|
from kicad_mcp.utils.advanced_drc import (
|
|
create_drc_manager,
|
|
AdvancedDRCManager,
|
|
DRCRule,
|
|
RuleType,
|
|
RuleSeverity
|
|
)
|
|
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
|
|
} |