SolidWorks as Code lets you record an interactive MCP session and export it as a clean, runnable Python script. The round-trip is:
MCP tool calls → SQLite log → soc_exporter → script.py
↕ rewind / pickup
Every call you make through the MCP adapter is logged. When you're done, export the log as a self-contained script. You can rewind to any checkpoint and replay, or pick up manual changes made directly in SolidWorks.
from solidworks_mcp.adapters.circuit_breaker import CircuitBreakerAdapter
adapter = CircuitBreakerAdapter(...)
adapter.soc_session_id = "my-bracket" # any unique string
# adapter.soc_db_path = Path("custom.db") # optional overrideEvery adapter call from this point is written to SQLite as a ToolCallRecord.
from solidworks_mcp.agents.soc_exporter import export_session
export_session("my-bracket", "my_bracket.py")Or from the command line:
python -m solidworks_mcp.agents.soc_exporter my-bracket my_bracket.pyThe exported script looks exactly like the hand-written reference artifact build_u_bracket_artifact.py. You can open it, read it, and run it to reproduce the part from scratch.
A checkpoint marks a save point: the model file path, the record range that produced it, and a label you choose.
await adapter.soc_create_checkpoint(
"base-extrude",
"C:/parts/bracket_cp1.sldprt",
)This writes a SoCCheckpoint row to SQLite and inserts a parseable comment block into the exported script:
# -- checkpoint ----------------------------------------------------
# label: base-extrude
# file: C:/parts/bracket_cp1.sldprt
# records: 1-6
# ----------------------------------------------------from solidworks_mcp.agents.soc_rewind import list_checkpoints
for cp in list_checkpoints("my-bracket"):
print(cp["label"], cp["file_path"])Rewind opens the .sldprt saved at a checkpoint and optionally truncates the script to that boundary.
from solidworks_mcp.agents.soc_rewind import rewind_to_checkpoint
script = open("my_bracket.py").read()
truncated = await rewind_to_checkpoint(
adapter,
session_id="my-bracket",
label="base-extrude",
script_text=script,
)
# truncated is the script up to (and including) the checkpoint block.
# Continue building by appending new tool calls.CLI (prints checkpoint info):
python -m solidworks_mcp.agents.soc_rewind my-bracket base-extrudeIf you make changes directly in SolidWorks after the last checkpoint, pickup_changes diffs the current feature tree against the last snapshot and emits delta lines.
from solidworks_mcp.agents.soc_pickup import pickup_changes
delta_lines = await pickup_changes(
adapter,
session_id="my-bracket",
checkpoint_label="post-manual-edit",
output_path="my_bracket.py", # appended before the finally block
)Delta output example:
# ── pickup ──────────────────────────────────────────────
# 1 new feature(s) detected since last checkpoint
# Fill in '?' placeholders before running.
# ──────────────────────────────────────────────────────────
# [pickup] 'Fillet1' (fillet)
require(
await adapter.add_fillet(radius=?, edge_names=[]), # TODO: radius + edges
"add_fillet Fillet1",
)The exporter has two layers:
| Layer | What it does |
|---|---|
| Specialized emitters | Tracks entity IDs returned by add_line, add_circle, etc. and emits them as named Python variables (line_1, circle_1) so constraints/dimensions can reference them by name. |
| Generic fallback | Every other logged write call is emitted as require(await adapter.<tool_name>(**kwargs), "<tool_name>") directly from the logged input_json — no manual wiring needed. |
Read-only queries (get_model_info, list_features, get_dimension, etc.) are logged to SQLite for audit but skipped in the replay script since they don't change model state.
This section shows the full loop: how you drive MCP interactively, place checkpoints, export the generated script, and rewind when something goes wrong. The Yoke_male part from the U-joint assembly serves as the example.
Tell Claude Code to tag all calls with a session ID before doing anything else:
Use session_id "ujoint-yoke-male" for this session.
Build Yoke_male.sldprt for the U-joint assembly from these dimensions only:
Profile : U-shape on Front plane, 80 mm wide × 100 mm tall
Body zone Y = 0 → 40 mm (40 mm body, full width)
Arm zone Y = 40 → 100 mm (60 mm arms, 15 mm wide each)
Arm gap X = -25 → +25 (50 mm clear span)
Depth : 38 mm symmetric extrude (±19 mm from Front plane)
Pin bores : ∅8 mm in each arm, centred at X = ±32.5 mm, Y = 70 mm
Flange pad : ∅60 mm × 3 mm, extruded downward from the body base
Flange holes : 4 × ∅4.2 mm on ∅50 mm bolt circle (M4 clearance)
Arm fillets : 1 mm on arm top corners
After each major phase, create a checkpoint to save a restore point.
Do NOT open the reference file (Yoke_male.sldprt) yet — compare at the end.
Behind the scenes, Claude Code sets adapter.soc_session_id = "ujoint-yoke-male" and every subsequent MCP call is written as a ToolCallRecord to .solidworks_mcp/agent_memory.sqlite3.
Claude calls the MCP tools to draw the 8-line U-profile and extrude it. You watch the part build live in SolidWorks. When it looks right, prompt:
Looks good — the U-profile is extruded cleanly.
Create a checkpoint labelled "body-extrude" and save the file as
docs/getting-started/tutorial-parts/yoke_male_cp1.sldprt
Claude calls:
await adapter.save_file("...yoke_male_cp1.sldprt")
await adapter.soc_create_checkpoint("body-extrude", "...yoke_male_cp1.sldprt")SQLite now has a SoCCheckpoint row pointing to that file and spanning records 1–12.
Export mid-session to check the script so far:
.venv\Scripts\python.exe -m solidworks_mcp.agents.soc_exporter `
ujoint-yoke-male yoke_male_draft.pyThe output script looks like this — the exporter generated it entirely from the SQLite log, no hand-writing:
require(await adapter.create_part(name='yoke_male'), "create_part")
require(await adapter.create_sketch('Front'), "create_sketch")
line_1 = require(await adapter.add_line(-40.0, 0.0, -40.0, 100.0), "add_line")
line_2 = require(await adapter.add_line(-40.0, 100.0, -25.0, 100.0), "add_line")
line_3 = require(await adapter.add_line(-25.0, 100.0, -25.0, 40.0), "add_line")
line_4 = require(await adapter.add_line(-25.0, 40.0, 25.0, 40.0), "add_line")
line_5 = require(await adapter.add_line(25.0, 40.0, 25.0, 100.0), "add_line")
line_6 = require(await adapter.add_line(25.0, 100.0, 40.0, 100.0), "add_line")
line_7 = require(await adapter.add_line(40.0, 100.0, 40.0, 0.0), "add_line")
line_8 = require(await adapter.add_line(40.0, 0.0, -40.0, 0.0), "add_line")
require(await adapter.exit_sketch(), "exit_sketch")
require(
await adapter.create_extrusion(
ExtrusionParameters(
depth=38.0,
both_directions=True,
)
),
"create_extrusion",
)
require(await adapter.save_file('...yoke_male_cp1.sldprt'), "save_file")
# -- checkpoint ----------------------------------------------------
# label: body-extrude
# file: yoke_male_cp1.sldprt
# records: 1-12
# ----------------------------------------------------Notice what's happening:
add_linecalls are specialized: each gets its own variable (line_1,line_2…) because later constraint calls would need to reference them by name.create_extrusionfalls through to the specialized emitter which formatsExtrusionParameterscleanly.add_fillet(added later) falls through toemit_generic— no manual wiring at all.list_featuresorget_model_infocalls you made to check the part are silently skipped — they're logged for audit but they don't belong in a replay script.
Suppose after Phase 2 (bore cut) you realise the bore was ∅10 mm instead of ∅8 mm. The bore checkpoint is bore-cut. Tell Claude:
The bore diameter is wrong — it came out ∅10 mm, should be ∅8 mm (radius 4 mm).
Rewind to the "body-extrude" checkpoint and redo the bore.
Claude runs:
from solidworks_mcp.agents.soc_rewind import rewind_to_checkpoint
script = open("yoke_male_draft.py").read()
truncated = await rewind_to_checkpoint(
adapter,
session_id="ujoint-yoke-male",
label="body-extrude",
script_text=script,
)What happens:
yoke_male_cp1.sldprt(the body-extrude checkpoint file) is opened in SolidWorks.truncatedis the script with everything afterbody-extruderemoved — a clean slate.- Claude then redo the bore sketch with
radius=4.0and creates a newbore-cutcheckpoint.
From the command line (prints checkpoint info, no SolidWorks needed):
python -m solidworks_mcp.agents.soc_rewind ujoint-yoke-male body-extrude
# Checkpoint: body-extrude
# file: .../yoke_male_cp1.sldprt
# records: 1-12
# created: 2026-05-15T14:22:03+00:00
#
# To rewind: open '.../yoke_male_cp1.sldprt' in SolidWorksContinue prompting Claude:
Good. Now add the flange pad: ∅60 mm circle on the Front plane at Y=0,
extruded 3 mm downward. Then 4 × ∅4.2 mm holes on the Top plane at
(±25, 0) and (0, ±25). Finally, 1 mm fillet on the arm top corners.
Create a checkpoint "final" and save as yoke_male_final.sldprt.
Claude calls create_extrusion, create_cut_extrude, add_fillet, save_file, soc_create_checkpoint in sequence. Each call is logged.
Export the finished session:
.venv\Scripts\python.exe -m solidworks_mcp.agents.soc_exporter `
ujoint-yoke-male docs/getting-started/tutorial-parts/yoke_male_generated.pyThe complete generated script is the source of truth for this part. Run it on a clean SolidWorks session to confirm it's fully reproducible:
.venv\Scripts\python.exe docs/getting-started/tutorial-parts/yoke_male_generated.pyIf it completes without error and the exported PNGs match the reference:
C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Yoke_male.sldprt
...the part is done. Commit the generated script as the build artifact.
The hand-authored reference version lives at tutorial-parts/build_yoke_male_runbook.py and shows the identical structure.
| Trigger | Checkpoint label convention |
|---|---|
| Main body mass looks right in SolidWorks | body-extrude |
| Each major cut / hole feature complete | bore-cut, flange-holes |
| Ready to start a risky feature (sweep, loft, shell) | pre-<feature> |
| Part visually verified against reference image | verified |
| Assembled mate added and confirmed | mate-<part> |
Place checkpoints before you're sure things are right — the cost is a saved file and one SQLite row; the benefit is a clean rewind target if the next step breaks something.
The script tutorial-parts/build_u_bracket_runbook.py builds a cable-routing U-bracket entirely from the design spec below — no reference model used during construction.
Spec (from the original Prefab UI runbook):
| Parameter | Value |
|---|---|
| Outer envelope | 78 mm (X) × 52 mm (Y) × 36 mm (Z) |
| Inner clearance | 60 mm × 34 mm (9 mm walls on all sides) |
| Corner fillets | 9 mm radius on outer vertical edges |
| Mounting holes | M4 pilot 4.2 mm dia, X = ±24 mm on top flange |
| Cable slot | 16 mm × 8 mm, centred on top flange |
| Material / print | PETG, 0.6 mm nozzle, 0.2 mm layers |
Run it (requires SolidWorks + MCP server running):
.\.venv\Scripts\python.exe docs/getting-started/tutorial-parts/build_u_bracket_runbook.pyVerify by comparing the exported PNGs against bracket.sldprt:
C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\bracket.sldprt
- Two concentric rectangles in Sketch1 → SolidWorks extrudes the annular region automatically, producing the 9 mm walls.
create_extrusionemits theExtrusionParametersblock exactly as the exporter would generate it.add_filletfalls through toemit_generic— no specialized emitter needed.- Two checkpoints with parseable comment blocks, readable by
soc_rewind.truncate_script_at. - Sketch 2 adds mounting features on the top flange; face selection note shows where a production script would reference an actual model face.
| Module | Key function |
|---|---|
soc_exporter |
export_session(session_id, output_path) |
soc_exporter |
generate_script(records, checkpoints=...) |
soc_rewind |
rewind_to_checkpoint(adapter, session_id, label) |
soc_rewind |
truncate_script_at(script_text, label) |
soc_pickup |
pickup_changes(adapter, session_id, checkpoint_label=...) |
history_db |
list_soc_checkpoints(session_id) |
history_db |
get_soc_checkpoint(session_id, label) |
- Issue #21 — Assembly-aware
list_features: traverse sub-components in.SLDASMand list features per part. - Issue #22 — Context and glossary injection engine: TAG-style domain context for MCP tool calls (inspired by this article).
- Phase 3 — Lightweight two-panel UI: Monaco script editor (left) + Three.js GLB viewer (right) with checkpoint timeline.