Skip to content

Tutorial Tracks

Build SolidWorks parts from scratch using the MCP server and Python scripting.

Track A: Script-Based Part Generation

Best for automated, reproducible builds with direct Python scripting.

Example: Build the sample U-bracket from measured sketch coordinates:

.\.venv\Scripts\python.exe docs/getting-started/tutorial-parts/build_u_bracket_artifact.py

This generates tutorial-parts/u_bracket_from_prompt.SLDPRT and an isometric PNG alongside the SolidWorks answer-key render for visual comparison.

Advantages: - Fast, deterministic output - Repeatable across runs - Full control over feature sequence - Easy to version-control and share

Best for: CI/CD pipelines, automated testing, generating baseline artifacts


Track B: SolidWorks-as-Code (SoC) Export

Best for capturing a live MCP session as a replayable Python script.

After building a part interactively through MCP tool calls, export the session log as a clean script:

from solidworks_mcp.agents.soc_exporter import export_session

export_session(session_id="...", output_path="my_part.py")

The exported script mirrors the structure of build_u_bracket_artifact.py — adapter calls, sketch sequences, extrusion parameters — ready to replay or version-control.

Best for: Capturing design intent, sharing reproducible builds, checkpoint rewind


Choosing Your Track

Goal Track Reason
Build a known part A (Script) Fast, repeatable, CI-ready
Capture a live session B (SoC Export) Turn interactive work into a script
Bulk generation A (Script) Automation, minimal overhead

Available Tutorials

Reference Artifacts

U-Bracket Build Script — Builds the SolidWorks 2026 sample bracket from measured sketch coordinates; produces .sldprt and isometric PNG

⬇ Download Script

View full script — build_u_bracket_artifact.py
from __future__ import annotations

import asyncio
from pathlib import Path
from typing import Any

from solidworks_mcp.adapters import create_adapter
from solidworks_mcp.adapters.base import ExtrusionParameters
from solidworks_mcp.config import load_config

ROOT = Path(__file__).resolve().parents[3]
ARTIFACT_DIR = ROOT / "docs" / "getting-started" / "tutorial-parts"
OUTPUT_PART = ARTIFACT_DIR / "u_bracket_from_prompt.sldprt"
OUTPUT_IMAGE = ARTIFACT_DIR / "u_bracket_from_prompt_isometric.png"
ANSWER_KEY = Path(
    r"C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\bracket.sldprt"
)
ANSWER_KEY_IMAGE = ARTIFACT_DIR / "answer_key_bracket_isometric.png"


def require(result: Any, label: str) -> Any:
    if not result.is_success:
        raise RuntimeError(f"{label} failed: {result.error}")
    return result


def unwrap_for_method(adapter: Any, method_name: str) -> Any | None:
    current: Any | None = adapter
    visited: set[int] = set()
    while current is not None and id(current) not in visited:
        visited.add(id(current))
        if hasattr(current, method_name):
            return current
        current = getattr(current, "adapter", None)
    return None


def create_cut_extrude_direct(adapter: Any) -> None:
    raw_adapter = unwrap_for_method(adapter, "currentModel")
    if raw_adapter is None or raw_adapter.currentModel is None:
        raise RuntimeError("Could not access raw adapter currentModel for cut fallback")

    model = raw_adapter.currentModel
    feature_manager = model.FeatureManager

    # Blind cut 10 mm from Sketch2 (not through-all).
    feature = feature_manager.FeatureCut3(
        True,
        False,
        False,
        0,
        0,
        0.01,
        0.0,
        False,
        False,
        False,
        False,
        0.0,
        0.0,
        False,
        False,
        False,
        False,
        False,
        False,
        True,
        False,
        False,
        False,
        0,
        0.0,
        False,
    )
    if not feature:
        # Some installs flip the sketch normal on face/offset-plane sketches.
        feature = feature_manager.FeatureCut3(
            True,
            False,
            True,
            0,
            0,
            0.01,
            0.0,
            False,
            False,
            False,
            False,
            0.0,
            0.0,
            False,
            False,
            False,
            False,
            False,
            False,
            True,
            False,
            False,
            False,
            0,
            0.0,
            False,
        )
    if not feature:
        raise RuntimeError("Direct FeatureCut3 fallback returned no feature")


