solidworks-mcp
by lildebil0
README.md
# solidworks-mcp
**English** · [Русский](README.ru.md) · [Кыргызча](README.ky.md)
> An MCP server that gives an LLM **57 tools**: a cross-platform **build123d code-CAD engine** (generate geometry in Python → STEP/STL/PNG) and a **SolidWorks COM automation** surface (drive a running SolidWorks — documents, dimensions, sketches, features, drawings, VBA).
[](https://www.python.org/)
[](LICENSE)
[](#what-works--what-doesnt)
---
## Contents
- [What it is](#what-it-is)
- [What works / What doesn't](#what-works--what-doesnt)
- [Tool reference](#tool-reference)
- [Architecture](#architecture)
- [Two CAD paths](#two-cad-paths)
- [Install & run](#install--run)
- [Configure in an MCP client](#configure-in-an-mcp-client)
- [makepy (early binding)](#makepy-early-binding)
- [Safety](#safety)
- [Development & tests](#development--tests)
- [License & attribution](#license--attribution)
---
## What it is
`solidworks-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io/) server built on [FastMCP](https://github.com/jlowin/fastmcp). It exposes two complementary CAD surfaces to any MCP client (Claude, or another LLM):
1. A **build123d code-CAD engine** — describe a part in Python, run it in a sandbox, get back a STEP/STL file and a PNG preview so the model can *see* the geometry. Pure Python + OpenCascade (OCCT); runs on any OS, no SolidWorks needed.
2. A **SolidWorks COM automation** surface — the `sw_*` tools drive a **running, licensed SolidWorks** over COM: open/save native documents, read/write driving dimensions, build sketches and features, create drawings, run VBA, and — through a reflective core — reach the **entire** SolidWorks API.
All 57 tools are registered by one FastMCP server that speaks MCP over stdio.

---
## What works / What doesn't
This is an **honest** status section. The repo is a working skeleton with a green, cross-platform core and a fully implemented — but **not yet live-verified** — SolidWorks surface.
| Status | Meaning |
|:------:|---------|
| ✅ | **Works & tested** — exercised by the automated test suite, cross-platform. |
| 🧪 | **Implemented, NOT yet verified on live SolidWorks** — logic covered by mock-COM tests only; needs Windows + a running, licensed SolidWorks to exercise for real. |
| ⚠️ | **Caveat** — read before relying on it. |
**✅ Works & tested**
- The **build123d engine** (all 6 tools): generate → render → DRC → export STEP/STL, behind an AST sandbox. Cross-platform.
- **MCP registration** of all **57 tools** by the FastMCP server.
- The **test suite**: **47 pytest passing** — 13 build123d/sandbox + 34 mock-COM. Runs on any OS, no SolidWorks required.
**🧪 Implemented, not yet verified on live SolidWorks**
- **Every `sw_*` tool** (51 of them: 11 base + 40 advanced). They are written, import cleanly, and their Python logic — the object-handle registry, argument marshaling, dispatch routing, enum resolution, screenshot→PNG, VBA temp-file handling — is covered by **mock-COM unit tests**.
- What has **not** happened: running them against **real geometry**. SolidWorks COM is STA and **not headless**, so this requires a Windows machine with a running, licensed SolidWorks. On a machine without one, a real `sw_*` call **fails loud** with `SolidWorks not available` — by design, not a silent fake.
**⚠️ Caveats**
- The **Tier-1 wrappers hardcode specific COM method signatures** (e.g. `FeatureExtrusion3`, `FeatureCut3`). Method shapes vary slightly across SolidWorks releases; if yours differs and a wrapper raises, **fall back to `sw_call`** with the exact method from the [API Help](https://help.solidworks.com/).
- Some calls that return data through **ByRef out-parameters** need **makepy** (early binding) to marshal correctly; late binding covers the vast majority. See [makepy](#makepy-early-binding).
- **`sw_run_vba` and `sw_call` execute arbitrary local code** in SolidWorks — the same trust level as a user running a macro by hand. Local, user-invoked use only; do not expose this server to untrusted callers. See [Safety](#safety).
For the deep dive on the SolidWorks surface — full architecture, makepy bootstrap, the safety model, and a worked end-to-end live-acceptance sequence — see **[`docs/SW_API.md`](docs/SW_API.md)**.
---
## Tool reference
Units: the build123d engine is unitless build123d (mm by convention); Tier-1 `sw_*` wrappers take **millimetres / degrees**; the raw `sw_call` core talks to the API in **metres / radians**.
### build123d engine — 6 — ✅ works & tested
| Tool | What it does |
|------|--------------|
| `generate_part(code)` | Run build123d code in the sandbox → PNG preview + metrics (bbox, size, volume, CoM) + `part_id` |
| `render_views(part_id)` | Isometric + front + top + right views as one PNG |
| `export_model(part_id, format, path)` | Write `step` or `stl` to disk |
| `run_drc(part_id, min_wall, max_bbox)` | Minimal DFM: volume > 0, max size, min-dimension proxy |
| `batch_generate(specs)` | Many parts in one call (list of code strings) |
| `list_catalog(query)` | bd_warehouse standard parts — **stub / TODO** |
### SolidWorks base — 11 — 🧪 implemented, not live-tested
| Tool | What it does |
|------|--------------|
| `sw_connect(launch_if_needed=False)` | Attach to (or optionally launch) SolidWorks; returns its revision |
| `sw_open(filepath)` | Open a native `.sldprt` / `.sldasm` / `.slddrw` |
| `sw_save(filepath=None)` | Save in place, or Save As to a path |
| `sw_close(save_first=False)` | Close the active document |
| `sw_export_step(output_path)` | Export the active model to STEP (clears selection first) |
| `sw_rebuild(force=False)` | `EditRebuild3` (changed only) / `ForceRebuild3` (whole tree) |
| `sw_get_dimension(name)` | Read a named driving dimension, in mm (e.g. `D1@Sketch1`) |
| `sw_set_dimension(name, value_mm, do_rebuild=True)` | Set a named dimension and rebuild |
| `sw_list_configurations()` | List configuration names of the active document |
| `sw_activate_configuration(name)` | Activate a configuration by name |
| `sw_run_macro(macro_path, module_name, procedure_name)` | Run a prebuilt VBA macro via `RunMacro2` |
### SolidWorks Tier-0 generic core — 7 — 🧪
This layer reaches the **entire** SolidWorks API by itself.
| Tool | What it does |
|------|--------------|
| `sw_call(handle, method, args=[])` | ★ Invoke **any** COM method on the object behind `handle`; returns a value or a new handle |
| `sw_get_prop(handle, prop)` | Read any COM property |
| `sw_set_prop(handle, prop, value)` | Write any COM property |
| `sw_enum(name)` | Resolve a `swconst` constant by name (e.g. `swEndCondBlind` → 0) |
| `sw_handles()` | List live object handles (`app`, `doc:1`, `obj:2`, …) |
| `sw_release(handle)` | Drop a handle |
| `sw_capture(width, height)` | Screenshot the active view/sheet → image |
### SolidWorks Tier-1 ergonomic wrappers — 32 — 🧪 (version-sensitive)
| Area | Tools |
|------|-------|
| New docs | `sw_new_part`, `sw_new_drawing` |
| Sketch | `sw_sketch_start`, `sw_sketch_line`, `sw_sketch_circle`, `sw_sketch_rect`, `sw_sketch_arc`, `sw_sketch_add_relation`, `sw_sketch_add_dimension`, `sw_sketch_exit` |
| Feature | `sw_extrude`, `sw_revolve`, `sw_loft`, `sw_sweep`, `sw_fillet`, `sw_chamfer`, `sw_hole`, `sw_linear_pattern`, `sw_circular_pattern` |
| Drawing | `sw_add_sheet`, `sw_add_view`, `sw_add_projected_view`, `sw_add_section_view`, `sw_add_detail_view`, `sw_insert_model_dimensions`, `sw_add_note`, `sw_add_balloon`, `sw_set_titleblock`, `sw_insert_bom`, `sw_export_drawing` |
| Select | `sw_select_by_id`, `sw_clear_selection` |
### SolidWorks Tier-2 — 1 — 🧪
| Tool | What it does |
|------|--------------|
| `sw_run_vba(code, module, proc)` | Run arbitrary VBA (write a temp `.swb`, run via `RunMacro2`) — full macro-recorder parity |
---
## Architecture
The 57 tools split into the cross-platform build123d engine (green) and the SolidWorks COM stack (amber, needs a running SolidWorks).

### The core idea: object-handle registry + reflective `sw_call`
The SolidWorks API is thousands of methods across hundreds of interfaces, and almost every interesting one *returns another COM object* (`ISldWorks` → `IModelDoc2` → `IFeatureManager` → `IFeature` …). Rather than wrap each method, the **Tier-0 core**:
1. Keeps live COM objects in a process-global registry keyed by short string ids — the root `app` (= `ISldWorks`), then `doc:1`, `feat:2`, `sketch:3`, … The LLM never sees a raw COM pointer; it sees an id it threads back into the next call.
2. Exposes `sw_call(handle, method, args)`, which invokes **any** method by name (late-bound, no makepy needed). If the return is a COM object, it is auto-registered and its id handed back; otherwise a JSON value is returned.
**This pair alone reaches the entire API.** The 32 Tier-1 wrappers exist only so the common 80% reads naturally — each resolves the right COM object and makes one `sw_call`-style invocation underneath.

<details>
<summary>Code map (where things live)</summary>
| File | Role |
|------|------|
| `src/solidworks_mcp/server.py` | FastMCP server — registers `sw_*` + build123d tools, wraps PNG → image content |
| `src/solidworks_mcp/sw_tools.py` | Base 11 `sw_*` wrappers; then registers the advanced tools |
| `src/solidworks_mcp/sw_advanced_tools.py` | Tier-0/1/2 `@mcp.tool` adapters (generic core + sketch/feature/drawing wrappers + VBA) |
| `src/solidworks_mcp/sw_core.py` | Tier-0 COM core: handle registry, reflective `call`, `get_prop`/`set_prop`, enum, capture, run_vba |
| `src/solidworks_mcp/solidworks_bridge.py` | SolidWorks COM bridge (lazy pywin32, fail-loud, one connection per process) |
| `src/solidworks_mcp/tools.py` | build123d engine: tool logic + part registry + metrics + DRC |
| `src/solidworks_mcp/render.py` | HLR PNG previews (iso + 3 ortho), headless matplotlib |
| `src/solidworks_mcp/sandbox.py` | AST whitelist: blocks os/sys/subprocess/eval/open/dunder |
</details>
---
## Two CAD paths
There are two ways to produce geometry. **Path A** works anywhere and is tested; **Path B** needs a live SolidWorks and is not yet verified against real geometry.

- **Path A (green, works anywhere, tested):** describe a part in code → build123d → STEP → optionally `sw_open` it in SolidWorks.
- **Path B (amber, Windows + live SolidWorks, not yet verified):** drive SolidWorks directly (sketch/feature/drawing tools or `sw_call`) → native `.sldprt` / `.slddrw`.
---
## Install & run
**Requirements:** Python **3.12–3.14**, [uv](https://docs.astral.sh/uv/). For the SolidWorks tools: **Windows + a licensed, running SolidWorks + pywin32**.
```bash
git clone https://github.com/lildebil0/solidworks-mcp
cd solidworks-mcp
uv venv --python 3.12
uv pip install -e ".[solidworks,dev]" # SolidWorks (pywin32 on Windows) + build123d + test deps
# build123d-only / non-Windows:
# uv pip install -e ".[dev]"
```
Run the server (it speaks MCP over **stdio** — there is no port; the MCP client launches the process):
```bash
solidworks-mcp # the installed console script
# or, without installing onto PATH:
uv run solidworks-mcp
```
**Enabling / disabling the SolidWorks tools:**
- The `sw_*` tools **register automatically** whenever `pywin32` is importable. Registration does **not** launch SolidWorks; the app is only touched on an actual `sw_*` call (call `sw_connect` first).
- On non-Windows / no pywin32, they **auto-skip** and the build123d tools stay available.
- Set `SOLIDWORKS_MCP_DISABLE=1` to force the build123d-only surface even where pywin32 exists.
---
## Configure in an MCP client
Add this to your MCP client config — Claude Code project `.mcp.json`, or a client's `mcpServers` block (e.g. `claude_desktop_config.json`). Replace `<repo>` with the absolute path to your clone.
```json
{
"mcpServers": {
"solidworks-mcp": {
"command": "uv",
"args": ["run", "--directory", "<repo>", "solidworks-mcp"]
}
}
}
```
Once the package is installed on your `PATH`, you can use the console script directly instead:
```json
{
"mcpServers": {
"solidworks-mcp": {
"command": "solidworks-mcp"
}
}
}
```
After adding it, restart the client and confirm the `solidworks-mcp` tools appear.
---
## makepy (early binding)
The reflective core runs **late-bound** by default, so it works on any machine with a running SolidWorks **without** makepy. Generate a typed wrapper only when you hit a method whose **ByRef out-array** parameters do not marshal under late binding (some selection / mass-property queries, certain `Get…` calls), or when you want the **full** `swconst` set resolved by `sw_enum`:
```bash
python -m win32com.client.makepy "SOLIDWORKS 2025 Type Library"
```
Sources for signatures (legal and sufficient): the **SolidWorks Type Library** (ships with SolidWorks) and the official **[API Help](https://help.solidworks.com/)**. Reverse-engineering the SolidWorks binaries is neither used nor needed. Details in [`docs/SW_API.md`](docs/SW_API.md).
---
## Safety
- **`sw_run_vba` is arbitrary local code execution** inside the running SolidWorks process — the same trust level as a user running a macro by hand. That is the intended capability for **local, user-invoked** desktop automation. Do **not** expose this MCP server to untrusted or remote callers; there is no sandbox here.
- **`sw_call` / `sw_set_prop`** can likewise invoke **any** SolidWorks operation, including destructive ones (delete bodies, overwrite files via `SaveAs`). Treat the server as you would the SolidWorks GUI itself.
- The build123d `generate_part` tool runs model-authored Python behind an **AST whitelist** (`sandbox.py`) that blocks `os`/`sys`/`subprocess`/`eval`/`open`/dunder escapes *before* execution. This is a deny-by-default static gate, not a full OS-level sandbox; for untrusted multi-user use, add process isolation + timeouts (see the TODOs in `docs/SW_API.md`).
---
## Development & tests
```bash
uv run python -m pytest
```
Note the `-m`: the current working directory must be on `sys.path`, because two tests do `from tests.test_sw_core import FakeCom`. A bare `pytest` invocation fails those two; `uv run python -m pytest` runs the full **47** green.
The suite is two parts: the build123d engine smoke + sandbox gate (13, which skip cleanly if OCCT is absent), and the mock-COM suites for the SolidWorks generic core and advanced-tool registration/wiring (34, no SolidWorks needed). They verify the registry, marshaling (including nested handles), dispatch routing, enum resolution, error mapping, screenshot→PNG, and VBA temp-file handling — they do **not** assert that a real part/drawing is produced. That is the live sequence in [`docs/SW_API.md`](docs/SW_API.md).
---
## License & attribution
Licensed under the **MIT License** — see [`LICENSE`](LICENSE).
The SolidWorks COM bridge and the full-API core are **original code**; no source was copied verbatim from third-party projects. COM signatures and integration patterns were informed by published documentation and prior open-source work, credited in full in [`NOTICE`](NOTICE):
- **[build123d](https://github.com/gumyr/build123d)** — the code-CAD engine (Apache-2.0).
- **[alisamsam/solidworks-mcp](https://github.com/alisamsam/solidworks-mcp)** (MIT) — studied for the COM connection pattern and ByRef out-parameter handling.
- **[vespo92/SolidworksMCP-TS](https://github.com/vespo92/SolidworksMCP-TS)** (MIT) — studied for COM call signatures (dimensions, export, rebuild, macros).
- The Tier-1 wrapper method signatures come from the official **SOLIDWORKS API Help** (Dassault Systèmes, help.solidworks.com); the object-handle registry and reflective-dispatch design are original.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues