Skip to main content
Glama
Christancho-co

solidworks-mcp

README.md
# solidworks-mcp

An MCP server that drives a local SOLIDWORKS installation to build and modify
parametric solid models.

Verified against **SOLIDWORKS 2026 SP0** (revision 34.0.0) on Windows 11.

## How it works

```
MCP client  ──stdio──►  solidworks-mcp  ──COM──►  SLDWORKS.exe
```

SOLIDWORKS exposes a classic COM automation API. The server attaches to a
running instance (or launches one), and every tool maps onto that API.

**All lengths are in millimetres and all angles in degrees.** The SOLIDWORKS API
is metric-SI internally; conversion happens at the tool boundary.

## Requirements

- SOLIDWORKS installed and licensed, on the same machine.
- Python 3.12+, 64-bit — it must match SOLIDWORKS' architecture or COM will not bind.
- [uv](https://docs.astral.sh/uv/) for dependency management.

## Install

```bash
uv sync
```

## Register with an MCP client

For Claude Code:

```bash
claude mcp add solidworks -- uv --directory E:\solid run solidworks-mcp
```

For a client that reads a JSON config:

```json
{
  "mcpServers": {
    "solidworks": {
      "command": "uv",
      "args": ["--directory", "E:\\solid", "run", "solidworks-mcp"]
    }
  }
}
```

## Tools

**Session and documents** — `solidworks_status`, `new_part`, `open_part`,
`save_part`, `close_part`

**Sketching** — `list_planes`, `start_sketch`, `start_sketch_on_face`,
`sketch_line`, `sketch_centerline`, `sketch_circle`, `sketch_rectangle`,
`sketch_arc`, `sketch_polygon`, `sketch_ellipse`, `add_sketch_dimension`,
`add_sketch_relation`, `finish_sketch`

**Features** — `extrude`, `cut_extrude`, `revolve`, `fillet`, `select_entity`,
`clear_selection`

**Parametric control** — `list_features`, `list_dimensions`, `set_dimension`,
`add_equation`, `list_equations`, `rebuild`

**Inspection** — `get_measurements`, `capture_view`

## A worked example

Building a 80 × 50 × 10 mm plate with a hole, then driving it parametrically:

```
new_part
start_sketch(plane="front")
sketch_rectangle(0, 0, 80, 50)
add_sketch_dimension(entities=[[40, 0]], value=80)   -> "D1@Croquis1"
add_sketch_dimension(entities=[[0, 25]], value=50)   -> "D2@Croquis1"
finish_sketch
extrude(depth=10)

start_sketch(plane="front")
sketch_circle(40, 25, 8)
finish_sketch
cut_extrude(depth=10, end_condition="through_all", reverse=True)

fillet(radius=5, edges=[[0,0,5], [80,0,5], [80,50,5], [0,50,5]])

set_dimension("D1@Croquis1", 120)   -> the solid rebuilds to 120 mm wide
get_measurements                    -> bounding box 120 x 50 x 10 mm
capture_view("isometric")
```

## Things worth knowing

**Sketches created through the API have no dimensions.** SOLIDWORKS only adds
driving dimensions when you ask for them, so a sketch drawn with `sketch_*`
alone has nothing to drive. Call `add_sketch_dimension` while the sketch is
still open if you intend to change the geometry later.

**Cut direction follows the sketch normal.** A sketch on the Front Plane cutting
a solid that was extruded away from it needs `reverse=True`, otherwise the cut
travels into empty space and fails.

**Reference plane names are localised.** A Spanish install names features
`Croquis1` and `Saliente-Extruir1`. Tools accept the logical aliases
`front`/`top`/`right` and resolve them by position in the feature tree, so they
work regardless of UI language. `list_planes` reports the real names.

**SOLIDWORKS must be running.** There is no supported headless mode. The server
launches the application if it is not already open.

**Modal dialogs deadlock COM.** `add_sketch_dimension` temporarily disables the
"input dimension value" preference, which would otherwise pop a modal box and
hang the call, and restores it afterwards.

## Implementation notes

Two pywin32 behaviours shape the code and are easy to trip over:

- **Zero-argument COM members are auto-invoked on attribute access.** Under late
  binding `doc.GetTitle` returns the title string; `doc.GetTitle()` raises
  `TypeError: 'str' object is not callable`. Members taking one or more
  arguments are called normally.
- **Typed nulls and in/out parameters need explicit VARIANTs.** Optional
  interface arguments reject a bare `None` with "Type mismatch" and need
  `VARIANT(VT_DISPATCH, None)`; error and warning out-parameters need
  `VARIANT(VT_BYREF | VT_I4, 0)`, with the result read back from `.value`.

COM objects live in a single-threaded apartment, so `com_bridge.py` funnels every
call through one dedicated thread. Enum values in `constants.py` were read from
`swconst.tlb` rather than transcribed from documentation, because some differ
from commonly quoted values — `swEndCondThroughAllBoth` is 9, not 8.