def create_sketch_on_top_planar_face(adapter: Any, sketch_name: str) -> None:
    """Start Sketch2 on a deterministic plane aligned to the top flange face.

    On some COM bindings face-picking is unreliable, so this creates an offset
    plane from Top Plane at the measured top-face elevation (88.90 mm), then
    starts the sketch on that plane.
    """
    raw_adapter = unwrap_for_method(adapter, "currentModel")
    if raw_adapter is None or raw_adapter.currentModel is None:
        raise RuntimeError("Could not access raw adapter currentModel for face sketch")

    model = raw_adapter.currentModel

    top_plane = model.FeatureByName("Top Plane") or model.FeatureByName("Planta")
    if not top_plane:
        raise RuntimeError("Failed to find Top Plane for Sketch2 offset plane")

    model.ClearSelection2(True)
    if not top_plane.Select2(False, 0):
        raise RuntimeError("Failed to select Top Plane for Sketch2 offset plane")

    # swRefPlaneReferenceConstraint_Distance = 8
    offset_feature = model.FeatureManager.InsertRefPlane(
        8, 88.9 / 1000.0, 0, 0.0, 0, 0.0
    )
    if not offset_feature:
        raise RuntimeError("Failed to create top-face offset plane for Sketch2")

    model.ClearSelection2(True)
    if not offset_feature.Select2(False, 0):
        raise RuntimeError("Failed to select Sketch2 offset plane")

    sketch_manager = model.SketchManager
    try:
        sketch = sketch_manager.InsertSketch(True)
    except Exception:
        sketch = sketch_manager.InsertSketch()

    # Some COM variants return bool for InsertSketch; add_* operations only
    # require currentSketchManager, so keep a nullable currentSketch here.
    if isinstance(sketch, bool):
        sketch = None

    if hasattr(raw_adapter, "_reset_sketch_entity_registry"):
        raw_adapter._reset_sketch_entity_registry()

    raw_adapter.currentSketchManager = sketch_manager
    raw_adapter.currentSketch = sketch
    raw_adapter._sketch_count += 1
    raw_adapter._last_sketch_name = sketch_name


def close_all_docs_and_restore(adapter: Any, model_path: Path) -> None:
    """Close open docs and restore the saved tutorial part as active."""
    raw_adapter = unwrap_for_method(adapter, "swApp")
    if raw_adapter is None or raw_adapter.swApp is None:
        raise RuntimeError("Could not access raw adapter swApp for document cleanup")

    app = raw_adapter.swApp
    # Prevent stale PartXXX windows from remaining open between runs.
    try:
        app.CloseAllDocuments(True)
    except Exception:
        # Fallback: best effort close-all by title/path for older COM variants.
        app.CloseDoc(str(model_path))


async def ensure_saved_part_active(adapter: Any, model_path: Path, label: str) -> None:
    """Open the saved part and keep it as adapter/current active model."""
    require(await adapter.open_model(str(model_path)), label)


async def build_part() -> None:
    config = load_config()
    adapter = await create_adapter(config)
    await adapter.connect()
    try:
        require(await adapter.create_part(name="u_bracket_from_prompt"), "create_part")

        # Rebuild the SolidWorks sample bracket from measured sketch coordinates.
        # Feature tree target: Sketch1 -> Base-Extrude-Thin -> Sketch2 -> Cut-Extrude1.
        # Units are mm, derived from the sample model currently shipped with SW 2026.

        require(await adapter.create_sketch("Front"), "create_sketch Sketch1")

        require(await adapter.add_line(0.0, 0.0, 0.0, 82.55), "right web")
        require(await adapter.add_line(0.0, 82.55, -57.15, 82.55), "top flange")
        require(await adapter.add_line(-77.216, 27.494, -44.45, 0.0), "angled tab")
        require(await adapter.add_line(-44.45, 0.0, 0.0, 0.0), "bottom rail")
        require(await adapter.exit_sketch(), "exit_sketch Sketch1")

        # Base-Extrude-Thin: mid-plane 38.1 mm depth, 6.35 mm thin-wall.
        require(
            await adapter.create_extrusion(
                ExtrusionParameters(
                    depth=38.1,
                    thin_feature=True,
                    thin_thickness=6.35,
                    both_directions=True,
                    auto_fillet_corners=True,
                    fillet_corners_radius=3.175,
                )
            ),
            "create Base-Extrude-Thin",
        )

        # Sketch2: place the hole on the top flange face (highlighted sample face).
        # Offset is 12.70 mm from the left edge, diameter is 12.70 mm.
        create_sketch_on_top_planar_face(adapter, "Sketch2")
        require(
            await adapter.add_centerline(0.0, 0.0, -57.15, 0.0),
            "Sketch2 flange reference centerline",
        )
        require(await adapter.add_circle(-44.45, 0.0, 6.35), "sample bracket hole")
        definition_check = require(
            await adapter.check_sketch_fully_defined("Sketch2"),
            "check_sketch_fully_defined Sketch2",
        )
        if isinstance(definition_check.data, dict):
            is_defined = definition_check.data.get("is_fully_defined")
            if is_defined is False:
                print(
                    f"WARNING: Sketch2 may not be fully defined: {definition_check.data}"
                )
        require(await adapter.exit_sketch(), "exit_sketch Sketch2")

        create_cut_extrude_direct(adapter)

        require(await adapter.save_file(str(OUTPUT_PART)), "save_file tutorial part")
        await ensure_saved_part_active(
            adapter, OUTPUT_PART, "activate tutorial part before screenshot"
        )
        require(
            await adapter.export_image(
                {
                    "file_path": str(OUTPUT_IMAGE),
                    "format_type": "png",
                    "width": 1600,
                    "height": 1000,
                    "view_orientation": "isometric",
                }
            ),
            "export_image tutorial part",
        )

        if ANSWER_KEY.exists():
            require(await adapter.open_model(str(ANSWER_KEY)), "open answer key")
            require(
                await adapter.export_image(
                    {
                        "file_path": str(ANSWER_KEY_IMAGE),
                        "format_type": "png",
                        "width": 1600,
                        "height": 1000,
                        "view_orientation": "isometric",
                    }
                ),
                "export_image answer key",
            )

        # Keep only the rebuilt bracket active at end of run.
        # close_all_docs_and_restore(adapter, OUTPUT_PART)
        await ensure_saved_part_active(adapter, OUTPUT_PART, "restore tutorial part")
    finally:
        await adapter.disconnect()


