""" 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 }