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.
Files changed (115) hide show
  1. solidworks_mcp/__init__.py +57 -0
  2. solidworks_mcp/adapters/__init__.py +40 -0
  3. solidworks_mcp/adapters/base.py +1882 -0
  4. solidworks_mcp/adapters/circuit_breaker.py +2052 -0
  5. solidworks_mcp/adapters/com_executor.py +252 -0
  6. solidworks_mcp/adapters/complexity_analyzer.py +272 -0
  7. solidworks_mcp/adapters/connection_pool.py +1884 -0
  8. solidworks_mcp/adapters/factory.py +366 -0
  9. solidworks_mcp/adapters/intelligent_router.py +218 -0
  10. solidworks_mcp/adapters/mock_adapter.py +4016 -0
  11. solidworks_mcp/adapters/pywin32_adapter.py +2842 -0
  12. solidworks_mcp/adapters/solidworks/__init__.py +17 -0
  13. solidworks_mcp/adapters/solidworks/bitmap.py +180 -0
  14. solidworks_mcp/adapters/solidworks/com_utils.py +56 -0
  15. solidworks_mcp/adapters/solidworks/dimension_layout.py +753 -0
  16. solidworks_mcp/adapters/solidworks/documentation.py +1476 -0
  17. solidworks_mcp/adapters/solidworks/drawing_standard.py +1993 -0
  18. solidworks_mcp/adapters/solidworks/face_selection.py +392 -0
  19. solidworks_mcp/adapters/solidworks/features.py +3362 -0
  20. solidworks_mcp/adapters/solidworks/io.py +3649 -0
  21. solidworks_mcp/adapters/solidworks/rebuild_diagnostics.py +269 -0
  22. solidworks_mcp/adapters/solidworks/rebuild_inspector.py +146 -0
  23. solidworks_mcp/adapters/solidworks/selection.py +308 -0
  24. solidworks_mcp/adapters/solidworks/sketch.py +2545 -0
  25. solidworks_mcp/adapters/sw_feature_errors.py +66 -0
  26. solidworks_mcp/adapters/sw_type_info.py +317 -0
  27. solidworks_mcp/adapters/vba_adapter.py +318 -0
  28. solidworks_mcp/adapters/vba_macro_executor.py +215 -0
  29. solidworks_mcp/agents/__init__.py +68 -0
  30. solidworks_mcp/agents/design_knowledge/assembly_patterns.md +127 -0
  31. solidworks_mcp/agents/design_knowledge/hinges.md +118 -0
  32. solidworks_mcp/agents/design_knowledge/snap_fits.md +93 -0
  33. solidworks_mcp/agents/design_knowledge/solidworks_basics.md +3 -0
  34. solidworks_mcp/agents/design_knowledge/tolerancing.md +128 -0
  35. solidworks_mcp/agents/harness.py +216 -0
  36. solidworks_mcp/agents/history_db.py +1508 -0
  37. solidworks_mcp/agents/retrieval_index.py +164 -0
  38. solidworks_mcp/agents/schemas.py +165 -0
  39. solidworks_mcp/agents/smoke_test.py +285 -0
  40. solidworks_mcp/agents/soc_exporter.py +650 -0
  41. solidworks_mcp/agents/soc_pickup.py +332 -0
  42. solidworks_mcp/agents/soc_rewind.py +221 -0
  43. solidworks_mcp/agents/vector_rag.py +665 -0
  44. solidworks_mcp/cache/__init__.py +5 -0
  45. solidworks_mcp/cache/response_cache.py +164 -0
  46. solidworks_mcp/config.py +729 -0
  47. solidworks_mcp/exceptions.py +37 -0
  48. solidworks_mcp/security/__init__.py +68 -0
  49. solidworks_mcp/security/auth.py +128 -0
  50. solidworks_mcp/security/cors.py +27 -0
  51. solidworks_mcp/security/rate_limiting.py +90 -0
  52. solidworks_mcp/security/runtime.py +155 -0
  53. solidworks_mcp/server.py +777 -0
  54. solidworks_mcp/server_cli_fixed.py +120 -0
  55. solidworks_mcp/setup/__init__.py +1 -0
  56. solidworks_mcp/setup/cli.py +399 -0
  57. solidworks_mcp/setup/clients.py +157 -0
  58. solidworks_mcp/setup/config_file.py +230 -0
  59. solidworks_mcp/setup/handshake.py +202 -0
  60. solidworks_mcp/setup/launcher.py +102 -0
  61. solidworks_mcp/setup/legacy.py +100 -0
  62. solidworks_mcp/setup/registration.py +193 -0
  63. solidworks_mcp/setup/solidworks.py +49 -0
  64. solidworks_mcp/tools/__init__.py +64 -0
  65. solidworks_mcp/tools/analysis.py +723 -0
  66. solidworks_mcp/tools/automation.py +578 -0
  67. solidworks_mcp/tools/docs_discovery.py +1476 -0
  68. solidworks_mcp/tools/drawing.py +1015 -0
  69. solidworks_mcp/tools/drawing_analysis.py +456 -0
  70. solidworks_mcp/tools/drawing_automation.py +627 -0
  71. solidworks_mcp/tools/engineering_data.py +466 -0
  72. solidworks_mcp/tools/error_classifier.py +232 -0
  73. solidworks_mcp/tools/export.py +833 -0
  74. solidworks_mcp/tools/file_facts.py +40 -0
  75. solidworks_mcp/tools/file_management.py +1473 -0
  76. solidworks_mcp/tools/input_compat.py +17 -0
  77. solidworks_mcp/tools/macro_recording.py +464 -0
  78. solidworks_mcp/tools/modeling.py +2360 -0
  79. solidworks_mcp/tools/sketching.py +1422 -0
  80. solidworks_mcp/tools/template_management.py +367 -0
  81. solidworks_mcp/tools/tool_boundary.py +280 -0
  82. solidworks_mcp/tools/vba_generation.py +1145 -0
  83. solidworks_mcp/ui/__init__.py +9 -0
  84. solidworks_mcp/ui/local_llm.py +725 -0
  85. solidworks_mcp/ui/routers/__init__.py +10 -0
  86. solidworks_mcp/ui/routers/checkpoint.py +24 -0
  87. solidworks_mcp/ui/routers/docs.py +47 -0
  88. solidworks_mcp/ui/routers/llm.py +83 -0
  89. solidworks_mcp/ui/routers/local_model.py +69 -0
  90. solidworks_mcp/ui/routers/model.py +75 -0
  91. solidworks_mcp/ui/routers/preview.py +38 -0
  92. solidworks_mcp/ui/routers/session.py +161 -0
  93. solidworks_mcp/ui/routers/viewer.py +154 -0
  94. solidworks_mcp/ui/schemas.py +502 -0
  95. solidworks_mcp/ui/server.py +298 -0
  96. solidworks_mcp/ui/service.py +481 -0
  97. solidworks_mcp/ui/services/__init__.py +136 -0
  98. solidworks_mcp/ui/services/_utils.py +958 -0
  99. solidworks_mcp/ui/services/checkpoint_service.py +1110 -0
  100. solidworks_mcp/ui/services/docs_service.py +282 -0
  101. solidworks_mcp/ui/services/llm_service.py +956 -0
  102. solidworks_mcp/ui/services/model_service.py +459 -0
  103. solidworks_mcp/ui/services/parameter_repair_service.py +314 -0
  104. solidworks_mcp/ui/services/preview_service.py +489 -0
  105. solidworks_mcp/ui/services/session_service.py +1389 -0
  106. solidworks_mcp/utils/__init__.py +9 -0
  107. solidworks_mcp/utils/feature_tree_classifier.py +342 -0
  108. solidworks_mcp/utils/logging.py +76 -0
  109. solidworks_mcp/utils/validation.py +77 -0
  110. solidworks_mcp/version.py +8 -0
  111. solidworks_mcp_python-1.5.0.dist-info/METADATA +410 -0
  112. solidworks_mcp_python-1.5.0.dist-info/RECORD +115 -0
  113. solidworks_mcp_python-1.5.0.dist-info/WHEEL +4 -0
  114. solidworks_mcp_python-1.5.0.dist-info/entry_points.txt +3 -0
  115. solidworks_mcp_python-1.5.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,298 @@