if __name__ == "__main__":
    ARTIFACT_DIR.mkdir(parents=True, exist_ok=True)
    asyncio.run(build_part())
    print(OUTPUT_PART)
    print(OUTPUT_IMAGE)
    print(ANSWER_KEY_IMAGE)

Guided Prompt Packs

U-Joint Rebuild Prompts — Pre-written prompts for rebuilding the U-joint if you already have reference samples

⬇ Download Prompts

View full prompt pack — u_joint_rebuild_prompt.md

U-Joint Rebuild Prompts

Note: These prompts are for when you have access to the reference SolidWorks sample models and want to match them exactly. For learning and from-scratch builds, start with the U-Joint Assembly Tutorial instead.

Reference models location:

C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\

Reference Model Analysis

Before using these prompts, inspect the reference assembly to understand the geometry:

  • bracket.sldprt — Mounting base
  • Yoke_male.sldprt — Primary yoke arm
  • Yoke_female.sldprt — Secondary yoke arm
  • Spider.sldprt — Cross hub connecting yokes
  • Pin.sldprt — Shaft pin (qty 4 in assembly)
  • Crank_shaft.sldprt — Drive shaft
  • Crank_arm.sldprt — Actuation lever
  • Crank_knob.sldprt — Grip handle
  • UJoint.SLDASM — Complete assembly

Prompt 1: Bracket (Exact Parity)

Use this prompt if you want to match the reference bracket exactly and keep the same feature-tree shape.

Create Bracket_v1.SLDPRT from scratch to match the reference model exactly.

Use mm units and do not add extra features.

Required feature tree:
1. Sketch1
2. Base-Extrude-Thin
3. Sketch2
4. Cut-Extrude1

Build steps (exact dimensions):
1. On Front Plane, create Sketch1 using these connected line segments:
   - (0.00, 0.00) to (0.00, 82.55)
   - (0.00, 82.55) to (-57.15, 82.55)
   - (-57.15, 82.55) to (-77.216, 27.494)
   - (-77.216, 27.494) to (-44.45, 0.00)

   Add dimensions to ALL lines, ensure all sketches are fully defined before moving on. 
   Ensure the first and last points are NOT connected, it's an open u-bracket design.

2. Create Base-Extrude-Thin:
   - Mid-plane depth: 38.10
   - Thin wall thickness: 6.35
   - Auto-fillet corners ON
   - Corner radius: 3.175

3. Create Sketch2 on the top planar face (offset plane from Top Plane at 88.90 if needed).

4. In Sketch2:
   - Add centerline from (0.00, 0.00) to (-57.15, 0.00)
   - Add circle centered at (-44.45, 0.00) with diameter 12.70

5. Create Cut-Extrude1:
   - Blind cut depth: 10.00

Validation requirements:
- Report final feature tree names in order.
- Export isometric PNG as bracket_isometric.png.
- Compare against reference bracket isometric and report mismatch status.

