""" Design Rule Check (DRC) tools for KiCad PCB files. """ import os # import logging # <-- Remove if no other logging exists from typing import Any from fastmcp import FastMCP # Import implementations from kicad_mcp.tools.drc_impl.cli_drc import run_drc_via_cli from kicad_mcp.utils.drc_history import compare_with_previous, get_drc_history, save_drc_result from kicad_mcp.utils.file_utils import get_project_files def register_drc_tools(mcp: FastMCP) -> None: """Register DRC tools with the MCP server. Args: mcp: The FastMCP server instance """ @mcp.tool() def get_drc_history_tool(project_path: str) -> dict[str, Any]: """Get the DRC check history for a KiCad project. Args: project_path: Path to the KiCad project file (.kicad_pro) Returns: Dictionary with DRC history entries """ print(f"Getting DRC history for project: {project_path}") if not os.path.exists(project_path): print(f"Project not found: {project_path}") return {"success": False, "error": f"Project not found: {project_path}"} # Get history entries history_entries = get_drc_history(project_path) # Calculate trend information trend = None if len(history_entries) >= 2: first = history_entries[-1] # Oldest entry last = history_entries[0] # Newest entry first_violations = first.get("total_violations", 0) last_violations = last.get("total_violations", 0) if first_violations > last_violations: trend = "improving" elif first_violations < last_violations: trend = "degrading" else: trend = "stable" return { "success": True, "project_path": project_path, "history_entries": history_entries, "entry_count": len(history_entries), "trend": trend, } @mcp.tool() def run_drc_check(project_path: str) -> dict[str, Any]: """Run a Design Rule Check on a KiCad PCB file. Args: project_path: Path to the KiCad project file (.kicad_pro) Returns: Dictionary with DRC results and statistics """ print(f"Running DRC check for project: {project_path}") if not os.path.exists(project_path): print(f"Project not found: {project_path}") return {"success": False, "error": f"Project not found: {project_path}"} # Get PCB file from project files = get_project_files(project_path) if "pcb" not in files: print("PCB file not found in project") return {"success": False, "error": "PCB file not found in project"} pcb_file = files["pcb"] print(f"Found PCB file: {pcb_file}") # Run DRC using the appropriate approach drc_results = None print("Using kicad-cli for DRC") # Use synchronous DRC check try: from kicad_mcp.tools.drc_impl.cli_drc import run_drc_via_cli_sync drc_results = run_drc_via_cli_sync(pcb_file) except ImportError: # Fallback - call the async version but handle it differently import asyncio drc_results = asyncio.run(run_drc_via_cli(pcb_file, None)) # Process and save results if successful if drc_results and drc_results.get("success", False): # logging.info(f"[DRC] DRC check successful for {pcb_file}. Saving results.") # <-- Remove log # Save results to history save_drc_result(project_path, drc_results) # Add comparison with previous run comparison = compare_with_previous(project_path, drc_results) if comparison: drc_results["comparison"] = comparison if comparison["change"] < 0: print(f"Great progress! You've fixed {abs(comparison['change'])} DRC violations since the last check.") elif comparison["change"] > 0: print(f"Found {comparison['change']} new DRC violations since the last check.") else: print("No change in the number of DRC violations since the last check.") elif drc_results: # logging.warning(f"[DRC] DRC check reported failure for {pcb_file}: {drc_results.get('error')}") # <-- Remove log # Pass or print a warning if needed pass else: # logging.error(f"[DRC] DRC check returned None for {pcb_file}") # <-- Remove log # Pass or print an error if needed pass # DRC check completed return drc_results or {"success": False, "error": "DRC check failed with an unknown error"}