@hybridlabor-api/bdb-hardware-pcb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -0
- package/config/mcp/antigravity.json +22 -0
- package/config/mcp/claude.json +22 -0
- package/config/mcp/codex.toml +25 -0
- package/docs/adr/ADR-001-KICAD-OPENSCAD-MCP-STRATEGY.md +334 -0
- package/docs/review_documentation.md +121 -0
- package/installer.js +358 -0
- package/mcp_servers/kicad-mcp-server/.env.example +22 -0
- package/mcp_servers/kicad-mcp-server/.github/workflows/ci.yml +36 -0
- package/mcp_servers/kicad-mcp-server/CLAUDE.md +487 -0
- package/mcp_servers/kicad-mcp-server/README.md +316 -0
- package/mcp_servers/kicad-mcp-server/docs/DEVICE_TREE.md +416 -0
- package/mcp_servers/kicad-mcp-server/docs/INSTALLATION.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/PIN_ANALYSIS.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/README.md +240 -0
- package/mcp_servers/kicad-mcp-server/docs/TESTING.md +613 -0
- package/mcp_servers/kicad-mcp-server/docs/VALIDATION.md +268 -0
- package/mcp_servers/kicad-mcp-server/pyproject.toml +96 -0
- package/mcp_servers/kicad-mcp-server/requirements-dev.txt +16 -0
- package/mcp_servers/kicad-mcp-server/requirements-test.txt +24 -0
- package/mcp_servers/kicad-mcp-server/requirements.txt +13 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__init__.py +3 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__main__.py +17 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/config.py +46 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/types.py +87 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/netlist_parser.py +234 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser.py +375 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser_kicad.py +327 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/schematic_parser.py +902 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/server.py +71 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/arduino/connectivity_test.cpp.j2 +189 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/atmega.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/esp32.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/nrf52.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/stm32f4.dts.j2 +89 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/esp_idf/test_suite.c.j2 +340 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/pytest/test_connectivity.py.j2 +147 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/st_hal/hal_test.c.j2 +313 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_gpio_test.py.j2 +99 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_i2c_test.py.j2 +117 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_pinmux_test.py.j2 +43 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_spi_test.py.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_gpio_test.c.j2 +113 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_i2c_test.c.j2 +101 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_spi_test.c.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/unittest/test_schematic.py.j2 +172 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/__init__.py +36 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/device_tree.py +1187 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/hierarchical_analysis.py +211 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/netlist.py +320 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/parts_registry.py +142 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb.py +955 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb_layout.py +308 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pin_analysis.py +765 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/project.py +196 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic.py +319 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_editor.py +674 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_search.py +158 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/validation.py +866 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/visualization.py +225 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/file_handlers.py +65 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_cli.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_version.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/parts_registry.py +197 -0
- package/mcp_servers/kicad-mcp-server/tests/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/examples/ESP32S3_TEST.md +219 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/README.md +65 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_pcb.kicad_pcb +177 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_schematic.kicad_sch +145 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/child.kicad_sch +24 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/root.kicad_sch +38 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_hierarchical_labels.py +195 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_kicad_cli.py +116 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_netlist_cache_path.py +29 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic.py +189 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic_hierarchy.py +69 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_visualization.py +136 -0
- package/mcp_servers/kicad-mcp-server/uv.lock +2873 -0
- package/mcp_servers/openscad-mcp-server/.dockerignore +9 -0
- package/mcp_servers/openscad-mcp-server/.github/workflows/test.yml +40 -0
- package/mcp_servers/openscad-mcp-server/Dockerfile +29 -0
- package/mcp_servers/openscad-mcp-server/LICENSE +21 -0
- package/mcp_servers/openscad-mcp-server/README.md +154 -0
- package/mcp_servers/openscad-mcp-server/docs/audit.md +56 -0
- package/mcp_servers/openscad-mcp-server/docs/docker.md +66 -0
- package/mcp_servers/openscad-mcp-server/docs/issue-followup.md +19 -0
- package/mcp_servers/openscad-mcp-server/docs/jetson.md +17 -0
- package/mcp_servers/openscad-mcp-server/glama.json +4 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.md +15 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.original.md +294 -0
- package/mcp_servers/openscad-mcp-server/legacy/implementation_plan.md +100 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/download_sam2_checkpoint.py +115 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/ai/sam_segmentation.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/models/threestudio_generator.py +231 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/workflow/image_to_model_pipeline.py +260 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/test_sam2_segmentation.py +96 -0
- package/mcp_servers/openscad-mcp-server/legacy/requirements.txt +57 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/README.md +39 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/ai-driven-code-generation.md +122 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/export-formats.md +76 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/ai/ai_service.py.md +51 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/main.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/models/code_generator.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/nlp/parameter_extractor.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/ai/natural-language-processing.md +78 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/nlp/parameter-extraction.md +173 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/export-formats.md +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/openscad-basics.md +66 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/primitive-testing.md +79 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/ai_service.py +257 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/gemini_api.py +161 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/venice_api.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/config.py +121 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py +1456 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py.new +404 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main_remote.py +401 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/code_generator.py +321 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/cuda_mvs.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/scad_templates/basic_shapes.scad +144 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/parameter_extractor.py +388 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/wrapper.py +418 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/printer_discovery.py +471 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/connection_manager.py +537 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_client.py +435 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_server.py +787 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/error_handling.py +415 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/primitive_tester.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/test_primitives.py +98 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/cad_exporter.py +241 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/format_validator.py +206 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_exporter.py +140 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_repair.py +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_validator.py +123 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/headless_renderer.py +52 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/renderer.py +177 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/web_interface.py +639 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/image_approval.py +148 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/multi_view_to_model_pipeline.py +338 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_complete_workflow.py +374 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_cuda_mvs.py +191 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_gemini_api.py +168 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval.py +192 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval_workflow.py +251 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_to_model_pipeline.py +145 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_model_selection.py +41 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_multi_view_pipeline.py +290 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_primitives.sh +13 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_rabbit_direct.py +71 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_remote_cuda_mvs.py +283 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_venice_example.py +69 -0
- package/mcp_servers/openscad-mcp-server/pyproject.toml +33 -0
- package/mcp_servers/openscad-mcp-server/requirements.txt +2 -0
- package/mcp_servers/openscad-mcp-server/scad/simple_cube.scad +2 -0
- package/mcp_servers/openscad-mcp-server/scripts/test_docker.py +220 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__init__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__main__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/engine.py +94 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/geometry.py +242 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/server.py +245 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/service.py +190 -0
- package/mcp_servers/openscad-mcp-server/tests/conftest.py +17 -0
- package/mcp_servers/openscad-mcp-server/tests/test_engine.py +37 -0
- package/mcp_servers/openscad-mcp-server/tests/test_geometry.py +106 -0
- package/mcp_servers/openscad-mcp-server/tests/test_integration.py +172 -0
- package/mcp_servers/openscad-mcp-server/tests/test_transports.py +314 -0
- package/mcp_servers/openscad-mcp-server/uv.lock +1123 -0
- package/package.json +44 -0
- package/scripts/install_mcps.sh +86 -0
- package/scripts/openscad_wrapper.sh +62 -0
- package/scripts/run_kicad_mcp.sh +25 -0
- package/scripts/run_openscad_mcp.sh +41 -0
- package/scripts/test_mcp_connection.py +626 -0
- package/scripts/test_mcp_connection.sh +168 -0
- package/skills/code-first-hardware-design/SKILL.md +260 -0
- package/skills/pcb-constraint-definition/SKILL.md +236 -0
- package/skills/pcb-layout-routing-automation/SKILL.md +153 -0
- package/skills/pcb-validation-dfm-signoff/SKILL.md +194 -0
- package/skills/schematic-datasheet-analysis/SKILL.md +202 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Design Rule Checking Guide
|
|
2
|
+
|
|
3
|
+
Comprehensive guide for using KiCad MCP Server's design rule checking capabilities.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The validation tools provide automated design rule checking (DRC) and electrical rules check (ERC) to ensure your hardware designs are correct before manufacturing.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
### ERC Tools
|
|
12
|
+
|
|
13
|
+
#### `run_erc(schematic_path: str) -> str`
|
|
14
|
+
|
|
15
|
+
Run Electrical Rules Check on a schematic file.
|
|
16
|
+
|
|
17
|
+
**What it checks:**
|
|
18
|
+
- Unconnected pins
|
|
19
|
+
- Power conflicts (VCC to VCC, GND to GND)
|
|
20
|
+
- Multiple outputs on same net
|
|
21
|
+
- Pin type mismatches
|
|
22
|
+
|
|
23
|
+
**Example:**
|
|
24
|
+
```python
|
|
25
|
+
result = run_erc("board.kicad_sch")
|
|
26
|
+
if "X" in result:
|
|
27
|
+
print("ERC violations found")
|
|
28
|
+
else:
|
|
29
|
+
print("No ERC violations")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Returns:**
|
|
33
|
+
- ✅ Pass: No violations detected
|
|
34
|
+
- ❌ Fail: List of violations with severity and descriptions
|
|
35
|
+
|
|
36
|
+
#### `get_erc_violations(schematic_path: str, severity: str = "") -> str`
|
|
37
|
+
|
|
38
|
+
Get filtered ERC violations by severity.
|
|
39
|
+
|
|
40
|
+
**Parameters:**
|
|
41
|
+
- `severity`: "error", "warning", or "" for all
|
|
42
|
+
|
|
43
|
+
**Example:**
|
|
44
|
+
```python
|
|
45
|
+
# Get only errors
|
|
46
|
+
errors = get_erc_violations("board.kicad_sch", severity="error")
|
|
47
|
+
|
|
48
|
+
# Get all violations
|
|
49
|
+
all_violations = get_erc_violations("board.kicad_sch")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### DRC Tools
|
|
53
|
+
|
|
54
|
+
#### `run_drc(pcb_path: str) -> str`
|
|
55
|
+
|
|
56
|
+
Run Design Rules Check on a PCB file.
|
|
57
|
+
|
|
58
|
+
**What it checks:**
|
|
59
|
+
- Clearance violations (< 0.15mm default)
|
|
60
|
+
- Track spacing violations
|
|
61
|
+
- Missing connections (unrouted nets)
|
|
62
|
+
- Pad/footprint overlaps
|
|
63
|
+
- Board edge constraints
|
|
64
|
+
|
|
65
|
+
**Example:**
|
|
66
|
+
```python
|
|
67
|
+
result = run_drc("board.kicad_pcb")
|
|
68
|
+
if "X" in result:
|
|
69
|
+
print("DRC violations found")
|
|
70
|
+
# Parse violations and fix in KiCad
|
|
71
|
+
else:
|
|
72
|
+
print("No DRC violations - ready for manufacturing")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### `get_drc_violations(pcb_path: str, violation_type: str = "") -> str`
|
|
76
|
+
|
|
77
|
+
Get filtered DRC violations by type.
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
- `violation_type`: "clearance", "spacing", "missing_connection", or "" for all
|
|
81
|
+
|
|
82
|
+
**Example:**
|
|
83
|
+
```python
|
|
84
|
+
# Get only clearance violations
|
|
85
|
+
clearance_issues = get_drc_violations("board.kicad_pcb", violation_type="clearance")
|
|
86
|
+
|
|
87
|
+
# Get all violations
|
|
88
|
+
all_violations = get_drc_violations("board.kicad_pcb")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Export Tools
|
|
92
|
+
|
|
93
|
+
#### `export_erc_report(schematic_path: str, output_path: str = "") -> str`
|
|
94
|
+
#### `export_drc_report(pcb_path: str, output_path: str = "") -> str`
|
|
95
|
+
|
|
96
|
+
Export validation reports to files for documentation.
|
|
97
|
+
|
|
98
|
+
**Example:**
|
|
99
|
+
```python
|
|
100
|
+
export_erc_report("board.kicad_sch", "reports/erc_report.txt")
|
|
101
|
+
export_drc_report("board.kicad_pcb", "reports/drc_report.txt")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Usage Patterns
|
|
105
|
+
|
|
106
|
+
### Pre-Manufacturing Checklist
|
|
107
|
+
|
|
108
|
+
Before sending your design to manufacturing:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# 1. Run ERC on schematic
|
|
112
|
+
erc_result = run_erc("board.kicad_sch")
|
|
113
|
+
assert "X" not in erc_result, "Fix ERC violations first"
|
|
114
|
+
|
|
115
|
+
# 2. Run DRC on PCB
|
|
116
|
+
drc_result = run_drc("board.kicad_pcb")
|
|
117
|
+
assert "X" not in drc_result, "Fix DRC violations first"
|
|
118
|
+
|
|
119
|
+
# 3. Export reports for documentation
|
|
120
|
+
export_erc_report("board.kicad_sch", "manufacturing/erc.txt")
|
|
121
|
+
export_drc_report("board.kicad_pcb", "manufacturing/drc.txt")
|
|
122
|
+
|
|
123
|
+
print("OK Design ready for manufacturing")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### CI/CD Integration
|
|
127
|
+
|
|
128
|
+
Automated validation in continuous integration:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# In your CI pipeline
|
|
132
|
+
python -c "
|
|
133
|
+
from kicad_mcp_server.tools import validation
|
|
134
|
+
import sys
|
|
135
|
+
|
|
136
|
+
# Run checks
|
|
137
|
+
erc = validation.run_erc('board.kicad_sch')
|
|
138
|
+
drc = validation.run_drc('board.kicad_pcb')
|
|
139
|
+
|
|
140
|
+
# Fail if violations found
|
|
141
|
+
if 'X' in erc or 'X' in drc:
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Iterative Design Process
|
|
147
|
+
|
|
148
|
+
During design iteration:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
while True:
|
|
152
|
+
# Make design changes in KiCad
|
|
153
|
+
input("Make changes in KiCad, then press Enter...")
|
|
154
|
+
|
|
155
|
+
# Run validation
|
|
156
|
+
erc = run_erc("board.kicad_sch")
|
|
157
|
+
drc = run_drc("board.kicad_pcb")
|
|
158
|
+
|
|
159
|
+
# Check for violations
|
|
160
|
+
if "X" not in erc and "X" not in drc:
|
|
161
|
+
print("OK Design is clean!")
|
|
162
|
+
break
|
|
163
|
+
|
|
164
|
+
# Show violations to fix
|
|
165
|
+
print(erc)
|
|
166
|
+
print(drc)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Common Violations
|
|
170
|
+
|
|
171
|
+
### ERC Violations
|
|
172
|
+
|
|
173
|
+
**Unconnected Input Pin**
|
|
174
|
+
```
|
|
175
|
+
X ERC violation detected
|
|
176
|
+
Type: unconnected_input
|
|
177
|
+
Component: U1
|
|
178
|
+
Pin: 3 (RESET)
|
|
179
|
+
Description: Unconnected input pin may cause undefined behavior
|
|
180
|
+
```
|
|
181
|
+
**Fix:** Connect the pin to appropriate signal or add pull-up/pull-down resistor.
|
|
182
|
+
|
|
183
|
+
**Multiple Outputs on Same Net**
|
|
184
|
+
```
|
|
185
|
+
X ERC violation detected
|
|
186
|
+
Type: multiple_outputs
|
|
187
|
+
Components: U1:8, U2:3
|
|
188
|
+
Description: Multiple outputs on same net can cause damage
|
|
189
|
+
```
|
|
190
|
+
**Fix:** Remove one output or add proper isolation (diode, buffer).
|
|
191
|
+
|
|
192
|
+
**Power Conflict**
|
|
193
|
+
```
|
|
194
|
+
X ERC violation detected
|
|
195
|
+
Type: power_conflict
|
|
196
|
+
Components: U1:1, U2:1
|
|
197
|
+
Description: Multiple power outputs on same net
|
|
198
|
+
```
|
|
199
|
+
**Fix:** Ensure only one power source per net or use proper power distribution.
|
|
200
|
+
|
|
201
|
+
### DRC Violations
|
|
202
|
+
|
|
203
|
+
**Clearance Violation**
|
|
204
|
+
```
|
|
205
|
+
X DRC violation detected
|
|
206
|
+
Type: clearance
|
|
207
|
+
Location: (45.2, 23.1)
|
|
208
|
+
Description: Insufficient clearance (0.12mm < 0.15mm required)
|
|
209
|
+
```
|
|
210
|
+
**Fix:** Increase spacing between tracks/pads to meet clearance requirements.
|
|
211
|
+
|
|
212
|
+
**Missing Connection**
|
|
213
|
+
```
|
|
214
|
+
X DRC violation detected
|
|
215
|
+
Type: missing_connection
|
|
216
|
+
Net: I2C_SDA
|
|
217
|
+
Description: Unrouted net detected
|
|
218
|
+
```
|
|
219
|
+
**Fix:** Route the connection in KiCad or mark as no-route if intentional.
|
|
220
|
+
|
|
221
|
+
## Best Practices
|
|
222
|
+
|
|
223
|
+
1. **Run ERC Early:** Check schematic frequently during design
|
|
224
|
+
2. **Run DRC After Layout:** Check PCB after routing is complete
|
|
225
|
+
3. **Fix Errors First:** Always fix error-level violations before warnings
|
|
226
|
+
4. **Document Exceptions:** Some warnings may be acceptable design choices
|
|
227
|
+
5. **Version Control:** Commit validation reports with design files
|
|
228
|
+
|
|
229
|
+
## Troubleshooting
|
|
230
|
+
|
|
231
|
+
**Issue:** kicad-cli not found
|
|
232
|
+
```bash
|
|
233
|
+
# Install KiCad or add to PATH
|
|
234
|
+
export PATH=$PATH:/path/to/kicad/bin
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Issue:** False positives in ERC
|
|
238
|
+
- Some warnings may be intentional design choices
|
|
239
|
+
- Use `get_erc_violations()` with severity filters to focus on errors
|
|
240
|
+
- Document design exceptions in your project notes
|
|
241
|
+
|
|
242
|
+
**Issue:** DRC takes too long
|
|
243
|
+
- Check design rules in KiCad (Board Setup → Design Rules)
|
|
244
|
+
- Simplify rules if too strict for your application
|
|
245
|
+
- Use `get_drc_violations()` to check specific violation types
|
|
246
|
+
|
|
247
|
+
## Integration with Other Tools
|
|
248
|
+
|
|
249
|
+
### Before Device Tree Generation
|
|
250
|
+
```python
|
|
251
|
+
# Always validate before generating code
|
|
252
|
+
validate_pin_configuration("board.kicad_sch") # Run ERC/DRC first
|
|
253
|
+
generate_device_tree("board.kicad_sch", "stm32f4", "board.dts")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Before Test Generation
|
|
257
|
+
```python
|
|
258
|
+
# Ensure design is valid before generating tests
|
|
259
|
+
run_erc("board.kicad_sch")
|
|
260
|
+
run_drc("board.kicad_pcb")
|
|
261
|
+
generate_hardware_tests("board.kicad_sch", "pytest")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Resources
|
|
265
|
+
|
|
266
|
+
- [KiCad Design Rules](https://docs.kicad.org/doxygen/latest/)
|
|
267
|
+
- [IPC Standards](https://www.ipc.org/)
|
|
268
|
+
- [Project-specific design rules](board.kicad_pcb setup)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kicad-mcp-server"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Model Context Protocol server for KiCad schematic/PCB analysis and validation"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Seeed Studio" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["kicad", "mcp", "schematic", "pcb", "eda"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Python :: 3.14",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
dependencies = [
|
|
29
|
+
# The upper bounds are load-bearing. Without them pip/uv resolve
|
|
30
|
+
# fastmcp 2.14.1 + mcp 2.0.0, which install WITHOUT pydantic-settings,
|
|
31
|
+
# and the server dies on import (ModuleNotFoundError: pydantic_settings).
|
|
32
|
+
# Keep these in sync with requirements.txt.
|
|
33
|
+
"mcp[cli]>=1.27,<2",
|
|
34
|
+
"fastmcp>=3.2,<4",
|
|
35
|
+
"kicad-skip>=0.2.5",
|
|
36
|
+
"pydantic>=2.0.0",
|
|
37
|
+
"python-dotenv>=1.0.0",
|
|
38
|
+
"jinja2>=3.1.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
test = [
|
|
43
|
+
"pytest>=7.0.0",
|
|
44
|
+
"pytest-asyncio>=0.21.0",
|
|
45
|
+
"pytest-cov>=4.0.0",
|
|
46
|
+
"pytest-mock>=3.12.0",
|
|
47
|
+
]
|
|
48
|
+
hardware = [
|
|
49
|
+
"RPi.GPIO>=0.7.0; platform_machine == 'aarch64' or platform_machine == 'armv7l'",
|
|
50
|
+
"smbus2>=0.4.0",
|
|
51
|
+
"spidev>=3.5; platform_machine == 'aarch64' or platform_machine == 'armv7l'",
|
|
52
|
+
"pyserial>=3.5",
|
|
53
|
+
]
|
|
54
|
+
dev = [
|
|
55
|
+
"pytest>=7.0.0",
|
|
56
|
+
"pytest-asyncio>=0.21.0",
|
|
57
|
+
"black>=23.0.0",
|
|
58
|
+
"ruff>=0.1.0",
|
|
59
|
+
"mypy>=1.0.0",
|
|
60
|
+
]
|
|
61
|
+
all = [
|
|
62
|
+
"kicad-mcp-server[test,hardware,dev]"
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[project.scripts]
|
|
66
|
+
kicad-mcp-server = "kicad_mcp_server.__main__:main"
|
|
67
|
+
|
|
68
|
+
[project.urls]
|
|
69
|
+
Homepage = "https://github.com/Seeed-Studio/kicad-mcp-server"
|
|
70
|
+
Documentation = "https://github.com/Seeed-Studio/kicad-mcp-server#readme"
|
|
71
|
+
Issues = "https://github.com/Seeed-Studio/kicad-mcp-server/issues"
|
|
72
|
+
|
|
73
|
+
[tool.hatch.build.targets.wheel]
|
|
74
|
+
packages = ["src/kicad_mcp_server"]
|
|
75
|
+
|
|
76
|
+
[tool.black]
|
|
77
|
+
line-length = 100
|
|
78
|
+
target-version = ["py310", "py311", "py312", "py313", "py314"]
|
|
79
|
+
|
|
80
|
+
[tool.ruff]
|
|
81
|
+
line-length = 100
|
|
82
|
+
target-version = "py310"
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint]
|
|
85
|
+
select = ["E", "F", "W", "I", "N", "UP", "B", "C4"]
|
|
86
|
+
ignore = ["E501"]
|
|
87
|
+
|
|
88
|
+
[tool.mypy]
|
|
89
|
+
python_version = "3.10"
|
|
90
|
+
warn_return_any = true
|
|
91
|
+
warn_unused_configs = true
|
|
92
|
+
disallow_untyped_defs = true
|
|
93
|
+
|
|
94
|
+
[tool.pytest.ini_options]
|
|
95
|
+
asyncio_mode = "auto"
|
|
96
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Development dependencies for KiCad MCP Server
|
|
2
|
+
-r requirements.txt
|
|
3
|
+
|
|
4
|
+
# Testing
|
|
5
|
+
pytest>=7.0.0
|
|
6
|
+
pytest-asyncio>=0.21.0
|
|
7
|
+
pytest-cov>=4.0.0
|
|
8
|
+
|
|
9
|
+
# Code quality
|
|
10
|
+
black>=23.0.0
|
|
11
|
+
ruff>=0.1.0
|
|
12
|
+
mypy>=1.0.0
|
|
13
|
+
|
|
14
|
+
# Documentation
|
|
15
|
+
sphinx>=7.0.0
|
|
16
|
+
sphinx-rtd-theme>=1.3.0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Testing dependencies for hardware testing
|
|
2
|
+
# These are optional dependencies for running hardware tests with actual hardware interaction
|
|
3
|
+
|
|
4
|
+
# Python testing framework
|
|
5
|
+
pytest>=7.0.0
|
|
6
|
+
pytest-asyncio>=0.21.0
|
|
7
|
+
pytest-cov>=4.0.0
|
|
8
|
+
pytest-mock>=3.12.0
|
|
9
|
+
|
|
10
|
+
# Hardware interaction libraries (optional)
|
|
11
|
+
# Raspberry Pi GPIO
|
|
12
|
+
RPi.GPIO>=0.7.0; platform_machine == "aarch64" or platform_machine == "armv7l"
|
|
13
|
+
|
|
14
|
+
# I2C communication
|
|
15
|
+
smbus2>=0.4.0
|
|
16
|
+
|
|
17
|
+
# SPI communication
|
|
18
|
+
spidev>=3.5; platform_machine == "aarch64" or platform_machine == "armv7l"
|
|
19
|
+
|
|
20
|
+
# Serial communication
|
|
21
|
+
pyserial>=3.5
|
|
22
|
+
|
|
23
|
+
# Mock hardware for testing
|
|
24
|
+
mock>=4.0.0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Core dependencies for KiCad MCP Server
|
|
2
|
+
#
|
|
3
|
+
# The upper bounds are load-bearing. Without them pip/uv resolve
|
|
4
|
+
# fastmcp 2.14.1 + mcp 2.0.0, which install WITHOUT pydantic-settings, and
|
|
5
|
+
# the server dies on import:
|
|
6
|
+
# ModuleNotFoundError: No module named 'pydantic_settings'
|
|
7
|
+
# fastmcp 3.x is what actually provides the FastMCP API this server uses.
|
|
8
|
+
mcp[cli]>=1.27,<2
|
|
9
|
+
fastmcp>=3.2,<4
|
|
10
|
+
kicad-skip>=0.2.5
|
|
11
|
+
pydantic>=2.0.0
|
|
12
|
+
python-dotenv>=1.0.0
|
|
13
|
+
jinja2>=3.1.0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Main entry point for KiCad MCP Server."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main() -> None:
|
|
6
|
+
"""Entry point for running the MCP server."""
|
|
7
|
+
from .server import mcp
|
|
8
|
+
|
|
9
|
+
# show_banner=False skips log_server_banner(), which performs a *blocking*
|
|
10
|
+
# httpx.get("https://pypi.org/pypi/fastmcp/json") before stdio_server()
|
|
11
|
+
# opens the transport. That delays the initialize handshake and stalls the
|
|
12
|
+
# client entirely when PyPI is slow or unreachable.
|
|
13
|
+
mcp.run(show_banner=False)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
main()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Configuration management for KiCad MCP Server."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from dotenv import load_dotenv
|
|
6
|
+
|
|
7
|
+
# Load environment variables from .env file
|
|
8
|
+
load_dotenv()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Config:
|
|
12
|
+
"""Configuration settings for the MCP server."""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""Initialize configuration from environment variables."""
|
|
16
|
+
# KiCad project search paths
|
|
17
|
+
project_paths_str = os.getenv("KICAD_PROJECT_PATHS", "")
|
|
18
|
+
self.kicad_project_paths: list[str] = [
|
|
19
|
+
p.strip() for p in project_paths_str.split(",") if p.strip()
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
# Summary settings
|
|
23
|
+
self.default_summary_detail_level: str = os.getenv(
|
|
24
|
+
"DEFAULT_SUMMARY_DETAIL_LEVEL", "standard"
|
|
25
|
+
)
|
|
26
|
+
self.include_nets_in_summary: bool = (
|
|
27
|
+
os.getenv("INCLUDE_NETS_IN_SUMMARY", "true").lower() == "true"
|
|
28
|
+
)
|
|
29
|
+
self.include_power_in_summary: bool = (
|
|
30
|
+
os.getenv("INCLUDE_POWER_IN_SUMMARY", "true").lower() == "true"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Test generation settings
|
|
34
|
+
self.default_test_framework: str = os.getenv("DEFAULT_TEST_FRAMEWORK", "pytest")
|
|
35
|
+
self.default_test_type: str = os.getenv("DEFAULT_TEST_TYPE", "connectivity")
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def get_instance(cls) -> "Config":
|
|
39
|
+
"""Get singleton instance of Config."""
|
|
40
|
+
if not hasattr(cls, "_instance"):
|
|
41
|
+
cls._instance = cls()
|
|
42
|
+
return cls._instance
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Global config instance
|
|
46
|
+
config = Config.get_instance()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Data models for KiCad MCP Server."""
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Type definitions for KiCad MCP Server."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ComponentInfo(BaseModel):
|
|
8
|
+
"""Information about a schematic component."""
|
|
9
|
+
|
|
10
|
+
reference: str = Field(description="Component reference designator (e.g., R1, U1)")
|
|
11
|
+
value: str = Field(description="Component value (e.g., 10k, ATmega328P)")
|
|
12
|
+
footprint: str | None = Field(default=None, description="Assigned footprint")
|
|
13
|
+
library_id: str = Field(description="Symbol library identifier")
|
|
14
|
+
properties: dict[str, str] = Field(default_factory=dict, description="Additional properties")
|
|
15
|
+
position: tuple[float, float] = Field(description="X, Y coordinates in schematic")
|
|
16
|
+
unit: int | None = Field(default=None, description="Multi-unit part unit number")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NetInfo(BaseModel):
|
|
20
|
+
"""Information about a net."""
|
|
21
|
+
|
|
22
|
+
name: str = Field(description="Net name")
|
|
23
|
+
code: int = Field(description="Internal net code")
|
|
24
|
+
node_count: int = Field(description="Number of connected pins")
|
|
25
|
+
pins: list[str] = Field(default_factory=list, description="Connected pins (ref:pin)")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PinInfo(BaseModel):
|
|
29
|
+
"""Information about a component pin."""
|
|
30
|
+
|
|
31
|
+
number: str = Field(description="Pin number")
|
|
32
|
+
name: str = Field(description="Pin name/function")
|
|
33
|
+
type: str = Field(description="Electrical type (input, output, power, etc.)")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SymbolInfo(BaseModel):
|
|
37
|
+
"""Detailed information about a schematic symbol."""
|
|
38
|
+
|
|
39
|
+
reference: str = Field(description="Component reference designator")
|
|
40
|
+
value: str = Field(description="Component value")
|
|
41
|
+
library_id: str = Field(description="Symbol library identifier")
|
|
42
|
+
pins: list[PinInfo] = Field(default_factory=list, description="Pin definitions")
|
|
43
|
+
properties: dict[str, str] = Field(default_factory=dict, description="Symbol properties")
|
|
44
|
+
unit_count: int = Field(default=1, description="Number of units in symbol")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FootprintInfo(BaseModel):
|
|
48
|
+
"""Information about a PCB footprint."""
|
|
49
|
+
|
|
50
|
+
reference: str = Field(description="Component reference designator")
|
|
51
|
+
footprint_id: str = Field(description="Footprint library identifier")
|
|
52
|
+
value: str = Field(description="Component value")
|
|
53
|
+
layer: str = Field(description="PCB layer (F.Cu, B.Cu, etc.)")
|
|
54
|
+
position: tuple[float, float] = Field(description="X, Y coordinates")
|
|
55
|
+
rotation: float = Field(description="Rotation angle in degrees")
|
|
56
|
+
pads: int = Field(default=0, description="Number of pads")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PCBStatistics(BaseModel):
|
|
60
|
+
"""Statistics about a PCB design."""
|
|
61
|
+
|
|
62
|
+
total_footprints: int = Field(description="Total number of footprints")
|
|
63
|
+
total_pads: int = Field(description="Total number of pads")
|
|
64
|
+
total_tracks: int = Field(description="Total number of track segments")
|
|
65
|
+
total_vias: int = Field(description="Total number of vias")
|
|
66
|
+
total_zones: int = Field(description="Total number of copper zones")
|
|
67
|
+
board_width: float = Field(description="Board width in mm")
|
|
68
|
+
board_height: float = Field(description="Board height in mm")
|
|
69
|
+
layers: int = Field(description="Number of copper layers")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ERCError(BaseModel):
|
|
73
|
+
"""Electrical Rules Check error."""
|
|
74
|
+
|
|
75
|
+
severity: str = Field(description="Error severity (error, warning)")
|
|
76
|
+
type: str = Field(description="Error type")
|
|
77
|
+
description: str = Field(description="Error description")
|
|
78
|
+
components: list[str] = Field(default_factory=list, description="Involved components")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DRCError(BaseModel):
|
|
82
|
+
"""Design Rules Check error."""
|
|
83
|
+
|
|
84
|
+
severity: str = Field(description="Error severity (error, warning)")
|
|
85
|
+
type: str = Field(description="Error type")
|
|
86
|
+
description: str = Field(description="Error description")
|
|
87
|
+
location: tuple[float, float] = Field(description="X, Y coordinates")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""File parsers for KiCad MCP Server."""
|