KiCad MCP Server
by lamaalrajih
Verified
- kicad-mcp
- docs
# Development Guide
This guide provides detailed information for developers who want to modify or extend the KiCad MCP Server.
## Development Environment Setup
1. **Set up your Python environment**:
```bash
# Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install development dependencies
pip install -r requirements.txt
```
2. **Run in development mode**:
```bash
# Run with development server for better debugging
python -m mcp.dev main.py
```
3. **Use the MCP Inspector** for debugging:
```bash
npx @modelcontextprotocol/inspector uv --directory . run main.py
```
## Project Structure
The KiCad MCP Server follows a modular architecture:
```
kicad-mcp/
├── main.py # Entry point
├── kicad_mcp/ # Main package
│ ├── __init__.py
│ ├── server.py # Server creation and setup
│ ├── config.py # Configuration settings
│ ├── context.py # Lifespan context management
│ ├── resources/ # Resource handlers
│ │ ├── __init__.py
│ │ ├── projects.py # Project listing resources
│ │ ├── files.py # File content resources
│ │ ├── drc_resources.py # DRC report resources
│ │ └── bom_resources.py # BOM resources
│ ├── tools/ # Tool handlers
│ │ ├── __init__.py
│ │ ├── project_tools.py # Project management tools
│ │ ├── analysis_tools.py # Design analysis tools
│ │ ├── drc_tools.py # DRC check tools
│ │ ├── export_tools.py # Export and thumbnail tools
│ │ └── bom_tools.py # BOM management tools
│ ├── prompts/ # Prompt templates
│ │ ├── __init__.py
│ │ ├── templates.py # General KiCad prompts
│ │ ├── drc_prompt.py # DRC-specific prompts
│ │ └── bom_prompts.py # BOM-specific prompts
│ └── utils/ # Utility functions
│ ├── __init__.py
│ ├── file_utils.py # File handling utilities
│ ├── kicad_utils.py # KiCad-specific functions
│ ├── python_path.py # Python path setup for KiCad modules
│ ├── drc_history.py # DRC history tracking
│ └── env.py # Environment variable handling
```
## Adding New Features
### Creating a New Resource
Resources provide read-only data to the LLM. To add a new resource:
1. Add your function to an existing resource file or create a new one in `kicad_mcp/resources/`:
```python
from mcp.server.fastmcp import FastMCP
def register_my_resources(mcp: FastMCP) -> None:
"""Register my custom resources with the MCP server."""
@mcp.resource("kicad://my-resource/{parameter}")
def my_custom_resource(parameter: str) -> str:
"""Description of what this resource provides.
Args:
parameter: Description of parameter
Returns:
Formatted data for the LLM
"""
# Implementation goes here
return f"Formatted data about {parameter}"
```
2. Register your resources in `kicad_mcp/server.py`:
```python
from kicad_mcp.resources.my_resources import register_my_resources
def create_server() -> FastMCP:
# ...
register_my_resources(mcp)
# ...
```
### Creating a New Tool
Tools are functions that perform actions or computations. To add a new tool:
1. Add your function to an existing tool file or create a new one in `kicad_mcp/tools/`:
```python
from typing import Dict, Any
from mcp.server.fastmcp import FastMCP, Context
def register_my_tools(mcp: FastMCP) -> None:
"""Register my custom tools with the MCP server."""
@mcp.tool()
async def my_custom_tool(parameter: str, ctx: Context) -> Dict[str, Any]:
"""Description of what this tool does.
Args:
parameter: Description of parameter
ctx: MCP context for progress reporting
Returns:
Dictionary with tool results
"""
# Report progress to the user
await ctx.report_progress(10, 100)
ctx.info(f"Starting operation on {parameter}")
# Implementation goes here
# Complete progress
await ctx.report_progress(100, 100)
ctx.info("Operation complete")
return {
"success": True,
"message": "Operation completed successfully",
"result": "Some result data"
}
```
2. Register your tools in `kicad_mcp/server.py`:
```python
from kicad_mcp.tools.my_tools import register_my_tools
def create_server() -> FastMCP:
# ...
register_my_tools(mcp)
# ...
```
### Creating a New Prompt
Prompts are reusable templates for common interactions. To add a new prompt:
1. Add your function to an existing prompt file or create a new one in `kicad_mcp/prompts/`:
```python
from mcp.server.fastmcp import FastMCP
def register_my_prompts(mcp: FastMCP) -> None:
"""Register my custom prompts with the MCP server."""
@mcp.prompt()
def my_custom_prompt() -> str:
"""Description of what this prompt is for."""
prompt = """
I need help with [specific task] in KiCad. Please assist me with:
1. [First aspect]
2. [Second aspect]
3. [Third aspect]
My KiCad project is located at:
[Enter the full path to your .kicad_pro file here]
[Additional contextual information or instructions]
"""
return prompt
```
2. Register your prompts in `kicad_mcp/server.py`:
```python
from kicad_mcp.prompts.my_prompts import register_my_prompts
def create_server() -> FastMCP:
# ...
register_my_prompts(mcp)
# ...
```
## Using the Lifespan Context
The KiCad MCP Server uses a typed lifespan context to share data across requests:
```python
from kicad_mcp.context import KiCadAppContext
@mcp.tool()
def my_tool(parameter: str, ctx: Context) -> Dict[str, Any]:
"""Example tool using lifespan context."""
# Access the typed context
app_context: KiCadAppContext = ctx.request_context.lifespan_context
# Check if KiCad modules are available
if app_context.kicad_modules_available:
# Use KiCad Python modules
pass
else:
# Fall back to alternative method
pass
# Use the cache to store expensive results
cache_key = f"my_operation_{parameter}"
if cache_key in app_context.cache:
return app_context.cache[cache_key]
# Perform operation
result = {}
# Cache the result
app_context.cache[cache_key] = result
return result
```
## Testing
To run tests:
```bash
# Run all tests
pytest
# Run specific test file
pytest tests/test_resources.py
# Run with verbose output
pytest -v
```
## Debugging
For debugging, use:
1. The Python debugger (pdb)
2. Print statements to the console (captured in Claude Desktop logs)
3. The MCP Inspector tool
## Performance Considerations
1. Use caching for expensive operations
2. Report progress to the user for long-running operations
3. Include proper error handling and fallbacks
4. Use asyncio for concurrent operations
## Security Best Practices
1. Validate all file paths and user inputs
2. Use absolute paths for better predictability
3. Implement proper error handling
4. Don't expose sensitive information in responses
5. Sanitize output before returning it to the client
## Documentation
When adding new features, remember to:
1. Add thorough docstrings to all functions and classes
2. Update relevant documentation files in the `docs/` directory
3. Include examples of how to use your feature