Save the part as Bracket_v1.SLDPRT.

Verification snapshot from this run:

Generated bracket vs answer key

Prompt 2: All Yoke Parts (Exact Parity)

Create Yoke_male.SLDPRT and Yoke_female.SLDPRT from scratch to match the reference models exactly.

Reference models:
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Yoke_male.sldprt
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Yoke_female.sldprt

Steps:
1. Inspect the reference yoke parts and extract geometry, dimensions, and feature sequence
2. Build Yoke_male.SLDPRT with exact feature tree and dimensions
3. Build Yoke_female.SLDPRT (may be identical or slightly different)
4. Replicate appearance and material properties
5. Validate: Report feature tree for each yoke and confirm they match reference models

Export isometric PNG for each: Yoke_male_isometric.png and Yoke_female_isometric.png

Prompt 3: Spider and Pin

Create Spider.SLDPRT and Pin.SLDPRT from scratch to match the reference models exactly.

Reference models:
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Spider.sldprt
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Pin.sldprt

Steps:
1. Inspect reference parts and extract exact dimensions and feature sequences
2. Build Spider.SLDPRT: cross-shaped hub with four radial bores for pins
3. Build Pin.SLDPRT: cylindrical shaft with head flange
4. Match all critical dimensions and tolerances
5. Validate: Report feature tree for each part

Export isometric PNG for each: Spider_isometric.png and Pin_isometric.png

Prompt 4: Crank Parts (Shaft, Arm, Knob)

Create Crank_shaft.SLDPRT, Crank_arm.SLDPRT, and Crank_knob.SLDPRT from scratch to match reference models exactly.

Reference models:
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Crank_shaft.sldprt
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Crank_arm.sldprt
- C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\Crank_knob.sldprt

Steps:
1. Inspect all three crank parts and extract geometry
2. Build Crank_shaft.SLDPRT with drive flange and mounting holes
3. Build Crank_arm.SLDPRT with connection bore and grip section
4. Build Crank_knob.SLDPRT with sphere body and connection post
5. Match all critical dimensions
6. Validate: Report feature tree for each part

Export isometric PNG: Crank_shaft_isometric.png, Crank_arm_isometric.png, Crank_knob_isometric.png

Prompt 5: Assembly Build (Exact Parity)

Create UJoint.SLDASM from scratch to match the reference assembly exactly.

Reference assembly: C:\Users\Public\Documents\SOLIDWORKS\SOLIDWORKS 2026\samples\learn\U-Joint\UJoint.SLDASM

Steps:
1. Inspect reference assembly: component tree, mate list, DOF constraints
2. Insert all 8 parts (or required qty) with exact mate sequence
3. Replicate every mate (coincident, concentric, distance, angle, etc.)
4. Validate final assembly:
   - All parts present in correct locations
   - All mates fully defined (no under-constraint)
   - No over-constraint
   - No interference between parts
   - Mechanism articulates smoothly (if applicable)
5. Report:
   - Total mate count and types
   - Interference analysis
   - Motion summary (free DOF, constrained DOF)

Export isometric PNG of final assembly.

Prompt 6: Final QA and Parity Check

Perform final parity check between your generated parts/assembly and the reference UJoint.SLDASM.

Checklist:
- [ ] All 8 parts exist and are correctly named
- [ ] Each part feature tree matches reference model
- [ ] Assembly has all required mates
- [ ] Assembly is fully defined
- [ ] No interference detected
- [ ] Crank shaft and driven components articulate correctly
- [ ] All dimensions within ±0.5% of reference models
- [ ] Material properties match (if specified)
- [ ] Appearance/color matches reference (if specified)

For any mismatches:
- Identify which part or mate differs
- Report the specific deviation
- Provide corrective action (re-build part, adjust mate, etc.)
- Re-validate after correction

Generate final pass/fail report with images (isometric view from 3 angles).

When to Use These Prompts

Use these prompts if:

  • You want to match the exact SolidWorks reference sample
  • You're validating MCP tool accuracy against known geometry
  • You need a precise baseline for comparative testing

Use the U-Joint Assembly Tutorial if:

  • You're learning MCP and the Prefab UI workflow
  • You want to build from scratch without reference constraints
  • You want to modify dimensions for your application
  • You're designing a custom U-joint variant


Getting Started

Run the reference artifact to verify your MCP setup is working:

.\.venv\Scripts\python.exe docs/getting-started/tutorial-parts/build_u_bracket_artifact.py

A successful run produces tutorial-parts/u_bracket_from_prompt.SLDPRT and two PNG images.