kcaa 0.1.0__py3-none-any.whl

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.
Files changed (74) hide show
  1. kcaa/__init__.py +29 -0
  2. kcaa/config.py +328 -0
  3. kcaa/context.py +85 -0
  4. kcaa/prompts/__init__.py +3 -0
  5. kcaa/prompts/bom_prompts.py +117 -0
  6. kcaa/prompts/drc_prompt.py +49 -0
  7. kcaa/prompts/pattern_prompts.py +145 -0
  8. kcaa/prompts/templates.py +59 -0
  9. kcaa/resources/__init__.py +3 -0
  10. kcaa/resources/bom_resources.py +281 -0
  11. kcaa/resources/drc_resources.py +255 -0
  12. kcaa/resources/files.py +46 -0
  13. kcaa/resources/netlist_resources.py +253 -0
  14. kcaa/resources/pattern_resources.py +294 -0
  15. kcaa/resources/projects.py +51 -0
  16. kcaa/server.py +304 -0
  17. kcaa/tools/__init__.py +9 -0
  18. kcaa/tools/analysis_tools.py +51 -0
  19. kcaa/tools/bom_tools.py +787 -0
  20. kcaa/tools/component_edit_tools.py +2037 -0
  21. kcaa/tools/drc_impl/__init__.py +3 -0
  22. kcaa/tools/drc_impl/cli_drc.py +168 -0
  23. kcaa/tools/drc_tools.py +140 -0
  24. kcaa/tools/export_tools.py +227 -0
  25. kcaa/tools/kipy_tools.py +280 -0
  26. kcaa/tools/netlist_tools.py +486 -0
  27. kcaa/tools/pattern_tools.py +196 -0
  28. kcaa/tools/pcb_edit_tools.py +443 -0
  29. kcaa/tools/pcb_group_tools.py +1541 -0
  30. kcaa/tools/pcb_library_tools.py +413 -0
  31. kcaa/tools/pcb_placement_helpers.py +1361 -0
  32. kcaa/tools/pcb_placement_tools.py +456 -0
  33. kcaa/tools/pcb_query_tools.py +850 -0
  34. kcaa/tools/pcb_zone_tools.py +492 -0
  35. kcaa/tools/placement_helpers.py +379 -0
  36. kcaa/tools/project_tools.py +59 -0
  37. kcaa/tools/symbol_tools.py +603 -0
  38. kcaa/tools/validation_tools.py +298 -0
  39. kcaa/tools/version_tools.py +133 -0
  40. kcaa/tools/wire_edit_tools.py +1410 -0
  41. kcaa/utils/__init__.py +3 -0
  42. kcaa/utils/boundary_validator.py +365 -0
  43. kcaa/utils/component_utils.py +433 -0
  44. kcaa/utils/drc_history.py +181 -0
  45. kcaa/utils/env.py +121 -0
  46. kcaa/utils/file_utils.py +71 -0
  47. kcaa/utils/footprint_database.py +464 -0
  48. kcaa/utils/footprint_index_manager.py +351 -0
  49. kcaa/utils/kicad_api_detection.py +70 -0
  50. kcaa/utils/kicad_cli.py +241 -0
  51. kcaa/utils/kicad_utils.py +122 -0
  52. kcaa/utils/kipy_reload.py +136 -0
  53. kcaa/utils/netlist_parser.py +539 -0
  54. kcaa/utils/path_validator.py +226 -0
  55. kcaa/utils/pattern_recognition.py +859 -0
  56. kcaa/utils/pcb_board_utils.py +422 -0
  57. kcaa/utils/pcb_footprint_utils.py +237 -0
  58. kcaa/utils/pcb_library_utils.py +351 -0
  59. kcaa/utils/pcb_sexp_utils.py +72 -0
  60. kcaa/utils/schematic_sexp_utils.py +28 -0
  61. kcaa/utils/secure_subprocess.py +294 -0
  62. kcaa/utils/skip_helpers.py +158 -0
  63. kcaa/utils/symbol_database.py +500 -0
  64. kcaa/utils/symbol_extractor.py +196 -0
  65. kcaa/utils/symbol_geometry.py +463 -0
  66. kcaa/utils/symbol_index_manager.py +490 -0
  67. kcaa/utils/symbol_index_reader.py +137 -0
  68. kcaa/utils/temp_dir_manager.py +24 -0
  69. kcaa/utils/version_manager.py +143 -0
  70. kcaa-0.1.0.dist-info/METADATA +291 -0
  71. kcaa-0.1.0.dist-info/RECORD +74 -0
  72. kcaa-0.1.0.dist-info/WHEEL +4 -0
  73. kcaa-0.1.0.dist-info/entry_points.txt +2 -0
  74. kcaa-0.1.0.dist-info/licenses/LICENSE +21 -0