1
+ """FastAPI backend for the Prefab CAD assistant dashboard.
2
+
3
+ REST API endpoints for dashboard actions: - GET /api/ui/state - Hydrate UI with current
4
+ session state - POST /api/ui/brief/approve - Accept user goal - POST /api/ui/clarify -
5
+ Call GitHub Copilot to generate Q&A - POST /api/ui/family/inspect - Call GitHub Copilot
6
+ to classify design family - POST /api/ui/family/accept - Accept proposed family - POST
7
+ /api/ui/checkpoints/execute-next - Execute next checkpoint (adapter-backed; unsupported
8
+ tools marked MOCKED) - POST /api/ui/preview/refresh - Sync 3D view from SolidWorks
9
+ export_image - POST /api/ui/manual-sync/reconcile - Detect manual edits via snapshot
10
+ diff - GET /previews/* - Serve static PNG preview images - GET /docs - FastAPI OpenAPI
11
+ UI for local endpoint inspection
12
+
13
+ LLM Integration: - Clarify button: GitHub Copilot (default: github:openai/gpt-4.1) -
14
+ Inspect button: GitHub Copilot family classification - Requires: GH_TOKEN or
15
+ GITHUB_API_KEY environment variable with models:read scope
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import time
22
+ from pathlib import Path as FilePath
23
+ from typing import Any
24
+
25
+ import uvicorn
26
+ from fastapi import FastAPI, Request
27
+ from fastapi.middleware.cors import CORSMiddleware
28
+ from fastapi.staticfiles import StaticFiles
29
+ from loguru import logger
30
+
31
+ from .routers import checkpoint as checkpoint_router
32
+ from .routers import docs as docs_router
33
+ from .routers import llm as llm_router
34
+ from .routers import local_model as local_model_router
35
+ from .routers import model as model_router
36
+ from .routers import preview as preview_router
37
+ from .routers import session as session_router
38
+ from .routers import viewer as viewer_router
39
+ from .services import ( # noqa: F401 (re-exported for monkeypatching in tests)
40
+ DEFAULT_API_ORIGIN,
41
+ DEFAULT_SESSION_ID,
42
+ accept_family_choice,
43
+ approve_design_brief,
44
+ build_dashboard_state,
45
+ build_dashboard_trace_payload,
46
+ connect_target_model,
47
+ ensure_preview_dir,
48
+ execute_next_checkpoint,
49
+ ingest_reference_source,
50
+ inspect_family,
51
+ reconcile_manual_edits,
52
+ refresh_preview,
53
+ request_clarifications,
54
+ select_workflow_mode,
55
+ update_ui_preferences,
56
+ )
57
+
58
+ UI_LOG_DIR = FilePath(".solidworks_mcp") / "ui_logs"
59
+ UI_HTTP_LOG_FILE = UI_LOG_DIR / "ui_http.log"
60
+ _UI_FILE_SINK_ID: int | None = None
61
+
62
+
63
+ def _configure_ui_file_logging() -> None:
64
+ """Build internal configure ui file logging.
65
+
66
+ Returns:
67
+ None: None.
68
+ """
69
+
70
+ global _UI_FILE_SINK_ID
71
+ if _UI_FILE_SINK_ID is not None:
72
+ return
73
+
74
+ UI_LOG_DIR.mkdir(parents=True, exist_ok=True)
75
+ _UI_FILE_SINK_ID = logger.add(
76
+ str(UI_HTTP_LOG_FILE),
77
+ level="INFO",
78
+ rotation="10 MB",
79
+ retention="14 days",
80
+ encoding="utf-8",
81
+ enqueue=True,
82
+ filter=lambda record: "[ui." in record["message"],
83
+ format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level:<8} | {message}",
84
+ )
85
+ logger.info(
86
+ "[ui.logging] file sink enabled path={}", str(UI_HTTP_LOG_FILE.resolve())
87
+ )
88
+
89
+
90
+ def _should_log_request(path: str) -> bool:
91
+ """Build internal should log request.
92
+
93
+ Args:
94
+ path (str): Filesystem path for the operation.
95
+
96
+ Returns:
97
+ bool: True if should log request, otherwise False.
98
+ """
99
+
100
+ return path == "/api/health" or path.startswith("/api/ui/")
101
+
102
+
103
+ def _sanitize_log_payload(value: Any) -> Any:
104
+ """Build internal sanitize log payload.
105
+
106
+ Args:
107
+ value (Any): The value value.
108
+
109
+ Returns:
110
+ Any: The result produced by the operation.
111
+ """
112
+
113
+ if isinstance(value, dict):
114
+ sanitized: dict[str, Any] = {}
115
+ for key, item in value.items():
116
+ if key == "data" and isinstance(item, str):
117
+ sanitized[key] = f"<omitted base64 payload len={len(item)}>"
118
+ elif key == "uploaded_files" and isinstance(item, list):
119
+ sanitized[key] = [_sanitize_log_payload(entry) for entry in item]
120
+ else:
121
+ sanitized[key] = _sanitize_log_payload(item)
122
+ return sanitized
123
+ if isinstance(value, list):
124
+ return [_sanitize_log_payload(item) for item in value]
125
+ return value
126
+
127
+
128
+ def _decode_request_body(body: bytes) -> Any:
129
+ """Build internal decode request body.
130
+
131
+ Args:
132
+ body (bytes): The body value.
133
+
134
+ Returns:
135
+ Any: The result produced by the operation.
136
+ """
137
+
138
+ if not body:
139
+ return None
140
+ try:
141
+ parsed = json.loads(body)
142
+ except json.JSONDecodeError:
143
+ return body.decode("utf-8", errors="replace")
144
+ return _sanitize_log_payload(parsed)
145
+
146
+
147
+ app = FastAPI(
148
+ title="SolidWorks Prefab UI Server",
149
+ version="0.1.0",
150
+ summary="FastAPI backend for the interactive SolidWorks Prefab dashboard.",
151
+ )
152
+
153
+ _configure_ui_file_logging()
154
+
155
+ app.add_middleware(
156
+ CORSMiddleware,
157
+ allow_origin_regex=r"https?://(127\.0\.0\.1|localhost):\d+$",
158
+ allow_methods=["*"],
159
+ allow_headers=["*"],
160
+ )
161
+
162
+
163
+ # TODO: Tasks pending completion -@andre at 4/15/2026, 7:57:32 PM
164
+ # Need to update on_event to the correct fastapi lifecycle event hook
165
+ @app.on_event("startup")
166
+ async def _startup_ingest_design_knowledge() -> None:
167
+ """Auto-ingest bundled design knowledge markdown files into FAISS on first startup.
168
+
169
+ Returns:
170
+ None: None.
171
+ """
172
+ import logging as _logging
173
+
174
+ _log = _logging.getLogger(__name__)
175
+ knowledge_dir = FilePath(__file__).parent.parent / "agents" / "design_knowledge"
176
+ if not knowledge_dir.is_dir():
177
+ return
178
+ md_files = sorted(knowledge_dir.glob("*.md"))
179
+ if not md_files:
180
+ return
181
+ try:
182
+ from ..agents.vector_rag import VectorRAGIndex # noqa: PLC0415
183
+
184
+ namespace = "solidworks-design-knowledge"
185
+ rag_dir = FilePath(".solidworks_mcp") / "rag"
186
+ idx = VectorRAGIndex.load(namespace=namespace, rag_dir=rag_dir)
187
+ # Only re-ingest if the index is empty (fresh install) or stale
188
+ if idx.chunk_count == 0:
189
+ for md_file in md_files:
190
+ text = md_file.read_text(encoding="utf-8")
191
+ idx.ingest_text(
192
+ text, source=md_file.name, tags=[namespace, md_file.stem]
193
+ )
194
+ idx.save()
195
+ _log.info(
196
+ "Auto-ingested %d design knowledge files into FAISS namespace '%s'",
197
+ len(md_files),
198
+ namespace,
199
+ )
200
+ else:
201
+ _log.debug(
202
+ "FAISS namespace '%s' already loaded (%d chunks) — skipping auto-ingest",
203
+ namespace,
204
+ idx.chunk_count,
205
+ )
206
+ except ImportError:
207
+ _log.debug(
208
+ "faiss/sentence-transformers not installed — skipping design knowledge auto-ingest"
209
+ )
210
+ except Exception as exc:
211
+ _log.warning("Design knowledge auto-ingest failed (non-fatal): %s", exc)
212
+
213
+
214
+ @app.middleware("http")
215
+ async def log_ui_requests(request: Request, call_next: Any) -> Any:
216
+ """Log each UI request (method, path, body) before passing it on.
217
+
218
+ Args:
219
+ request (Request): The incoming request.
220
+ call_next (Any): Starlette's handler for the rest of the chain.
221
+
222
+ Returns:
223
+ Any: The downstream response.
224
+ """
225
+
226
+ if not _should_log_request(request.url.path):
227
+ return await call_next(request)
228
+
229
+ started_at = time.perf_counter()
230
+ raw_body = await request.body()
231
+ payload = {
232
+ "method": request.method,
233
+ "path": request.url.path,
234
+ "query": dict(request.query_params),
235
+ "body": _decode_request_body(raw_body),
236
+ }
237
+
238
+ logger.info(
239
+ "[ui.http.request] payload={}",
240
+ json.dumps(payload, ensure_ascii=True, default=str),
241
+ )
242
+
243
+ try:
244
+ response = await call_next(request)
245
+ except Exception as exc:
246
+ duration_ms = round((time.perf_counter() - started_at) * 1000, 2)
247
+ logger.exception(
248
+ "[ui.http.error] method={} path={} duration_ms={} error={}",
249
+ request.method,
250
+ request.url.path,
251
+ duration_ms,
252
+ exc,
253
+ )
254
+ raise
255
+
256
+ duration_ms = round((time.perf_counter() - started_at) * 1000, 2)
257
+ logger.info(
258
+ "[ui.http.response] method={} path={} status_code={} duration_ms={}",
259
+ request.method,
260
+ request.url.path,
261
+ response.status_code,
262
+ duration_ms,
263
+ )
264
+ return response
265
+
266
+
267
+ app.mount(
268
+ "/previews",
269
+ StaticFiles(directory=str(ensure_preview_dir().resolve())),
270
+ name="previews",
271
+ )
272
+
273
+ # ---------------------------------------------------------------------------
274
+ # Include modular routers
275
+ # ---------------------------------------------------------------------------
276
+ app.include_router(session_router.router)
277
+ app.include_router(model_router.router)
278
+ app.include_router(preview_router.router)
279
+ app.include_router(llm_router.router)
280
+ app.include_router(checkpoint_router.router)
281
+ app.include_router(docs_router.router)
282
+ app.include_router(local_model_router.router)
283
+ app.include_router(viewer_router.router)
284
+
285
+
286
+ @app.get("/api/health")
287
+ async def health() -> dict[str, str]:
288
+ """Health check endpoint."""
289
+ return {"status": "ok"}
290
+
291
+
292
+ def main() -> None:
293
+ """Run the dashboard backend locally."""
294
+ uvicorn.run(app, host="127.0.0.1", port=8766)
295
+
296
+
297
+ if __name__ == "__main__":
298
+ main()