solidworks-mcp-python 1.5.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.
- solidworks_mcp/__init__.py +57 -0
- solidworks_mcp/adapters/__init__.py +40 -0
- solidworks_mcp/adapters/base.py +1882 -0
- solidworks_mcp/adapters/circuit_breaker.py +2052 -0
- solidworks_mcp/adapters/com_executor.py +252 -0
- solidworks_mcp/adapters/complexity_analyzer.py +272 -0
- solidworks_mcp/adapters/connection_pool.py +1884 -0
- solidworks_mcp/adapters/factory.py +366 -0
- solidworks_mcp/adapters/intelligent_router.py +218 -0
- solidworks_mcp/adapters/mock_adapter.py +4016 -0
- solidworks_mcp/adapters/pywin32_adapter.py +2842 -0
- solidworks_mcp/adapters/solidworks/__init__.py +17 -0
- solidworks_mcp/adapters/solidworks/bitmap.py +180 -0
- solidworks_mcp/adapters/solidworks/com_utils.py +56 -0
- solidworks_mcp/adapters/solidworks/dimension_layout.py +753 -0
- solidworks_mcp/adapters/solidworks/documentation.py +1476 -0
- solidworks_mcp/adapters/solidworks/drawing_standard.py +1993 -0
- solidworks_mcp/adapters/solidworks/face_selection.py +392 -0
- solidworks_mcp/adapters/solidworks/features.py +3362 -0
- solidworks_mcp/adapters/solidworks/io.py +3649 -0
- solidworks_mcp/adapters/solidworks/rebuild_diagnostics.py +269 -0
- solidworks_mcp/adapters/solidworks/rebuild_inspector.py +146 -0
- solidworks_mcp/adapters/solidworks/selection.py +308 -0
- solidworks_mcp/adapters/solidworks/sketch.py +2545 -0
- solidworks_mcp/adapters/sw_feature_errors.py +66 -0
- solidworks_mcp/adapters/sw_type_info.py +317 -0
- solidworks_mcp/adapters/vba_adapter.py +318 -0
- solidworks_mcp/adapters/vba_macro_executor.py +215 -0
- solidworks_mcp/agents/__init__.py +68 -0
- solidworks_mcp/agents/design_knowledge/assembly_patterns.md +127 -0
- solidworks_mcp/agents/design_knowledge/hinges.md +118 -0
- solidworks_mcp/agents/design_knowledge/snap_fits.md +93 -0
- solidworks_mcp/agents/design_knowledge/solidworks_basics.md +3 -0
- solidworks_mcp/agents/design_knowledge/tolerancing.md +128 -0
- solidworks_mcp/agents/harness.py +216 -0
- solidworks_mcp/agents/history_db.py +1508 -0
- solidworks_mcp/agents/retrieval_index.py +164 -0
- solidworks_mcp/agents/schemas.py +165 -0
- solidworks_mcp/agents/smoke_test.py +285 -0
- solidworks_mcp/agents/soc_exporter.py +650 -0
- solidworks_mcp/agents/soc_pickup.py +332 -0
- solidworks_mcp/agents/soc_rewind.py +221 -0
- solidworks_mcp/agents/vector_rag.py +665 -0
- solidworks_mcp/cache/__init__.py +5 -0
- solidworks_mcp/cache/response_cache.py +164 -0
- solidworks_mcp/config.py +729 -0
- solidworks_mcp/exceptions.py +37 -0
- solidworks_mcp/security/__init__.py +68 -0
- solidworks_mcp/security/auth.py +128 -0
- solidworks_mcp/security/cors.py +27 -0
- solidworks_mcp/security/rate_limiting.py +90 -0
- solidworks_mcp/security/runtime.py +155 -0
- solidworks_mcp/server.py +777 -0
- solidworks_mcp/server_cli_fixed.py +120 -0
- solidworks_mcp/setup/__init__.py +1 -0
- solidworks_mcp/setup/cli.py +399 -0
- solidworks_mcp/setup/clients.py +157 -0
- solidworks_mcp/setup/config_file.py +230 -0
- solidworks_mcp/setup/handshake.py +202 -0
- solidworks_mcp/setup/launcher.py +102 -0
- solidworks_mcp/setup/legacy.py +100 -0
- solidworks_mcp/setup/registration.py +193 -0
- solidworks_mcp/setup/solidworks.py +49 -0
- solidworks_mcp/tools/__init__.py +64 -0
- solidworks_mcp/tools/analysis.py +723 -0
- solidworks_mcp/tools/automation.py +578 -0
- solidworks_mcp/tools/docs_discovery.py +1476 -0
- solidworks_mcp/tools/drawing.py +1015 -0
- solidworks_mcp/tools/drawing_analysis.py +456 -0
- solidworks_mcp/tools/drawing_automation.py +627 -0
- solidworks_mcp/tools/engineering_data.py +466 -0
- solidworks_mcp/tools/error_classifier.py +232 -0
- solidworks_mcp/tools/export.py +833 -0
- solidworks_mcp/tools/file_facts.py +40 -0
- solidworks_mcp/tools/file_management.py +1473 -0
- solidworks_mcp/tools/input_compat.py +17 -0
- solidworks_mcp/tools/macro_recording.py +464 -0
- solidworks_mcp/tools/modeling.py +2360 -0
- solidworks_mcp/tools/sketching.py +1422 -0
- solidworks_mcp/tools/template_management.py +367 -0
- solidworks_mcp/tools/tool_boundary.py +280 -0
- solidworks_mcp/tools/vba_generation.py +1145 -0
- solidworks_mcp/ui/__init__.py +9 -0
- solidworks_mcp/ui/local_llm.py +725 -0
- solidworks_mcp/ui/routers/__init__.py +10 -0
- solidworks_mcp/ui/routers/checkpoint.py +24 -0
- solidworks_mcp/ui/routers/docs.py +47 -0
- solidworks_mcp/ui/routers/llm.py +83 -0
- solidworks_mcp/ui/routers/local_model.py +69 -0
- solidworks_mcp/ui/routers/model.py +75 -0
- solidworks_mcp/ui/routers/preview.py +38 -0
- solidworks_mcp/ui/routers/session.py +161 -0
- solidworks_mcp/ui/routers/viewer.py +154 -0
- solidworks_mcp/ui/schemas.py +502 -0
- solidworks_mcp/ui/server.py +298 -0
- solidworks_mcp/ui/service.py +481 -0
- solidworks_mcp/ui/services/__init__.py +136 -0
- solidworks_mcp/ui/services/_utils.py +958 -0
- solidworks_mcp/ui/services/checkpoint_service.py +1110 -0
- solidworks_mcp/ui/services/docs_service.py +282 -0
- solidworks_mcp/ui/services/llm_service.py +956 -0
- solidworks_mcp/ui/services/model_service.py +459 -0
- solidworks_mcp/ui/services/parameter_repair_service.py +314 -0
- solidworks_mcp/ui/services/preview_service.py +489 -0
- solidworks_mcp/ui/services/session_service.py +1389 -0
- solidworks_mcp/utils/__init__.py +9 -0
- solidworks_mcp/utils/feature_tree_classifier.py +342 -0
- solidworks_mcp/utils/logging.py +76 -0
- solidworks_mcp/utils/validation.py +77 -0
- solidworks_mcp/version.py +8 -0
- solidworks_mcp_python-1.5.0.dist-info/METADATA +410 -0
- solidworks_mcp_python-1.5.0.dist-info/RECORD +115 -0
- solidworks_mcp_python-1.5.0.dist-info/WHEEL +4 -0
- solidworks_mcp_python-1.5.0.dist-info/entry_points.txt +3 -0
- solidworks_mcp_python-1.5.0.dist-info/licenses/LICENSE +21 -0
solidworks_mcp/config.py
ADDED
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
"""Configuration management for SolidWorks MCP Server.
|
|
2
|
+
|
|
3
|
+
Supports both local and remote deployment with comprehensive security options.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import platform
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
|
+
from enum import StrEnum
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any, cast
|
|
14
|
+
|
|
15
|
+
from dotenv import dotenv_values
|
|
16
|
+
from pydantic import (
|
|
17
|
+
BaseModel,
|
|
18
|
+
ConfigDict,
|
|
19
|
+
Field,
|
|
20
|
+
SecretStr,
|
|
21
|
+
field_validator,
|
|
22
|
+
model_validator,
|
|
23
|
+
)
|
|
24
|
+
from pydantic_core.core_schema import ValidationInfo
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class DeploymentMode(StrEnum):
|
|
28
|
+
"""Deployment mode options.
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
HYBRID (Any): The hybrid value.
|
|
32
|
+
LOCAL (Any): The local value.
|
|
33
|
+
REMOTE (Any): The remote value.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
LOCAL = "local"
|
|
37
|
+
REMOTE = "remote"
|
|
38
|
+
HYBRID = "hybrid"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SecurityLevel(StrEnum):
|
|
42
|
+
"""Security level options.
|
|
43
|
+
|
|
44
|
+
Attributes:
|
|
45
|
+
MINIMAL (Any): The minimal value.
|
|
46
|
+
STANDARD (Any): The standard value.
|
|
47
|
+
STRICT (Any): The strict value.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
MINIMAL = "minimal" # Local only, no authentication
|
|
51
|
+
STANDARD = "standard" # API keys, basic validation
|
|
52
|
+
STRICT = "strict" # Full authentication, encryption, audit logs
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AdapterType(StrEnum):
|
|
56
|
+
"""SolidWorks adapter implementation options.
|
|
57
|
+
|
|
58
|
+
Attributes:
|
|
59
|
+
EDGE_DOTNET (Any): The edge dotnet value.
|
|
60
|
+
MOCK (Any): The mock value.
|
|
61
|
+
POWERSHELL (Any): The powershell value.
|
|
62
|
+
PYWIN32 (Any): The pywin32 value.
|
|
63
|
+
VBA (Any): The vba value.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
PYWIN32 = "pywin32" # Direct COM via pywin32
|
|
67
|
+
VBA = "vba" # VBA-oriented adapter wrapper
|
|
68
|
+
MOCK = "mock" # Mock for testing
|
|
69
|
+
EDGE_DOTNET = "edge_dotnet" # Edge.js bridge to .NET (future)
|
|
70
|
+
POWERSHELL = "powershell" # PowerShell bridge (future)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SolidWorksMCPConfig(BaseModel):
|
|
74
|
+
"""Main configuration for SolidWorks MCP Server.
|
|
75
|
+
|
|
76
|
+
Attributes:
|
|
77
|
+
adapter_type (AdapterType): The adapter type value.
|
|
78
|
+
allowed_hosts (list[str]): The allowed hosts value.
|
|
79
|
+
allowed_origins (list[str]): The allowed origins value.
|
|
80
|
+
api_key (SecretStr | None): The api key value.
|
|
81
|
+
api_key_required (bool): The api key required value.
|
|
82
|
+
api_keys (list[str]): The api keys value.
|
|
83
|
+
cache_dir (Path | None): The cache dir value.
|
|
84
|
+
circuit_breaker_enabled (bool): The circuit breaker enabled value.
|
|
85
|
+
circuit_breaker_threshold (int): The circuit breaker threshold value.
|
|
86
|
+
circuit_breaker_timeout (int): The circuit breaker timeout value.
|
|
87
|
+
complexity_parameter_threshold (int): The complexity parameter threshold value.
|
|
88
|
+
complexity_score_threshold (float): The complexity score threshold value.
|
|
89
|
+
connection_pool_size (int): The connection pool size value.
|
|
90
|
+
connection_pooling (bool): The connection pooling value.
|
|
91
|
+
cors_origins (list[str]): The cors origins value.
|
|
92
|
+
data_dir (Path): The data dir value.
|
|
93
|
+
database_url (str): The database url value.
|
|
94
|
+
debug (bool): The debug value.
|
|
95
|
+
deployment_mode (DeploymentMode): The deployment mode value.
|
|
96
|
+
enable_analysis_tools (bool): The enable analysis tools value.
|
|
97
|
+
enable_audit_logging (bool): The enable audit logging value.
|
|
98
|
+
enable_circuit_breaker (bool): The enable circuit breaker value.
|
|
99
|
+
enable_connection_pooling (bool): The enable connection pooling value.
|
|
100
|
+
enable_cors (bool): The enable cors value.
|
|
101
|
+
enable_design_tables (bool): The enable design tables value.
|
|
102
|
+
enable_intelligent_routing (bool): The enable intelligent routing value.
|
|
103
|
+
enable_macro_recording (bool): The enable macro recording value.
|
|
104
|
+
enable_pdm (bool): The enable pdm value.
|
|
105
|
+
enable_rate_limiting (bool): The enable rate limiting value.
|
|
106
|
+
enable_response_cache (bool): The enable response cache value.
|
|
107
|
+
enable_sql_integration (bool): The enable sql integration value.
|
|
108
|
+
enable_windows_validation (bool): The enable windows validation value.
|
|
109
|
+
host (str): The host value.
|
|
110
|
+
log_file (Path | None): The log file value.
|
|
111
|
+
log_level (str): The log level value.
|
|
112
|
+
max_connections (int): The max connections value.
|
|
113
|
+
max_retries (int): The max retries value.
|
|
114
|
+
mock_solidworks (bool): The mock solidworks value.
|
|
115
|
+
model_config (Any): The model config value.
|
|
116
|
+
pdm_server (str | None): The pdm server value.
|
|
117
|
+
pdm_vault (str | None): The pdm vault value.
|
|
118
|
+
port (int): The port value.
|
|
119
|
+
rate_limit_enabled (bool): The rate limit enabled value.
|
|
120
|
+
rate_limit_per_minute (int): The rate limit per minute value.
|
|
121
|
+
response_cache_max_entries (int): The response cache max entries value.
|
|
122
|
+
response_cache_ttl_seconds (int): The response cache ttl seconds value.
|
|
123
|
+
security_level (SecurityLevel): The security level value.
|
|
124
|
+
solidworks_path (str | None): The solidworks path value.
|
|
125
|
+
solidworks_year (int | None): The solidworks year value.
|
|
126
|
+
sql_connection (str | None): The sql connection value.
|
|
127
|
+
state_file (str | None): The state file value.
|
|
128
|
+
testing (bool): The testing value.
|
|
129
|
+
timeout_seconds (float): The timeout seconds value.
|
|
130
|
+
worker_processes (int): The worker processes value.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
# === Server Configuration ===
|
|
134
|
+
deployment_mode: DeploymentMode = Field(
|
|
135
|
+
default=DeploymentMode.LOCAL,
|
|
136
|
+
description="Deployment mode: local, remote, or hybrid",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
security_level: SecurityLevel = Field(
|
|
140
|
+
default=SecurityLevel.STANDARD, description="Security level for the server"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
host: str = Field(default="127.0.0.1", description="Server host")
|
|
144
|
+
port: int = Field(default=8000, description="Server port")
|
|
145
|
+
|
|
146
|
+
# === SolidWorks Configuration ===
|
|
147
|
+
solidworks_path: str | None = Field(
|
|
148
|
+
default=None, description="Path to SolidWorks executable"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
solidworks_year: int | None = Field(
|
|
152
|
+
default=None,
|
|
153
|
+
description="SolidWorks release year hint (e.g., 2025, 2026)",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
adapter_type: AdapterType = Field(
|
|
157
|
+
default=AdapterType.PYWIN32,
|
|
158
|
+
description="SolidWorks adapter implementation to use",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
enable_windows_validation: bool = Field(
|
|
162
|
+
default=True, description="Validate Windows environment on startup"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# === Feature Flags ===
|
|
166
|
+
enable_macro_recording: bool = Field(
|
|
167
|
+
default=True, description="Enable VBA macro recording capabilities"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
enable_pdm: bool = Field(
|
|
171
|
+
default=False, description="Enable PDM (Product Data Management) integration"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
enable_sql_integration: bool = Field(
|
|
175
|
+
default=False, description="Enable SQL database integration"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
enable_design_tables: bool = Field(
|
|
179
|
+
default=True, description="Enable design table functionality"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
enable_analysis_tools: bool = Field(
|
|
183
|
+
default=True, description="Enable FEA and analysis tools"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# === Security Configuration ===
|
|
187
|
+
api_key: SecretStr | None = Field(
|
|
188
|
+
default=None, description="API key for remote authentication"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
allowed_hosts: list[str] = Field(
|
|
192
|
+
default_factory=lambda: ["localhost", "127.0.0.1"],
|
|
193
|
+
description="Allowed hosts for remote connections",
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
enable_cors: bool = Field(
|
|
197
|
+
default=False, description="Enable CORS for web client access"
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
cors_origins: list[str] = Field(
|
|
201
|
+
default_factory=list, description="Allowed CORS origins"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
enable_rate_limiting: bool = Field(
|
|
205
|
+
default=True, description="Enable rate limiting for API endpoints"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
rate_limit_per_minute: int = Field(
|
|
209
|
+
default=60, description="Maximum requests per minute per client"
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# === Data Storage ===
|
|
213
|
+
data_dir: Path = Field(
|
|
214
|
+
default_factory=lambda: Path.home() / ".solidworks_mcp",
|
|
215
|
+
description="Data directory for persistent storage",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
state_file: str | None = Field(
|
|
219
|
+
default=None, description="Path to persistent state file"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
cache_dir: Path | None = Field(
|
|
223
|
+
default=None, description="Cache directory (defaults to data_dir/cache)"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# === Database Configuration ===
|
|
227
|
+
database_url: str = Field(
|
|
228
|
+
default="sqlite:///./solidworks_mcp.db",
|
|
229
|
+
description="Database URL for persistent storage",
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
sql_connection: str | None = Field(
|
|
233
|
+
default=None, description="External SQL server connection string"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# === PDM Configuration ===
|
|
237
|
+
pdm_vault: str | None = Field(default=None, description="PDM vault name")
|
|
238
|
+
|
|
239
|
+
pdm_server: str | None = Field(default=None, description="PDM server address")
|
|
240
|
+
|
|
241
|
+
# === Logging Configuration ===
|
|
242
|
+
log_level: str = Field(default="INFO", description="Logging level")
|
|
243
|
+
|
|
244
|
+
log_file: Path | None = Field(
|
|
245
|
+
default=None, description="Log file path (defaults to data_dir/logs/server.log)"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
enable_audit_logging: bool = Field(
|
|
249
|
+
default=False, description="Enable detailed audit logging"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# === Performance Configuration ===
|
|
253
|
+
worker_processes: int = Field(default=1, description="Number of worker processes")
|
|
254
|
+
|
|
255
|
+
enable_connection_pooling: bool = Field(
|
|
256
|
+
default=False, description="Enable SolidWorks connection pooling"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
enable_intelligent_routing: bool = Field(
|
|
260
|
+
default=True,
|
|
261
|
+
description="Enable complexity-based COM/VBA routing for eligible operations",
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
complexity_parameter_threshold: int = Field(
|
|
265
|
+
default=12,
|
|
266
|
+
description="Parameter-count threshold used by the complexity analyzer",
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
complexity_score_threshold: float = Field(
|
|
270
|
+
default=0.6,
|
|
271
|
+
description="Complexity score threshold used to prefer VBA routing",
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
enable_response_cache: bool = Field(
|
|
275
|
+
default=True,
|
|
276
|
+
description="Enable in-memory caching for read-heavy adapter operations",
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
response_cache_ttl_seconds: int = Field(
|
|
280
|
+
default=60,
|
|
281
|
+
description="Default TTL for cached responses in seconds",
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
response_cache_max_entries: int = Field(
|
|
285
|
+
default=512,
|
|
286
|
+
description="Maximum number of entries retained in response cache",
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
connection_pool_size: int = Field(
|
|
290
|
+
default=3, description="Maximum connections in pool"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
enable_circuit_breaker: bool = Field(
|
|
294
|
+
default=True, description="Enable circuit breaker pattern"
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
circuit_breaker_threshold: int = Field(
|
|
298
|
+
default=5, description="Circuit breaker failure threshold"
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
circuit_breaker_timeout: int = Field(
|
|
302
|
+
default=60, description="Circuit breaker timeout in seconds"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# === Additional Test Configuration Fields ===
|
|
306
|
+
max_retries: int = Field(default=3, description="Maximum retries for operations")
|
|
307
|
+
|
|
308
|
+
timeout_seconds: float = Field(
|
|
309
|
+
default=30.0, description="Operation timeout in seconds"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
circuit_breaker_enabled: bool = Field(
|
|
313
|
+
default=True,
|
|
314
|
+
description="Enable circuit breaker (alias for enable_circuit_breaker)",
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
connection_pooling: bool = Field(
|
|
318
|
+
default=False,
|
|
319
|
+
description="Enable connection pooling (alias for enable_connection_pooling)",
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
max_connections: int = Field(
|
|
323
|
+
default=5, description="Maximum connections (alias for connection_pool_size)"
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
api_key_required: bool = Field(
|
|
327
|
+
default=False, description="Whether API key is required for access"
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
rate_limit_enabled: bool = Field(
|
|
331
|
+
default=True,
|
|
332
|
+
description="Enable rate limiting (alias for enable_rate_limiting)",
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
allowed_origins: list[str] = Field(
|
|
336
|
+
default_factory=list,
|
|
337
|
+
description="Allowed CORS origins (alias for cors_origins)",
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
api_keys: list[str] = Field(
|
|
341
|
+
default_factory=list, description="List of valid API keys"
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# === SolidWorks-as-Code (SoC) session logging ===
|
|
345
|
+
soc_logging_enabled: bool = Field(
|
|
346
|
+
default=False,
|
|
347
|
+
description=(
|
|
348
|
+
"Log every adapter tool call to the SoC SQLite database so the "
|
|
349
|
+
"session can be exported as a runnable Python script. Off by "
|
|
350
|
+
"default; enable with SOLIDWORKS_MCP_SOC_LOGGING_ENABLED=true."
|
|
351
|
+
),
|
|
352
|
+
)
|
|
353
|
+
soc_session_id: str | None = Field(
|
|
354
|
+
default=None,
|
|
355
|
+
description=(
|
|
356
|
+
"SoC session name to log under. When logging is enabled and this "
|
|
357
|
+
"is unset, a timestamped id is generated at startup."
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
soc_db_path: Path | None = Field(
|
|
361
|
+
default=None,
|
|
362
|
+
description=(
|
|
363
|
+
"Override the SoC SQLite database path "
|
|
364
|
+
"(default: .solidworks_mcp/agent_memory.sqlite3)."
|
|
365
|
+
),
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# === Docs index freshness ===
|
|
369
|
+
docs_index_auto_refresh: bool = Field(
|
|
370
|
+
default=True,
|
|
371
|
+
description=(
|
|
372
|
+
"Rebuild the SolidWorks API docs index automatically when it is "
|
|
373
|
+
"older than docs_index_max_age_days. No-op without SolidWorks + "
|
|
374
|
+
"win32com; falls back to the existing (stale) index on failure."
|
|
375
|
+
),
|
|
376
|
+
)
|
|
377
|
+
docs_index_max_age_days: int = Field(
|
|
378
|
+
default=21,
|
|
379
|
+
ge=1,
|
|
380
|
+
description="Age in days after which the docs index is treated as stale.",
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
# === Development & Testing ===
|
|
384
|
+
debug: bool = Field(default=False, description="Enable debug mode")
|
|
385
|
+
|
|
386
|
+
testing: bool = Field(default=False, description="Enable testing mode")
|
|
387
|
+
|
|
388
|
+
mock_solidworks: bool = Field(
|
|
389
|
+
default=False, description="Use mock SolidWorks for testing"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
model_config = ConfigDict(
|
|
393
|
+
extra="allow" # Allow extra fields for test configurations
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
@model_validator(mode="after")
|
|
397
|
+
def sync_legacy_alias_fields(self) -> SolidWorksMCPConfig:
|
|
398
|
+
"""Sync test/developer alias fields into canonical runtime fields.
|
|
399
|
+
|
|
400
|
+
Several fixtures and scripts still populate compatibility fields such as
|
|
401
|
+
``rate_limit_enabled`` and ``connection_pooling``. Runtime code reads the canonical
|
|
402
|
+
fields, so normalize them here after validation.
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
SolidWorksMCPConfig: The result produced by the operation.
|
|
406
|
+
"""
|
|
407
|
+
self.enable_circuit_breaker = self.circuit_breaker_enabled
|
|
408
|
+
self.enable_connection_pooling = self.connection_pooling
|
|
409
|
+
self.connection_pool_size = self.max_connections
|
|
410
|
+
self.enable_rate_limiting = self.rate_limit_enabled
|
|
411
|
+
if self.allowed_origins and not self.cors_origins:
|
|
412
|
+
self.cors_origins = list(self.allowed_origins)
|
|
413
|
+
return self
|
|
414
|
+
|
|
415
|
+
@field_validator("cache_dir")
|
|
416
|
+
@classmethod
|
|
417
|
+
def set_cache_dir(cls, v: Path | None, info: ValidationInfo) -> Path:
|
|
418
|
+
"""Set default cache directory.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
v (Path | None): The v value.
|
|
422
|
+
info (ValidationInfo): The info value.
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
Path: The result produced by the operation.
|
|
426
|
+
"""
|
|
427
|
+
if v is None:
|
|
428
|
+
data_dir = cast(
|
|
429
|
+
Path,
|
|
430
|
+
info.data.get("data_dir", Path.home() / ".solidworks_mcp"),
|
|
431
|
+
)
|
|
432
|
+
return data_dir / "cache"
|
|
433
|
+
return v
|
|
434
|
+
|
|
435
|
+
@field_validator("log_file")
|
|
436
|
+
@classmethod
|
|
437
|
+
def set_log_file(cls, v: Path | None, info: ValidationInfo) -> Path:
|
|
438
|
+
"""Set default log file path.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
v (Path | None): The v value.
|
|
442
|
+
info (ValidationInfo): The info value.
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
Path: The result produced by the operation.
|
|
446
|
+
"""
|
|
447
|
+
if v is None:
|
|
448
|
+
data_dir = cast(
|
|
449
|
+
Path,
|
|
450
|
+
info.data.get("data_dir", Path.home() / ".solidworks_mcp"),
|
|
451
|
+
)
|
|
452
|
+
return data_dir / "logs" / "server.log"
|
|
453
|
+
return v
|
|
454
|
+
|
|
455
|
+
@field_validator("adapter_type")
|
|
456
|
+
@classmethod
|
|
457
|
+
def validate_adapter_type(cls, v: AdapterType, info: ValidationInfo) -> AdapterType:
|
|
458
|
+
"""Validate adapter type based on platform.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
v (AdapterType): The v value.
|
|
462
|
+
info (ValidationInfo): The info value.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
AdapterType: The result produced by the operation.
|
|
466
|
+
"""
|
|
467
|
+
return v
|
|
468
|
+
|
|
469
|
+
@field_validator("port")
|
|
470
|
+
@classmethod
|
|
471
|
+
def validate_port(cls, v: int) -> int:
|
|
472
|
+
"""Validate the port.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
v (int): The v value.
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
int: The computed numeric result.
|
|
479
|
+
|
|
480
|
+
Raises:
|
|
481
|
+
ValueError: Port must be between 1 and 65535.
|
|
482
|
+
"""
|
|
483
|
+
if v < 1 or v > 65535:
|
|
484
|
+
raise ValueError("Port must be between 1 and 65535")
|
|
485
|
+
return v
|
|
486
|
+
|
|
487
|
+
@field_validator("timeout_seconds")
|
|
488
|
+
@classmethod
|
|
489
|
+
def validate_timeout(cls, v: float) -> float:
|
|
490
|
+
"""Validate the timeout.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
v (float): The v value.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
float: The computed numeric result.
|
|
497
|
+
|
|
498
|
+
Raises:
|
|
499
|
+
ValueError: Timeout_seconds must be > 0.
|
|
500
|
+
"""
|
|
501
|
+
if v <= 0:
|
|
502
|
+
raise ValueError("timeout_seconds must be > 0")
|
|
503
|
+
return v
|
|
504
|
+
|
|
505
|
+
@field_validator("complexity_parameter_threshold")
|
|
506
|
+
@classmethod
|
|
507
|
+
def validate_complexity_parameter_threshold(cls, v: int) -> int:
|
|
508
|
+
"""Validate the complexity parameter threshold.
|
|
509
|
+
|
|
510
|
+
Args:
|
|
511
|
+
v (int): The v value.
|
|
512
|
+
|
|
513
|
+
Returns:
|
|
514
|
+
int: The computed numeric result.
|
|
515
|
+
|
|
516
|
+
Raises:
|
|
517
|
+
ValueError: Complexity_parameter_threshold must be >= 1.
|
|
518
|
+
"""
|
|
519
|
+
if v < 1:
|
|
520
|
+
raise ValueError("complexity_parameter_threshold must be >= 1")
|
|
521
|
+
return v
|
|
522
|
+
|
|
523
|
+
@field_validator("complexity_score_threshold")
|
|
524
|
+
@classmethod
|
|
525
|
+
def validate_complexity_score_threshold(cls, v: float) -> float:
|
|
526
|
+
"""Validate the complexity score threshold.
|
|
527
|
+
|
|
528
|
+
Args:
|
|
529
|
+
v (float): The v value.
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
float: The computed numeric result.
|
|
533
|
+
|
|
534
|
+
Raises:
|
|
535
|
+
ValueError: Complexity_score_threshold must be in (0, 1].
|
|
536
|
+
"""
|
|
537
|
+
if v <= 0 or v > 1:
|
|
538
|
+
raise ValueError("complexity_score_threshold must be in (0, 1]")
|
|
539
|
+
return v
|
|
540
|
+
|
|
541
|
+
@field_validator("response_cache_ttl_seconds")
|
|
542
|
+
@classmethod
|
|
543
|
+
def validate_response_cache_ttl_seconds(cls, v: int) -> int:
|
|
544
|
+
"""Validate default response cache TTL.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
v (int): The v value.
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
int: The computed numeric result.
|
|
551
|
+
|
|
552
|
+
Raises:
|
|
553
|
+
ValueError: Response_cache_ttl_seconds must be >= 1.
|
|
554
|
+
"""
|
|
555
|
+
if v < 1:
|
|
556
|
+
raise ValueError("response_cache_ttl_seconds must be >= 1")
|
|
557
|
+
return v
|
|
558
|
+
|
|
559
|
+
@field_validator("response_cache_max_entries")
|
|
560
|
+
@classmethod
|
|
561
|
+
def validate_response_cache_max_entries(cls, v: int) -> int:
|
|
562
|
+
"""Validate response cache size.
|
|
563
|
+
|
|
564
|
+
Args:
|
|
565
|
+
v (int): The v value.
|
|
566
|
+
|
|
567
|
+
Returns:
|
|
568
|
+
int: The computed numeric result.
|
|
569
|
+
|
|
570
|
+
Raises:
|
|
571
|
+
ValueError: Response_cache_max_entries must be >= 1.
|
|
572
|
+
"""
|
|
573
|
+
if v < 1:
|
|
574
|
+
raise ValueError("response_cache_max_entries must be >= 1")
|
|
575
|
+
return v
|
|
576
|
+
|
|
577
|
+
@classmethod
|
|
578
|
+
def from_env(cls, env_file: str | None = None) -> SolidWorksMCPConfig:
|
|
579
|
+
"""Build configuration from environment variables.
|
|
580
|
+
|
|
581
|
+
Args:
|
|
582
|
+
env_file (str | None): The env file value. Defaults to None.
|
|
583
|
+
|
|
584
|
+
Returns:
|
|
585
|
+
SolidWorksMCPConfig: The result produced by the operation.
|
|
586
|
+
"""
|
|
587
|
+
import json
|
|
588
|
+
|
|
589
|
+
env_prefix = "SOLIDWORKS_MCP_"
|
|
590
|
+
raw_values: dict[str, Any] = {}
|
|
591
|
+
|
|
592
|
+
list_like_fields = {"cors_origins", "allowed_hosts", "api_keys"}
|
|
593
|
+
|
|
594
|
+
def _coerce_env_value(key: str, value: Any) -> Any:
|
|
595
|
+
"""Build internal coerce env value.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
key (str): The key value.
|
|
599
|
+
value (Any): The value value.
|
|
600
|
+
|
|
601
|
+
Returns:
|
|
602
|
+
Any: The result produced by the operation.
|
|
603
|
+
"""
|
|
604
|
+
if not isinstance(value, str):
|
|
605
|
+
return value
|
|
606
|
+
if key in list_like_fields:
|
|
607
|
+
stripped = value.strip()
|
|
608
|
+
if stripped.startswith("[") and stripped.endswith("]"):
|
|
609
|
+
try:
|
|
610
|
+
parsed = json.loads(stripped)
|
|
611
|
+
if isinstance(parsed, list):
|
|
612
|
+
return parsed
|
|
613
|
+
except Exception:
|
|
614
|
+
# Leave original value for Pydantic to validate/report.
|
|
615
|
+
return value
|
|
616
|
+
return value
|
|
617
|
+
|
|
618
|
+
if env_file and Path(env_file).exists():
|
|
619
|
+
for key, value in dotenv_values(env_file).items():
|
|
620
|
+
if key and key.startswith(env_prefix) and value is not None:
|
|
621
|
+
field_name = key[len(env_prefix) :].lower()
|
|
622
|
+
raw_values[field_name] = _coerce_env_value(field_name, value)
|
|
623
|
+
|
|
624
|
+
for key, value in os.environ.items():
|
|
625
|
+
if key.startswith(env_prefix):
|
|
626
|
+
field_name = key[len(env_prefix) :].lower()
|
|
627
|
+
raw_values[field_name] = _coerce_env_value(field_name, value)
|
|
628
|
+
|
|
629
|
+
return cls(**raw_values)
|
|
630
|
+
|
|
631
|
+
def model_post_init(self, __context: Any) -> None:
|
|
632
|
+
"""Post-initialization setup.
|
|
633
|
+
|
|
634
|
+
Args:
|
|
635
|
+
__context (Any): The context value.
|
|
636
|
+
|
|
637
|
+
Returns:
|
|
638
|
+
None: None.
|
|
639
|
+
"""
|
|
640
|
+
if self.cache_dir is None:
|
|
641
|
+
self.cache_dir = self.data_dir / "cache"
|
|
642
|
+
if self.log_file is None:
|
|
643
|
+
self.log_file = self.data_dir / "logs" / "server.log"
|
|
644
|
+
|
|
645
|
+
# Ensure data directories exist
|
|
646
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
647
|
+
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
648
|
+
self.log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
649
|
+
|
|
650
|
+
# Set testing defaults
|
|
651
|
+
if self.testing:
|
|
652
|
+
self.mock_solidworks = True
|
|
653
|
+
self.adapter_type = AdapterType.MOCK
|
|
654
|
+
|
|
655
|
+
# Give SoC logging a session id to write under when it's enabled
|
|
656
|
+
# without one being named explicitly.
|
|
657
|
+
if self.soc_logging_enabled and not self.soc_session_id:
|
|
658
|
+
self.soc_session_id = f"soc-{datetime.now(UTC).strftime('%Y%m%d-%H%M%S')}"
|
|
659
|
+
|
|
660
|
+
@property
|
|
661
|
+
def is_windows(self) -> bool:
|
|
662
|
+
"""Check if running on Windows.
|
|
663
|
+
|
|
664
|
+
Returns:
|
|
665
|
+
bool: True if windows, otherwise False.
|
|
666
|
+
"""
|
|
667
|
+
return platform.system() == "Windows"
|
|
668
|
+
|
|
669
|
+
@property
|
|
670
|
+
def can_use_solidworks(self) -> bool:
|
|
671
|
+
"""Check if SolidWorks integration is possible.
|
|
672
|
+
|
|
673
|
+
Returns:
|
|
674
|
+
bool: True if use solidworks, otherwise False.
|
|
675
|
+
"""
|
|
676
|
+
return (
|
|
677
|
+
self.is_windows
|
|
678
|
+
and not self.mock_solidworks
|
|
679
|
+
and self.adapter_type != AdapterType.MOCK
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
def get_database_config(self) -> dict[str, Any]:
|
|
683
|
+
"""Get database configuration.
|
|
684
|
+
|
|
685
|
+
Returns:
|
|
686
|
+
dict[str, Any]: A dictionary containing the resulting values.
|
|
687
|
+
"""
|
|
688
|
+
return {
|
|
689
|
+
"url": self.database_url,
|
|
690
|
+
"echo": self.debug,
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
def get_security_config(self) -> dict[str, Any]:
|
|
694
|
+
"""Get security configuration.
|
|
695
|
+
|
|
696
|
+
Returns:
|
|
697
|
+
dict[str, Any]: A dictionary containing the resulting values.
|
|
698
|
+
"""
|
|
699
|
+
return {
|
|
700
|
+
"api_key": self.api_key.get_secret_value() if self.api_key else None,
|
|
701
|
+
"allowed_hosts": self.allowed_hosts,
|
|
702
|
+
"enable_cors": self.enable_cors,
|
|
703
|
+
"cors_origins": self.cors_origins,
|
|
704
|
+
"enable_rate_limiting": self.enable_rate_limiting,
|
|
705
|
+
"rate_limit_per_minute": self.rate_limit_per_minute,
|
|
706
|
+
"security_level": self.security_level,
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
def load_config(config_file: str | None = None) -> SolidWorksMCPConfig:
|
|
711
|
+
"""Load configuration from file and environment variables.
|
|
712
|
+
|
|
713
|
+
Args:
|
|
714
|
+
config_file (str | None): The config file value. Defaults to None.
|
|
715
|
+
|
|
716
|
+
Returns:
|
|
717
|
+
SolidWorksMCPConfig: The result produced by the operation.
|
|
718
|
+
"""
|
|
719
|
+
if config_file:
|
|
720
|
+
config_path = Path(config_file)
|
|
721
|
+
if config_path.exists() and config_path.suffix.lower() == ".json":
|
|
722
|
+
import json
|
|
723
|
+
|
|
724
|
+
with config_path.open("r", encoding="utf-8") as f:
|
|
725
|
+
data = json.load(f)
|
|
726
|
+
return SolidWorksMCPConfig(**data)
|
|
727
|
+
return SolidWorksMCPConfig.from_env(str(config_path))
|
|
728
|
+
|
|
729
|
+
return SolidWorksMCPConfig.from_env()
|