diff --git a/README.md b/README.md index db97ea7..15b599f 100644 --- a/README.md +++ b/README.md @@ -152,9 +152,8 @@ The KiCad MCP Server provides several key features, each with detailed documenta - **BOM Management**: Analyze and export Bills of Materials - *Example:* "Generate a BOM for my smart watch project" → Creates a detailed bill of materials - - **Design Rule Checking**: Run DRC checks and track your progress over time + - **Design Rule Checking**: Run DRC checks using the KiCad CLI and track your progress over time - *Example:* "Run DRC on my power supply board and compare to last week" → Shows progress in fixing violations - - *KiCad 9.0+ Compatible:* Uses the new KiCad CLI or IPC API automatically - **PCB Visualization**: Generate visual representations of your PCB layouts - *Example:* "Show me a thumbnail of my audio amplifier PCB" → Displays a visual render of the board diff --git a/docs/drc_guide.md b/docs/drc_guide.md index e8382e8..6385af8 100644 --- a/docs/drc_guide.md +++ b/docs/drc_guide.md @@ -11,15 +11,7 @@ The Design Rule Check (DRC) functionality allows you to: 3. Track your progress over time as you fix issues 4. Compare current results with previous checks -## KiCad 9.0+ Compatibility - -**Important Update**: With KiCad 9.0+, the DRC functionality has been reimplemented to work with the new KiCad APIs. The server now supports two methods for running DRC: - -1. **KiCad CLI Method** (Recommended) - Uses the `kicad-cli` command-line tool to run DRC checks without requiring a running instance of KiCad. - -2. **IPC API Method** - Connects to a running instance of KiCad through the new IPC API using the `kicad-python` package. - -The server automatically selects the best available method based on your KiCad installation. +It does this all by using the `kicad-cli` command-line tool to run DRC checks without requiring a running instance of KiCad. ## Prerequisites @@ -27,7 +19,6 @@ For optimal DRC functionality with KiCad 9.0+, you should have: - KiCad 9.0 or newer installed - `kicad-cli` available in your system PATH (included with KiCad 9.0+) -- For IPC API functionality: the `kicad-python` package installed (`pip install kicad-python`) ## Using DRC Features @@ -43,7 +34,7 @@ Please run a DRC check on my project at /Users/username/Documents/KiCad/my_proje ``` The tool will: -- Automatically select the best available method (CLI or IPC API) +- Use the kicad CLI to run the DRC check - Analyze your PCB design for rule violations - Generate a comprehensive report - Save the results to your DRC history @@ -141,19 +132,7 @@ If the DRC check fails to run: 1. Ensure your KiCad project exists at the specified path 2. Verify that the project contains a PCB file (.kicad_pcb) -3. Check your KiCad installation: - - For CLI method: Verify `kicad-cli` is in your PATH or in a standard installation location - - For IPC API method: Make sure KiCad is running with the API server enabled in Preferences > Plugins +3. Check your KiCad installation: Verify `kicad-cli` is in your PATH or in a standard installation location 4. Try using the full absolute path to your project file -### Method Selection Issues - -If you want to force a specific DRC method: - -1. **CLI Method**: Ensure `kicad-cli` is available in your PATH -2. **IPC API Method**: - - Install the `kicad-python` package - - Launch KiCad before running the DRC check - - Enable the API server in KiCad preferences - If you continue to experience issues, check the server logs for more detailed error information. diff --git a/kicad_mcp/tools/drc_impl/ipc_drc.py b/kicad_mcp/tools/drc_impl/ipc_drc.py deleted file mode 100644 index 08334be..0000000 --- a/kicad_mcp/tools/drc_impl/ipc_drc.py +++ /dev/null @@ -1,160 +0,0 @@ -""" -Design Rule Check (DRC) implementation using the KiCad IPC API. -""" -import os -from typing import Any, Dict - -from mcp.server.fastmcp import Context - -from kicad_mcp.utils.kicad_api_detection import check_ipc_api_environment - -async def run_drc_with_ipc_api(pcb_file: str, ctx: Context) -> Dict[str, Any]: - """Run DRC using the KiCad IPC API (kicad-python). - This requires a running instance of KiCad with the IPC API enabled. - - Args: - pcb_file: Path to the PCB file (.kicad_pcb) - ctx: MCP context for progress reporting - - Returns: - Dictionary with DRC results - """ - try: - # Import the kicad-python modules - import kipy - from kipy.board_types import DrcExclusion, DrcSeverity - print("Successfully imported kipy modules") - - # Check if we're running in a KiCad IPC plugin environment - is_plugin, socket_path = check_ipc_api_environment() - - # Connect to KiCad - await ctx.report_progress(20, 100) - ctx.info("Connecting to KiCad...") - - if is_plugin: - # When running as a plugin, let kipy use environment variables - kicad = kipy.KiCad() - else: - # When running standalone, try to connect to KiCad - if socket_path: - kicad = kipy.KiCad(socket_path=socket_path) - else: - # Try with default socket path - kicad = kipy.KiCad() - - # Get the currently open board - await ctx.report_progress(30, 100) - ctx.info("Getting board...") - - # Check which board to use - current_boards = await kicad.get_open_documents("board") - - # If we have an open board, check if it's the one we want - use_current_board = False - board_doc = None - - if current_boards: - for doc in current_boards: - if doc.file_path and os.path.normpath(doc.file_path) == os.path.normpath(pcb_file): - board_doc = doc - use_current_board = True - break - - # If the board isn't open, see if we can open it - if not use_current_board: - ctx.info(f"Opening board file: {pcb_file}") - try: - # Try to open the board - doc = await kicad.open_document(pcb_file) - board_doc = doc - except Exception as e: - print(f"Error opening board: {str(e)}") - return { - "success": False, - "method": "ipc", - "error": f"Failed to open board file: {str(e)}" - } - - # Get the board - board = await kicad.board.get_board(board_doc.uuid) - - # Run DRC - await ctx.report_progress(50, 100) - ctx.info("Running DRC check...") - - # Define which severities to include - severity_filter = DrcSeverity.ERROR | DrcSeverity.WARNING - - # Run DRC on the board - drc_report = await kicad.board.run_drc( - board.uuid, - severity_filter=severity_filter, - exclusions=DrcExclusion.NONE # Include all violations - ) - - # Process results - await ctx.report_progress(70, 100) - ctx.info("Processing DRC results...") - - # Get all violations - violations = drc_report.violations - violation_count = len(violations) - - print(f"DRC completed with {violation_count} violations") - ctx.info(f"DRC completed with {violation_count} violations") - - # Process the violations - drc_errors = [] - error_types = {} - - for violation in violations: - # Get violation details - severity = str(violation.severity) - message = violation.message - - # Extract location - location = { - "x": violation.location.x if hasattr(violation, 'location') and violation.location else 0, - "y": violation.location.y if hasattr(violation, 'location') and violation.location else 0 - } - - error_info = { - "severity": severity, - "message": message, - "location": location - } - - drc_errors.append(error_info) - - # Count by type - if message not in error_types: - error_types[message] = 0 - error_types[message] += 1 - - # Create result - results = { - "success": True, - "method": "ipc", - "pcb_file": pcb_file, - "total_violations": violation_count, - "violation_categories": error_types, - "violations": drc_errors - } - - return results - - except ImportError as e: - print(f"Failed to import kipy modules: {str(e)}") - return { - "success": False, - "method": "ipc", - "error": f"Failed to import kipy modules: {str(e)}" - } - except Exception as e: - print(f"Error in IPC API DRC: {str(e)}", exc_info=True) - return { - "success": False, - "method": "ipc", - "error": f"Error in IPC API DRC: {str(e)}" - } diff --git a/kicad_mcp/tools/drc_tools.py b/kicad_mcp/tools/drc_tools.py index d348ee9..f3cf8fd 100644 --- a/kicad_mcp/tools/drc_tools.py +++ b/kicad_mcp/tools/drc_tools.py @@ -8,7 +8,6 @@ from mcp.server.fastmcp import FastMCP, Context from kicad_mcp.utils.file_utils import get_project_files from kicad_mcp.utils.drc_history import save_drc_result, get_drc_history, compare_with_previous -from kicad_mcp.utils.kicad_api_detection import get_best_api_approach # Import implementations from kicad_mcp.tools.drc_impl.cli_drc import run_drc_via_cli diff --git a/kicad_mcp/utils/kicad_api_detection.py b/kicad_mcp/utils/kicad_api_detection.py index ad2f89e..d0de87f 100644 --- a/kicad_mcp/utils/kicad_api_detection.py +++ b/kicad_mcp/utils/kicad_api_detection.py @@ -68,64 +68,3 @@ def check_for_cli_api() -> bool: except Exception as e: print(f"Error checking for KiCad CLI API: {str(e)}") return False - - -def check_for_ipc_api() -> bool: - """Check if KiCad IPC API (kicad-python) is available. - - Returns: - True if KiCad IPC API is available, False otherwise - """ - try: - # Try to import the kipy module - import kipy - print("KiCad IPC API (kicad-python) is available") - return True - except ImportError: - print("KiCad IPC API (kicad-python) is not available") - return False - except Exception as e: - print(f"Error checking for KiCad IPC API: {str(e)}") - return False - - -def check_ipc_api_environment() -> Tuple[bool, Optional[str]]: - """Check if we're running in a KiCad IPC plugin environment. - - Returns: - Tuple of (is_plugin, socket_path) - """ - # Check for environment variables that would indicate we're a plugin - is_plugin = os.environ.get("KICAD_PLUGIN_ENV") is not None - - # Check for socket path in environment - socket_path = os.environ.get("KICAD_SOCKET_PATH") - - if is_plugin: - print("Running as a KiCad plugin") - elif socket_path: - print(f"KiCad IPC socket path found: {socket_path}") - - return (is_plugin, socket_path) - - -def get_best_api_approach() -> Literal["cli", "ipc", "none"]: - """Determine the best available KiCad API approach. - - Returns: - String indicating which API approach to use: - - "cli": Use KiCad command-line interface - - "ipc": Use KiCad IPC API (kicad-python) - - "none": No API available - """ - # Check for IPC API first (preferred if available) - if check_for_ipc_api(): - return "ipc" - - # Check for CLI API next - if check_for_cli_api(): - return "cli" - - # No API available - print("No KiCad API available") - return "none" diff --git a/requirements.txt b/requirements.txt index 6d0beab..3f39619 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,5 @@ mcp[cli] -httpx -pytest pandas -kicad-python # Development/Testing -pytest-asyncio \ No newline at end of file +pytest \ No newline at end of file