Major documentation update bringing all docs current with the 122-tool, 16-category state of the project (previously frozen at v2.1.0-alpha/59 tools). New documentation (9 files): - FREEROUTING_GUIDE.md - autorouter setup, Docker/Podman, all 4 tools - SCHEMATIC_TOOLS_REFERENCE.md - all 27 schematic tools with parameters - ROUTING_TOOLS_REFERENCE.md - all 13 routing tools with examples - FOOTPRINT_SYMBOL_CREATOR_GUIDE.md - 8 creator tools with examples - SVG_IMPORT_GUIDE.md - SVG logo import tool - DATASHEET_TOOLS_GUIDE.md - datasheet enrichment tools - PCB_DESIGN_WORKFLOW.md - end-to-end design guide - ARCHITECTURE.md - system architecture for contributors - INDEX.md - documentation table of contents Updated documentation (12 files): - README.md - tool count 64->122, feature list, contributor credits - TOOL_INVENTORY.md - complete rebuild with all 122 tools - STATUS_SUMMARY.md - updated to v2.2.3 feature matrix - ROADMAP.md - marked completed milestones, added v2.3+ vision - KNOWN_ISSUES.md - removed resolved issues, added v2.2.x fixes - CLIENT_CONFIGURATION.md - added KICAD_MCP_DEV, FREEROUTING_JAR env vars - LIBRARY_INTEGRATION.md - added symbol and project-local library support - ROUTER_ARCHITECTURE.md, ROUTER_QUICK_START.md - updated tool counts - IPC_BACKEND_STATUS.md - updated dates - JLCPCB_USAGE_GUIDE.md - added cross-reference note - CONTRIBUTING.md - added ARCHITECTURE.md reference, updated tool count Archived 10 completed planning docs to docs/archive/. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
315 lines
11 KiB
Markdown
315 lines
11 KiB
Markdown
# KiCAD MCP Server Architecture
|
|
|
|
This document describes the system architecture for contributors who want to understand, modify, or extend the server.
|
|
|
|
---
|
|
|
|
## System Overview
|
|
|
|
```
|
|
AI Assistant (Claude, etc.)
|
|
|
|
|
| MCP Protocol (JSON-RPC 2.0 over STDIO)
|
|
v
|
|
TypeScript MCP Server (src/)
|
|
|
|
|
| Spawn Python subprocess, pass JSON commands
|
|
v
|
|
Python KiCAD Interface (python/)
|
|
|
|
|
| pcbnew SWIG API or KiCAD IPC API
|
|
v
|
|
KiCAD 9.0+
|
|
```
|
|
|
|
The server has two layers:
|
|
|
|
1. **TypeScript layer** -- implements the MCP protocol, registers tools with schemas, validates input, manages the Python subprocess
|
|
2. **Python layer** -- interfaces with KiCAD's pcbnew API (SWIG bindings) or IPC API for actual PCB/schematic operations
|
|
|
|
---
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
KiCAD-MCP-Server/
|
|
src/ # TypeScript MCP server
|
|
server.ts # Main server, tool registration, Python subprocess
|
|
logger.ts # Logging configuration
|
|
tools/ # Tool definitions (one file per category)
|
|
registry.ts # Tool category definitions and lookup
|
|
router.ts # Router tools (list/search/execute)
|
|
project.ts # Project management tools
|
|
board.ts # Board operations tools
|
|
component.ts # Component tools
|
|
routing.ts # Routing tools
|
|
design-rules.ts # DRC tools
|
|
export.ts # Export tools
|
|
schematic.ts # Schematic tools
|
|
library.ts # Footprint library tools
|
|
library-symbol.ts # Symbol library tools
|
|
footprint.ts # Footprint creator tools
|
|
symbol-creator.ts # Symbol creator tools
|
|
datasheet.ts # Datasheet tools
|
|
jlcpcb-api.ts # JLCPCB integration tools
|
|
freerouting.ts # Autorouter tools
|
|
ui.ts # UI management tools
|
|
resources/ # MCP resource definitions
|
|
prompts/ # MCP prompt templates
|
|
utils/ # Utility functions
|
|
|
|
python/ # Python KiCAD interface
|
|
kicad_interface.py # Main entry point, command router
|
|
commands/ # Command implementations
|
|
project.py # Project operations
|
|
board.py # Board manipulation
|
|
component.py # PCB component operations
|
|
component_schematic.py # Schematic component operations
|
|
connection_schematic.py # Schematic wiring and connections
|
|
schematic.py # Schematic file management
|
|
routing.py # Trace routing
|
|
design_rules.py # DRC operations
|
|
export.py # File export
|
|
library.py # Footprint library access
|
|
library_symbol.py # Symbol library access
|
|
footprint.py # Custom footprint creation
|
|
symbol_creator.py # Custom symbol creation
|
|
datasheet_manager.py # Datasheet enrichment
|
|
jlcpcb.py # JLCPCB API client
|
|
jlcsearch.py # JLCSearch public API client
|
|
jlcpcb_parts.py # JLCPCB parts database
|
|
freerouting.py # Freerouting autorouter
|
|
svg_import.py # SVG to PCB polygon conversion
|
|
dynamic_symbol_loader.py # Dynamic symbol injection
|
|
wire_manager.py # S-expression wire creation
|
|
pin_locator.py # Pin position discovery
|
|
layers.py # Layer utilities
|
|
outline.py # Board outline utilities
|
|
size.py # Size/dimension utilities
|
|
view.py # Board rendering utilities
|
|
kicad_api/ # Backend abstraction
|
|
base.py # Abstract base class
|
|
factory.py # Backend auto-detection
|
|
swig_backend.py # pcbnew SWIG API backend
|
|
ipc_backend.py # KiCAD 9.0 IPC API backend
|
|
schemas/ # JSON Schema definitions
|
|
tool_schemas.py # Tool parameter schemas
|
|
resources/ # Resource handlers
|
|
templates/ # Schematic/project templates
|
|
tests/ # Python test suite
|
|
utils/ # Platform detection, helpers
|
|
|
|
docs/ # Documentation
|
|
config/ # Configuration examples
|
|
```
|
|
|
|
---
|
|
|
|
## TypeScript Layer
|
|
|
|
### Server Startup (`src/server.ts`)
|
|
|
|
1. Creates an MCP server instance
|
|
2. Registers all tools from each tool file (registerProjectTools, registerBoardTools, etc.)
|
|
3. Registers resources and prompts
|
|
4. Starts the STDIO transport for MCP communication
|
|
5. On first tool call, spawns the Python subprocess
|
|
|
|
### Tool Registration
|
|
|
|
Each tool file exports a `register*Tools(server, callKicadScript)` function that:
|
|
- Defines tool name, description, and Zod schema for parameters
|
|
- Registers a handler that calls `callKicadScript(command, args)`
|
|
|
|
Example from `src/tools/project.ts`:
|
|
```typescript
|
|
server.tool(
|
|
"create_project",
|
|
"Create a new KiCAD project",
|
|
{ name: z.string(), path: z.string() },
|
|
async (args) => {
|
|
const result = await callKicadScript("create_project", args);
|
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
}
|
|
);
|
|
```
|
|
|
|
### Tool Router (`src/tools/router.ts` and `src/tools/registry.ts`)
|
|
|
|
The router pattern reduces AI context usage:
|
|
- `registry.ts` defines tool categories and which tools are "direct" (always visible) vs "routed" (discoverable)
|
|
- `router.ts` provides 4 meta-tools: `list_tool_categories`, `get_category_tools`, `search_tools`, `execute_tool`
|
|
- Routed tools are not registered as individual MCP tools -- they are invoked through `execute_tool`
|
|
|
|
### Python Subprocess Communication
|
|
|
|
`callKicadScript(command, args)` in `server.ts`:
|
|
1. Spawns `python3 python/kicad_interface.py` (if not already running)
|
|
2. Sends a JSON message: `{"command": "...", "params": {...}}`
|
|
3. Reads the JSON response
|
|
4. Returns the result to the MCP tool handler
|
|
|
|
---
|
|
|
|
## Python Layer
|
|
|
|
### Main Entry Point (`python/kicad_interface.py`)
|
|
|
|
- Reads JSON commands from stdin
|
|
- Routes commands to the appropriate handler
|
|
- Manages the pcbnew board object lifecycle
|
|
- Handles backend selection (SWIG vs IPC)
|
|
- Auto-saves after board-modifying operations
|
|
|
|
### Command Routing
|
|
|
|
Commands are routed by name to handler methods. The mapping is defined in `kicad_interface.py`. Each handler:
|
|
1. Receives a params dict
|
|
2. Calls the appropriate command class method
|
|
3. Returns a result dict with `success`, `message`, and any additional data
|
|
|
|
### Backend System (`python/kicad_api/`)
|
|
|
|
Two backends for interacting with KiCAD:
|
|
|
|
**SWIG Backend** (default):
|
|
- Direct Python bindings to KiCAD's C++ API via SWIG
|
|
- Operates on files -- loads .kicad_pcb, modifies in memory, saves back
|
|
- Works without KiCAD running
|
|
- Requires manual UI reload to see changes
|
|
|
|
**IPC Backend** (experimental):
|
|
- Communicates with running KiCAD via IPC API socket
|
|
- Changes appear in the UI immediately
|
|
- Requires KiCAD 9.0+ running with IPC enabled
|
|
- Falls back to SWIG when unavailable
|
|
|
|
`factory.py` auto-detects which backend to use.
|
|
|
|
### Schematic System
|
|
|
|
Schematic manipulation uses a different stack than PCB operations:
|
|
- **kicad-skip** library for reading/modifying schematic files
|
|
- **S-expression parsing** for direct file manipulation (wires, symbols)
|
|
- **DynamicSymbolLoader** for injecting any KiCad symbol into a schematic
|
|
- **WireManager** for creating wires via S-expression injection
|
|
- **PinLocator** for discovering pin positions with rotation support
|
|
|
|
---
|
|
|
|
## Adding a New Tool
|
|
|
|
### Step 1: Define the TypeScript Schema
|
|
|
|
Create or edit a file in `src/tools/`. Register the tool with `server.tool()`:
|
|
|
|
```typescript
|
|
server.tool(
|
|
"my_new_tool",
|
|
"Description of what the tool does",
|
|
{
|
|
param1: z.string().describe("Description of param1"),
|
|
param2: z.number().optional().describe("Optional param2"),
|
|
},
|
|
async (args) => {
|
|
const result = await callKicadScript("my_new_tool", args);
|
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
}
|
|
);
|
|
```
|
|
|
|
### Step 2: Add to Registry (if routed)
|
|
|
|
If the tool should be discoverable via the router (not always visible), add it to a category in `src/tools/registry.ts`:
|
|
|
|
```typescript
|
|
{
|
|
name: "category_name",
|
|
tools: ["existing_tool", "my_new_tool"]
|
|
}
|
|
```
|
|
|
|
If the tool should always be visible, add it to `directToolNames` instead.
|
|
|
|
### Step 3: Import in server.ts
|
|
|
|
Import and call the registration function in `src/server.ts`:
|
|
|
|
```typescript
|
|
import { registerMyTools } from "./tools/my-tools.js";
|
|
registerMyTools(server, callKicadScript);
|
|
```
|
|
|
|
### Step 4: Implement the Python Handler
|
|
|
|
Add a handler in `python/kicad_interface.py` or create a new command module in `python/commands/`:
|
|
|
|
```python
|
|
def handle_my_new_tool(self, params):
|
|
# Implementation using pcbnew API
|
|
return {"success": True, "message": "Done", "data": result}
|
|
```
|
|
|
|
Route the command in the main handler:
|
|
|
|
```python
|
|
elif command == "my_new_tool":
|
|
return self.handle_my_new_tool(params)
|
|
```
|
|
|
|
### Step 5: Build and Test
|
|
|
|
```bash
|
|
npm run build # Compile TypeScript
|
|
npm run test:py # Run Python tests
|
|
```
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Python Tests
|
|
|
|
Located in `python/tests/`. Run with:
|
|
```bash
|
|
pytest python/tests/ -v
|
|
```
|
|
|
|
Key test files:
|
|
- `test_schematic_tools.py` -- schematic tool tests
|
|
- `test_freerouting.py` -- autorouter tests
|
|
- `test_delete_schematic_component.py` -- component deletion tests
|
|
- `test_schematic_component_fields.py` -- field inspection tests
|
|
- `test_platform_helper.py` -- platform detection tests
|
|
|
|
### Manual Testing
|
|
|
|
1. Build the server: `npm run build`
|
|
2. Configure in Claude Desktop or Claude Code
|
|
3. Test tools interactively through your MCP client
|
|
|
|
---
|
|
|
|
## Key Design Decisions
|
|
|
|
- **TypeScript + Python split**: TypeScript handles MCP protocol (well-supported SDK), Python handles KiCAD (only available API)
|
|
- **Router pattern**: Reduces AI context from ~80K tokens (122 tools) to manageable size
|
|
- **Auto-save**: Every board-modifying SWIG operation auto-saves to prevent data loss
|
|
- **Dynamic symbol loading**: Works around kicad-skip's inability to create symbols from scratch
|
|
- **S-expression wire injection**: Works around kicad-skip's inability to create wires
|
|
|
|
---
|
|
|
|
## Source Files Reference
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `src/server.ts` | MCP server, subprocess management |
|
|
| `src/tools/registry.ts` | Tool categories and organization |
|
|
| `src/tools/router.ts` | Router meta-tools |
|
|
| `python/kicad_interface.py` | Python entry point, command routing |
|
|
| `python/kicad_api/factory.py` | Backend selection |
|
|
| `python/commands/dynamic_symbol_loader.py` | Symbol injection system |
|
|
| `python/commands/wire_manager.py` | Wire creation engine |
|
|
| `python/commands/pin_locator.py` | Pin position discovery |
|