kcaa/__init__.py ADDED
@@ -0,0 +1,29 @@
1
+ """
2
+ KiCad MCP Server.
3
+
4
+ A Model Context Protocol (MCP) server for KiCad electronic design automation (EDA) files.
5
+ """
6
+ from .server import *
7
+ from .config import *
8
+ from .context import *
9
+
10
+ __version__ = "0.1.0"
11
+ __author__ = "Lama Al Rajih"
12
+ __description__ = "Model Context Protocol server for KiCad on Mac, Windows, and Linux"
13
+
14
+ __all__ = [
15
+ # Package metadata
16
+ "__version__",
17
+ "__author__",
18
+ "__description__",
19
+
20
+ # Server creation / shutdown helpers
21
+ "create_server",
22
+ "add_cleanup_handler",
23
+ "run_cleanup_handlers",
24
+ "shutdown_server",
25
+
26
+ # Lifespan / context helpers
27
+ "kicad_lifespan",
28
+ "KiCadAppContext",
29
+ ]
kcaa/config.py ADDED
@@ -0,0 +1,328 @@
1
+ """
2
+ Configuration settings for the KiCad MCP server.
3
+
4
+ This module provides platform-specific configuration for KiCad integration,
5
+ including file paths, extensions, component libraries, and operational constants.
6
+ All settings are determined at import time based on the operating system.
7
+
8
+ Module Variables:
9
+ system (str): Operating system name from platform.system()
10
+ KICAD_VERSION (str): KiCad version string used to construct versioned paths
11
+ KICAD_USER_DIR (str): User's KiCad documents directory
12
+ KICAD_APP_PATH (str): KiCad application installation path
13
+ ADDITIONAL_SEARCH_PATHS (List[str]): Additional project search locations
14
+ DEFAULT_PROJECT_LOCATIONS (List[str]): Common project directory patterns
15
+ KICAD_PYTHON_BASE (str): KiCad Python framework base path (macOS only)
16
+ KICAD_EXTENSIONS (Dict[str, str]): KiCad file extension mappings
17
+ DATA_EXTENSIONS (List[str]): Recognized data file extensions
18
+ CIRCUIT_DEFAULTS (Dict[str, Union[float, List[float]]]): Default circuit parameters
19
+ COMMON_LIBRARIES (Dict[str, Dict[str, Dict[str, str]]]): Component library mappings
20
+ DEFAULT_FOOTPRINTS (Dict[str, List[str]]): Default footprint suggestions per component
21
+ TIMEOUT_CONSTANTS (Dict[str, float]): Operation timeout values in seconds
22
+ PROGRESS_CONSTANTS (Dict[str, int]): Progress reporting percentage values
23
+ DISPLAY_CONSTANTS (Dict[str, int]): UI display configuration values
24
+ LibraryPathConfig: Configuration class for symbol library paths and settings
25
+
26
+ Platform Support:
27
+ - macOS (Darwin): Full support with application bundle paths
28
+ - Windows: Standard installation paths
29
+ - Linux: System package paths
30
+ - Unknown: Defaults to macOS paths for compatibility
31
+
32
+ Dependencies:
33
+ - os: File system operations and environment variables
34
+ - platform: Operating system detection
35
+ """
36
+
37
+ import logging
38
+ import os
39
+ import platform
40
+
41
+ log = logging.getLogger(__name__)
42
+
43
+ # Determine operating system for platform-specific configuration
44
+ # Returns 'Darwin' (macOS), 'Windows', 'Linux', or other
45
+ system = platform.system()
46
+
47
+ # Platform-specific KiCad installation and user directory paths
48
+ # These paths are used for finding KiCad resources and user projects
49
+ if system == "Darwin": # macOS
50
+ KICAD_USER_DIR = os.path.expanduser("~/Documents/KiCad")
51
+ KICAD_APP_PATH = "/Applications/KiCad/KiCad.app"
52
+ elif system == "Windows":
53
+ KICAD_USER_DIR = os.path.expanduser("~/Documents/KiCad")
54
+ KICAD_APP_PATH = r"C:\Program Files\KiCad"
55
+ elif system == "Linux":
56
+ KICAD_USER_DIR = os.path.expanduser("~/KiCad")
57
+ KICAD_APP_PATH = "/usr/share/kicad"
58
+ else:
59
+ # Default to macOS paths if system is unknown for maximum compatibility
60
+ # This ensures the server can start even on unrecognized platforms
61
+ KICAD_USER_DIR = os.path.expanduser("~/Documents/KiCad")
62
+ KICAD_APP_PATH = "/Applications/KiCad/KiCad.app"
63
+
64
+ # Additional search paths from environment variable KICAD_SEARCH_PATHS
65
+ # Users can specify custom project locations as comma-separated paths
66
+ ADDITIONAL_SEARCH_PATHS = []
67
+ env_search_paths = os.environ.get("KICAD_SEARCH_PATHS", "")
68
+ if env_search_paths:
69
+ for path in env_search_paths.split(","):
70
+ expanded_path = os.path.expanduser(path.strip()) # Expand ~ and variables
71
+ if os.path.exists(expanded_path): # Only add existing directories
72
+ ADDITIONAL_SEARCH_PATHS.append(expanded_path)
73
+
74
+ # Auto-detect common project locations for convenient project discovery
75
+ # These are typical directory names users create for electronics projects
76
+ DEFAULT_PROJECT_LOCATIONS = [
77
+ "~/Documents/PCB", # Common Windows/macOS location
78
+ "~/PCB", # Simple home directory structure
79
+ "~/Electronics", # Generic electronics projects
80
+ "~/Projects/Electronics", # Organized project structure
81
+ "~/Projects/PCB", # PCB-specific project directory
82
+ "~/Projects/KiCad", # KiCad-specific project directory
83
+ ]
84
+
85
+ # Add existing default locations to search paths
86
+ # Avoids duplicates and only includes directories that actually exist
87
+ for location in DEFAULT_PROJECT_LOCATIONS:
88
+ expanded_path = os.path.expanduser(location)
89
+ if os.path.exists(expanded_path) and expanded_path not in ADDITIONAL_SEARCH_PATHS:
90
+ ADDITIONAL_SEARCH_PATHS.append(expanded_path)
91
+
92
+ # Base path to KiCad's Python framework for API access
93
+ # macOS bundles Python framework within the application
94
+ if system == "Darwin": # macOS
95
+ KICAD_PYTHON_BASE = os.path.join(
96
+ KICAD_APP_PATH, "Contents/Frameworks/Python.framework/Versions"
97
+ )
98
+ else:
99
+ # Linux/Windows use system Python or require dynamic detection
100
+ KICAD_PYTHON_BASE = "" # Will be determined dynamically in python_path.py
101
+
102
+
103
+ # KiCad file extension mappings for project file identification
104
+ # Used by file discovery and validation functions
105
+ KICAD_EXTENSIONS = {
106
+ "project": ".kicad_pro",
107
+ "pcb": ".kicad_pcb",
108
+ "schematic": ".kicad_sch",
109
+ "design_rules": ".kicad_dru",
110
+ "worksheet": ".kicad_wks",
111
+ "footprint": ".kicad_mod",
112
+ "netlist": "_netlist.net",
113
+ "kibot_config": ".kibot.yaml",
114
+ }
115
+
116
+ # Additional data file extensions that may be part of KiCad projects
117
+ # Includes manufacturing files, component data, and export formats
118
+ DATA_EXTENSIONS = [
119
+ ".csv", # BOM or other data
120
+ ".pos", # Component position file
121
+ ".net", # Netlist files
122
+ ".zip", # Gerber files and other archives
123
+ ".drl", # Drill files
124
+ ]
125
+
126
+ # Default parameters for circuit creation and component placement
127
+ # Values in mm unless otherwise specified, following KiCad conventions
128
+ CIRCUIT_DEFAULTS = {
129
+ "grid_spacing": 1.0, # Default grid spacing in mm for user coordinates
130
+ "component_spacing": 10.16, # Default component spacing in mm
131
+ "wire_width": 6, # Default wire width in KiCad units (0.006 inch)
132
+ "text_size": [1.27, 1.27], # Default text size in mm
133
+ "pin_length": 2.54, # Default pin length in mm
134
+ }
135
+
136
+ # Predefined component library mappings for quick circuit creation
137
+ # Maps common component types to their KiCad library and symbol names
138
+ # Organized by functional categories: basic, power, connectors
139
+ COMMON_LIBRARIES = {
140
+ "basic": {
141
+ "resistor": {"library": "Device", "symbol": "R"},
142
+ "capacitor": {"library": "Device", "symbol": "C"},
143
+ "inductor": {"library": "Device", "symbol": "L"},
144
+ "led": {"library": "Device", "symbol": "LED"},
145
+ "diode": {"library": "Device", "symbol": "D"},
146
+ },
147
+ "power": {
148
+ "vcc": {"library": "power", "symbol": "VCC"},
149
+ "gnd": {"library": "power", "symbol": "GND"},
150
+ "+5v": {"library": "power", "symbol": "+5V"},
151
+ "+3v3": {"library": "power", "symbol": "+3V3"},
152
+ "+12v": {"library": "power", "symbol": "+12V"},
153
+ "-12v": {"library": "power", "symbol": "-12V"},
154
+ },
155
+ "connectors": {
156
+ "conn_2pin": {"library": "Connector", "symbol": "Conn_01x02_Male"},
157
+ "conn_4pin": {"library": "Connector_Generic", "symbol": "Conn_01x04"},
158
+ "conn_8pin": {"library": "Connector_Generic", "symbol": "Conn_01x08"},
159
+ },
160
+ }
161
+
162
+ # Suggested footprints for common components, ordered by preference
163
+ # SMD variants listed first, followed by through-hole alternatives
164
+ DEFAULT_FOOTPRINTS = {
165
+ "R": [
166
+ "Resistor_SMD:R_0805_2012Metric",
167
+ "Resistor_SMD:R_0603_1608Metric",
168
+ "Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal",
169
+ ],
170
+ "C": [
171
+ "Capacitor_SMD:C_0805_2012Metric",
172
+ "Capacitor_SMD:C_0603_1608Metric",
173
+ "Capacitor_THT:C_Disc_D5.0mm_W2.5mm_P5.00mm",
174
+ ],
175
+ "LED": ["LED_SMD:LED_0805_2012Metric", "LED_THT:LED_D5.0mm"],
176
+ "D": ["Diode_SMD:D_SOD-123", "Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal"],
177
+ }
178
+
179
+ # Operation timeout values in seconds for external process management
180
+ # Prevents hanging operations and provides user feedback
181
+ TIMEOUT_CONSTANTS = {
182
+ "kicad_cli_version_check": 10.0, # Timeout for KiCad CLI version checks
183
+ "kicad_cli_export": 30.0, # Timeout for KiCad CLI export operations
184
+ "application_open": 10.0, # Timeout for opening applications (e.g., KiCad)
185
+ "subprocess_default": 30.0, # Default timeout for subprocess operations
186
+ }
187
+
188
+ # Progress percentage milestones for long-running operations
189
+ # Provides consistent progress reporting across different tools
190
+ PROGRESS_CONSTANTS = {
191
+ "start": 10, # Initial progress percentage
192
+ "detection": 20, # Progress after CLI detection
193
+ "setup": 30, # Progress after setup complete
194
+ "processing": 50, # Progress during processing
195
+ "finishing": 70, # Progress when finishing up
196
+ "validation": 90, # Progress during validation
197
+ "complete": 100, # Progress when complete
198
+ }
199
+
200
+ # User interface display configuration values
201
+ # Controls how much information is shown in previews and summaries
202
+ DISPLAY_CONSTANTS = {
203
+ "bom_preview_limit": 20, # Maximum number of BOM items to show in preview
204
+ }
205
+
206
+ # KiCad version string — fallback used when KICAD_VERSION env var is not set
207
+ KICAD_VERSION = "9.0"
208
+
209
+ class LibraryPathConfig:
210
+ """
211
+ KiCad symbol library path configuration.
212
+
213
+ Reads KICAD_VERSION and each path from the corresponding environment
214
+ variable; if a variable is absent the built-in default is used. The
215
+ resolved values are collected into ``self._env_vars`` so they can be
216
+ injected into subprocess environments that expand ``${VAR}`` URI
217
+ references.
218
+ """
219
+
220
+ @staticmethod
221
+ def _default_symbol_dir(kicad_app_path: str) -> str:
222
+ """Return the platform-specific default KiCad system symbols directory."""
223
+ if system == "Darwin":
224
+ return os.path.join(kicad_app_path, "Contents", "SharedSupport", "symbols")
225
+ elif system == "Windows":
226
+ return os.path.join(kicad_app_path, "share", "kicad", "symbols")
227
+ else:
228
+ return os.path.join(kicad_app_path, "symbols")
229
+
230
+ @staticmethod
231
+ def _default_footprint_dir(kicad_app_path: str) -> str:
232
+ """Return the platform-specific default KiCad system footprints directory."""
233
+ if system == "Darwin":
234
+ return os.path.join(kicad_app_path, "Contents", "SharedSupport", "footprints")
235
+ elif system == "Windows":
236
+ return os.path.join(kicad_app_path, "share", "kicad", "footprints")
237
+ else:
238
+ return os.path.join(kicad_app_path, "footprints")
239
+
240
+ @staticmethod
241
+ def _default_config_dir(kicad_version: str) -> str:
242
+ """Return the platform-specific default KiCad configuration directory."""
243
+ if system == "Darwin":
244
+ return os.path.expanduser(f"~/Library/Preferences/kicad/{kicad_version}")
245
+ elif system == "Windows":
246
+ appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
247
+ return os.path.join(appdata, "kicad", kicad_version)
248
+ else:
249
+ return os.path.expanduser(f"~/.config/kicad/{kicad_version}")
250
+
251
+ @staticmethod
252
+ def _default_3rd_party(kicad_version: str) -> str:
253
+ """Return the platform-specific default KiCad 3rd-party packages directory."""
254
+ if system == "Darwin":
255
+ return os.path.expanduser(f"~/Library/Application Support/kicad/{kicad_version}/3rdparty")
256
+ elif system == "Windows":
257
+ appdata = os.environ.get("APPDATA", os.path.expanduser("~"))
258
+ return os.path.join(appdata, "kicad", kicad_version, "3rdparty")
259
+ else:
260
+ return os.path.expanduser(f"~/.local/share/kicad/{kicad_version}/3rdparty")
261
+
262
+ @staticmethod
263
+ def _default_template_dir(kicad_app_path: str, kicad_version: str) -> str:
264
+ """Return the platform-specific default KiCad templates directory."""
265
+ if system == "Darwin":
266
+ return os.path.join(kicad_app_path, "Contents", "SharedSupport", "template")
267
+ elif system == "Windows":
268
+ return os.path.join(kicad_app_path, "share", "kicad", "template")
269
+ else:
270
+ return os.path.join(kicad_app_path, "template")
271
+
272
+ def __init__(self):
273
+ kicad_version = os.environ.get("KICAD_VERSION") or KICAD_VERSION
274
+ _ver_tag = kicad_version.split(".")[0]
275
+
276
+ # KICAD_APP_PATH must be set in the environment (typically via .env)
277
+ # for AppImage / non-standard installs. If the resolved path doesn't
278
+ # exist we log a clear warning rather than silently falling back —
279
+ # otherwise sym/fp-lib-table entries that reference
280
+ # ${KICAD{N}_TEMPLATE_DIR}/... etc. would be silently dropped.
281
+ kicad_app_path = os.environ.get("KICAD_APP_PATH") or KICAD_APP_PATH
282
+ if not os.path.isdir(kicad_app_path):
283
+ log.warning(
284
+ "KiCad application path does not exist: %s. "
285
+ "System symbol/footprint/template libraries will be unresolvable. "
286
+ "Set KICAD_APP_PATH in your .env file (e.g. for an AppImage, "
287
+ "the path under /tmp/.mount_kicad*/share/kicad while KiCad is "
288
+ "running).",
289
+ kicad_app_path,
290
+ )
291
+
292
+ self._kicad_config_dir = os.path.expanduser(
293
+ os.environ.get("KICAD_CONFIG_DIR")
294
+ or self._default_config_dir(kicad_version)
295
+ )
296
+ self._kicad_symbol_dir = os.path.expanduser(
297
+ os.environ.get("KICAD_SYMBOL_DIR")
298
+ or self._default_symbol_dir(kicad_app_path)
299
+ )
300
+ self._kicad_footprint_dir = os.path.expanduser(
301
+ os.environ.get("KICAD_FOOTPRINT_DIR")
302
+ or self._default_footprint_dir(kicad_app_path)
303
+ )
304
+ self._kicad_3rd_party = os.path.expanduser(
305
+ os.environ.get("KICAD_3RD_PARTY")
306
+ or self._default_3rd_party(kicad_version)
307
+ )
308
+ self._kicad_template_dir = os.path.expanduser(
309
+ os.environ.get("KICAD_TEMPLATE_DIR")
310
+ or self._default_template_dir(kicad_app_path, kicad_version)
311
+ )
312
+
313
+ # Env vars to inject into subprocesses that expand ${VAR} placeholders in library URIs
314
+ self._env_vars = {
315
+ f"KICAD{_ver_tag}_SYMBOL_DIR": self._kicad_symbol_dir,
316
+ f"KICAD{_ver_tag}_FOOTPRINT_DIR": self._kicad_footprint_dir,
317
+ f"KICAD{_ver_tag}_3RD_PARTY": self._kicad_3rd_party,
318
+ f"KICAD{_ver_tag}_TEMPLATE_DIR": self._kicad_template_dir,
319
+ }
320
+
321
+ @property
322
+ def symbol_table_file(self) -> str:
323
+ """Path to the sym-lib-table file."""
324
+ return self._kicad_config_dir + "/sym-lib-table"
325
+
326
+ def get_env_vars(self):
327
+ """Get the complete environment variables dictionary."""
328
+ return self._env_vars.copy()
kcaa/context.py ADDED
@@ -0,0 +1,85 @@
1
+ """
2
+ Lifespan context management for KiCad MCP Server.
3
+ """
4
+ from contextlib import asynccontextmanager
5
+ from dataclasses import dataclass
6
+ from typing import AsyncIterator, Dict, Any
7
+ import logging # Import logging
8
+ import os # Added for PID
9
+
10
+ from fastmcp import FastMCP
11
+
12
+ # Get PID for logging
13
+ # _PID = os.getpid()
14
+
15
+ @dataclass
16
+ class KiCadAppContext:
17
+ """Type-safe context for KiCad MCP server."""
18
+ kicad_modules_available: bool
19
+
20
+ # Optional cache for expensive operations
21
+ cache: Dict[str, Any]
22
+
23
+ @asynccontextmanager
24
+ async def kicad_lifespan(server: FastMCP, kicad_modules_available: bool = False) -> AsyncIterator[KiCadAppContext]:
25
+ """Manage KiCad MCP server lifecycle with type-safe context.
26
+
27
+ This function handles:
28
+ 1. Initializing shared resources when the server starts
29
+ 2. Providing a typed context object to all request handlers
30
+ 3. Properly cleaning up resources when the server shuts down
31
+
32
+ Args:
33
+ server: The FastMCP server instance
34
+ kicad_modules_available: Flag indicating if Python modules were found (passed from create_server)
35
+
36
+ Yields:
37
+ KiCadAppContext: A typed context object shared across all handlers
38
+ """
39
+ logging.info(f"Starting KiCad MCP server initialization")
40
+
41
+ # Resources initialization - Python path setup removed
42
+ # print("Setting up KiCad Python modules")
43
+ # kicad_modules_available = setup_kicad_python_path() # Now passed as arg
44
+ logging.info(f"KiCad Python module availability: {kicad_modules_available} (Setup logic removed)")
45
+
46
+ # Create in-memory cache for expensive operations
47
+ cache: Dict[str, Any] = {}
48
+
49
+ # Initialize any other resources that need cleanup later
50
+ created_temp_dirs = [] # Assuming this is managed elsewhere or not needed for now
51
+
52
+ try:
53
+ # --- Removed Python module preloading section ---
54
+ # if kicad_modules_available:
55
+ # try:
56
+ # print("Preloading KiCad Python modules")
57
+ # ...
58
+ # except ImportError as e:
59
+ # print(f"Failed to preload some KiCad modules: {str(e)}")
60
+
61
+ # Yield the context to the server - server runs during this time
62
+ logging.info(f"KiCad MCP server initialization complete")
63
+ yield KiCadAppContext(
64
+ kicad_modules_available=kicad_modules_available, # Pass the flag through
65
+ cache=cache
66
+ )
67
+ finally:
68
+ # Clean up resources when server shuts down
69
+ logging.info(f"Shutting down KiCad MCP server")
70
+
71
+ # Clear the cache
72
+ if cache:
73
+ logging.info(f"Clearing cache with {len(cache)} entries")
74
+ cache.clear()
75
+
76
+ # Clean up any temporary directories
77
+ import shutil
78
+ for temp_dir in created_temp_dirs:
79
+ try:
80
+ logging.info(f"Removing temporary directory: {temp_dir}")
81
+ shutil.rmtree(temp_dir, ignore_errors=True)
82
+ except Exception as e:
83
+ logging.error(f"Error cleaning up temporary directory {temp_dir}: {str(e)}")
84
+
85
+ logging.info(f"KiCad MCP server shutdown complete")
@@ -0,0 +1,3 @@
1
+ """
2
+ Prompt templates for KiCad MCP Server.
3
+ """
@@ -0,0 +1,117 @@
1
+ """
2
+ BOM-related prompt templates for KiCad.
3
+ """
4
+ from fastmcp import FastMCP
5
+
6
+
7
+ def register_bom_prompts(mcp: FastMCP) -> None:
8
+ """Register BOM-related prompt templates with the MCP server.
9
+
10
+ Args:
11
+ mcp: The FastMCP server instance
12
+ """
13
+
14
+ @mcp.prompt()
15
+ def analyze_components() -> str:
16
+ """Prompt for analyzing a KiCad project's components."""
17
+ prompt = """
18
+ I'd like to analyze the components used in my KiCad PCB design. Can you help me with:
19
+
20
+ 1. Identifying all the components in my design
21
+ 2. Analyzing the distribution of component types
22
+ 3. Checking for any potential issues or opportunities for optimization
23
+ 4. Suggesting any alternatives for hard-to-find or expensive components
24
+
25
+ My KiCad project is located at:
26
+ [Enter the full path to your .kicad_pro file here]
27
+
28
+ Please use the BOM analysis tools to help me understand my component usage.
29
+ """
30
+
31
+ return prompt
32
+
33
+ @mcp.prompt()
34
+ def cost_estimation() -> str:
35
+ """Prompt for estimating project costs based on BOM."""
36
+ prompt = """
37
+ I need to estimate the cost of my KiCad PCB project for:
38
+
39
+ 1. A prototype run (1-5 boards)
40
+ 2. A small production run (10-100 boards)
41
+ 3. Larger scale production (500+ boards)
42
+
43
+ My KiCad project is located at:
44
+ [Enter the full path to your .kicad_pro file here]
45
+
46
+ Please analyze my BOM to help estimate component costs, and provide guidance on:
47
+
48
+ - Which components contribute most to the overall cost
49
+ - Where I might find cost savings
50
+ - Potential volume discounts for larger runs
51
+ - Suggestions for alternative components that could reduce costs
52
+ - Estimated PCB fabrication costs based on board size and complexity
53
+
54
+ If my BOM doesn't include cost data, please suggest how I might find pricing information for my components.
55
+ """
56
+
57
+ return prompt
58
+
59
+ @mcp.prompt()
60
+ def bom_export_help() -> str:
61
+ """Prompt for assistance with exporting BOMs from KiCad."""
62
+ prompt = """
63
+ I need help exporting a Bill of Materials (BOM) from my KiCad project. I'm interested in:
64
+
65
+ 1. Understanding the different BOM export options in KiCad
66
+ 2. Exporting a BOM with specific fields (reference, value, footprint, etc.)
67
+ 3. Generating a BOM in a format compatible with my preferred supplier
68
+ 4. Adding custom fields to my components that will appear in the BOM
69
+
70
+ My KiCad project is located at:
71
+ [Enter the full path to your .kicad_pro file here]
72
+
73
+ Please guide me through the process of creating a well-structured BOM for my project.
74
+ """
75
+
76
+ return prompt
77
+
78
+ @mcp.prompt()
79
+ def component_sourcing() -> str:
80
+ """Prompt for help with component sourcing."""
81
+ prompt = """
82
+ I need help sourcing components for my KiCad PCB project. Specifically, I need assistance with:
83
+
84
+ 1. Identifying reliable suppliers for my components
85
+ 2. Finding alternatives for any hard-to-find or obsolete parts
86
+ 3. Understanding lead times and availability constraints
87
+ 4. Balancing cost versus quality considerations
88
+
89
+ My KiCad project is located at:
90
+ [Enter the full path to your .kicad_pro file here]
91
+
92
+ Please analyze my BOM and provide guidance on sourcing these components efficiently.
93
+ """
94
+
95
+ return prompt
96
+
97
+ @mcp.prompt()
98
+ def bom_comparison() -> str:
99
+ """Prompt for comparing BOMs between two design revisions."""
100
+ prompt = """
101
+ I have two versions of a KiCad project and I'd like to compare the changes between their Bills of Materials. I need to understand:
102
+
103
+ 1. Which components were added or removed
104
+ 2. Which component values or footprints changed
105
+ 3. The impact of these changes on the overall design
106
+ 4. Any potential issues introduced by these changes
107
+
108
+ My original KiCad project is located at:
109
+ [Enter the full path to your first .kicad_pro file here]
110
+
111
+ My revised KiCad project is located at:
112
+ [Enter the full path to your second .kicad_pro file here]
113
+
114
+ Please analyze the BOMs from both projects and help me understand the differences between them.
115
+ """
116
+
117
+ return prompt
@@ -0,0 +1,49 @@
1
+ """
2
+ DRC prompt templates for KiCad PCB design.
3
+ """
4
+ from fastmcp import FastMCP
5
+
6
+
7
+ def register_drc_prompts(mcp: FastMCP) -> None:
8
+ """Register DRC prompt templates with the MCP server.
9
+
10
+ Args:
11
+ mcp: The FastMCP server instance
12
+ """
13
+
14
+ @mcp.prompt()
15
+ def fix_drc_violations() -> str:
16
+ """Prompt for assistance with fixing DRC violations."""
17
+ return """
18
+ I'm trying to fix DRC (Design Rule Check) violations in my KiCad PCB design. I need help with:
19
+
20
+ 1. Understanding what these DRC errors mean
21
+ 2. Knowing how to fix each type of violation
22
+ 3. Best practices for preventing DRC issues in future designs
23
+
24
+ Here are the specific DRC errors I'm seeing (please list errors from your DRC report, or use the kicad://drc/path_to_project resource to see your full DRC report):
25
+
26
+ [list your DRC errors here]
27
+
28
+ Please help me understand these errors and provide step-by-step guidance on fixing them.
29
+ """
30
+
31
+ @mcp.prompt()
32
+ def custom_design_rules() -> str:
33
+ """Prompt for assistance with creating custom design rules."""
34
+ return """
35
+ I want to create custom design rules for my KiCad PCB. My project has the following requirements:
36
+
37
+ 1. [Describe your project's specific requirements]
38
+ 2. [List any special considerations like high voltage, high current, RF, etc.]
39
+ 3. [Mention any manufacturing constraints]
40
+
41
+ Please help me set up appropriate design rules for my KiCad project, including:
42
+
43
+ - Minimum trace width and clearance settings
44
+ - Via size and drill constraints
45
+ - Layer stack considerations
46
+ - Other important design rules
47
+
48
+ Explain how to configure these rules in KiCad and how to verify they're being applied correctly.
49
+ """