vcad.
Back to MCP Tools
MCP Tools

create_cad_document

Create parts from primitives, sketches, and assemblies

create_cad_document is the primary MCP tool for building 3D geometry. It accepts a structured JSON description of parts and operations and returns an IR document that can be inspected, exported, or opened in the browser.

Input Schema

{
  "parts": [...],
  "assembly": { ... },
  "format": "compact" | "json"
}
partsPartInput[]required

Array of part definitions. Each part must have a name and a geometry source (one of primitive, extrude, revolve, sweep, or loft), plus optional operations and material.

assemblyAssemblyInputoptional

Optional assembly definition containing instances and joints. When present, the tool creates part definitions, places instances, and builds the kinematic chain. Scene roots are replaced by the assembly representation.

formatstringoptional

Output format: compact (default, ~5x smaller) or json (verbose, human-readable). Compact is recommended for all MCP workflows since it saves tokens.

Part Definitions

A part is defined by its geometry source plus an optional chain of operations.

Primitive-Based Part

{
  "name": "plate",
  "primitive": {
    "type": "cube",
    "size": { "x": 100, "y": 60, "z": 5 }
  },
  "operations": [...],
  "material": "aluminum"
}
primitive.typestringrequired

Primitive type: cube, cylinder, sphere, or cone.

primitive.sizeVec3optional

Cube dimensions in mm. Cube corner sits at origin, extends to (size.x, size.y, size.z).

primitive.radiusnumberoptional

Radius for cylinder, sphere, or cone (bottom radius if radius_bottom is not specified).

primitive.heightnumberoptional

Height for cylinder and cone, along +Z axis.

primitive.segmentsnumberoptional

Facet count for curved surfaces. Default 32.

primitive.radius_bottomnumberoptional

Bottom radius for cone. Defaults to radius.

primitive.radius_topnumberoptional

Top radius for cone. 0 for a pointed cone.

Extrude-Based Part

{
  "name": "bracket",
  "extrude": {
    "sketch": {
      "plane": "xy",
      "shape": { "type": "rectangle", "width": 50, "height": 30, "centered": true }
    },
    "height": 10
  },
  "material": "steel"
}
extrude.sketchSketchInputrequired

Sketch profile to extrude. See Sketch Input below.

extrude.heightnumberoptional

Extrusion height in mm. Direction is normal to the sketch plane.

extrude.directionVec3optional

Custom extrusion direction vector. Overrides height and default normal direction.

Revolve-Based Part

{
  "name": "bowl",
  "revolve": {
    "sketch": {
      "plane": "xz",
      "shape": {
        "type": "polygon",
        "points": [{"x": 5, "y": 0}, {"x": 15, "y": 0}, {"x": 15, "y": 10}, {"x": 5, "y": 10}]
      }
    },
    "axis": "z",
    "angle_deg": 360
  }
}
revolve.axisstring | Vec3optional

Axis of revolution: "x", "y", "z", or a custom {x, y, z} vector. Default "z".

revolve.axis_offsetnumberoptional

Offset of the axis from the origin, perpendicular to the axis direction.

revolve.angle_degnumberoptional

Revolution angle in degrees. Default 360 (full revolution).

Sweep-Based Part

{
  "name": "spring",
  "sweep": {
    "sketch": {
      "shape": { "type": "circle", "radius": 2 }
    },
    "path": { "type": "helix", "radius": 10, "pitch": 5, "height": 50 }
  }
}
sweep.pathPathInputrequired

Sweep path. Either a line segment ({type: "line", start: Vec3, end: Vec3}) or a helix ({type: "helix", radius, pitch, height}).

sweep.twist_degnumberoptional

Twist angle applied over the sweep length, in degrees.

sweep.scale_startnumberoptional

Scale factor at the start of the sweep.

sweep.scale_endnumberoptional

Scale factor at the end of the sweep. Different from scale_start creates a tapered shape.

Loft-Based Part

{
  "name": "transition",
  "loft": {
    "sketches": [
      { "at": {"x": 0, "y": 0, "z": 0}, "shape": {"type": "rectangle", "width": 20, "height": 20} },
      { "at": {"x": 0, "y": 0, "z": 30}, "shape": {"type": "circle", "radius": 10} }
    ]
  }
}
loft.sketchesSketchInput[]required

Two or more sketch profiles at different positions. The loft interpolates between them.

loft.closedbooleanoptional

If true, connects the last profile back to the first (for closed-loop lofts).

Sketch Input

Sketch input defines a 2D profile on a plane.

planestringoptional

Sketch plane: "xy" (default), "xz", or "yz".

atVec3optional

Sketch plane origin. Default {x: 0, y: 0, z: 0}.

shapeobjectrequired

The sketch shape. One of rectangle, circle, or polygon.

Rectangle Shape

{ "type": "rectangle", "width": 50, "height": 30, "centered": true }
widthnumberrequired
Width in mm.
heightnumberrequired
Height in mm.
centeredbooleanoptional

If true, centered at the sketch origin. If false (default), corner at origin.

Circle Shape

{ "type": "circle", "radius": 10 }
radiusnumberrequired
Radius in mm.

Polygon Shape

{ "type": "polygon", "points": [{"x": 0, "y": 0}, {"x": 10, "y": 0}, {"x": 5, "y": 8}], "closed": true }
pointsVec2[]required
Array of 2D points defining the polygon vertices.
closedbooleanoptional

Close the polygon by connecting the last point to the first. Default true.

Operations

Operations are applied in order to the part's base geometry. Each operation modifies the result of the previous one.

Boolean Operations

{ "type": "difference", "primitive": { "type": "cylinder", "radius": 3, "height": 10 }, "at": "center" }
typestringrequired

Boolean type: "union", "difference", or "intersection".

primitivePrimitiverequired

The tool shape for the boolean operation.

atPositionSpecoptional

Position of the tool shape. See Position Specification below.

Hole

A convenience operation that creates a cylindrical difference along Z.

{ "type": "hole", "diameter": 5.5, "at": { "x": 25, "y": 15 } }
diameternumberrequired

Hole diameter in mm.

depthnumberoptional

Hole depth in mm. Omit for a through-hole (auto-sized to extend through the part).

atPositionSpecoptional

Hole center position. Default is "center".

Transforms

{ "type": "translate", "offset": { "x": 50, "y": 0, "z": 0 } }
{ "type": "rotate", "angles": { "x": 0, "y": 0, "z": 45 } }
{ "type": "scale", "factor": { "x": 2, "y": 2, "z": 1 } }

Patterns

{ "type": "linear_pattern", "direction": {"x": 1, "y": 0, "z": 0}, "count": 5, "spacing": 20 }
{ "type": "circular_pattern", "axis_origin": {"x": 0, "y": 0, "z": 0}, "axis_dir": {"x": 0, "y": 0, "z": 1}, "count": 6, "angle_deg": 360 }

Features

{ "type": "fillet", "radius": 2 }
{ "type": "chamfer", "distance": 1 }
{ "type": "shell", "thickness": 2 }
radiusnumberoptional

Fillet blend radius in mm. Default 1.

distancenumberoptional

Chamfer distance in mm. Default 1.

thicknessnumberoptional

Shell wall thickness in mm. Default 2.

Position Specification

Operations that accept an at parameter support three formats:

Absolute coordinates. An object with x, y, z fields: {"x": 25, "y": 15, "z": 0}.

Named positions. A string referencing a computed position on the base primitive's bounding box:

  • "center" -- center of the bounding box
  • "top-center" -- center of the top face (max Z)
  • "bottom-center" -- center of the bottom face (min Z)

Percentage coordinates. An object with percentage strings: {"x": "50%", "y": "50%"}. Percentages are relative to the base primitive's bounding box, where 0% is the minimum and 100% is the maximum.

Assembly

The optional assembly block defines a multi-body model with kinematic joints.

Instances

{
  "instances": [
    { "id": "base-1", "part": "Base", "position": {"x": 0, "y": 0, "z": 0} },
    { "id": "arm-1", "part": "Arm" }
  ]
}
idstringrequired
Unique instance identifier.
partstringrequired
Part name (must match a part in the parts array).
namestringoptional
Display name. Defaults to the instance ID.
positionVec3optional
Initial position in mm.
rotationVec3optional
Initial rotation as Euler angles in degrees.

Joints

{
  "joints": [
    {
      "id": "shoulder",
      "parent": "base-1",
      "child": "arm-1",
      "type": "revolute",
      "axis": "z",
      "parent_anchor": {"x": 0, "y": 0, "z": 50},
      "child_anchor": {"x": 0, "y": 0, "z": 0},
      "limits": [-90, 90],
      "state": 0
    }
  ]
}
idstringrequired
Unique joint identifier.
parentstring | nullrequired
Parent instance ID, or null for world-grounded.
childstringrequired
Child instance ID.
typestringrequired
Joint type: "fixed", "revolute", "slider", "cylindrical", "ball".
axisstring | Vec3optional
Joint axis: "x", "y", "z", or a custom vector. Default "z".
parent_anchorVec3optional
Anchor point on parent in local coordinates.
child_anchorVec3optional
Anchor point on child in local coordinates.
limits[number, number]optional
Joint limits (degrees for revolute, mm for slider).
statenumberoptional
Initial joint state. Default 0.

Ground

groundstringoptional

Instance ID of the fixed reference part. Required for forward kinematics.

Return Value

The tool returns a text response containing the IR document in the requested format. For compact format (default), the response is the compact IR text. For json format, it is a pretty-printed JSON document.

The returned document can be passed directly to inspect_cad, export_cad, or open_in_browser.

Example

{
  "parts": [
    {
      "name": "Bracket",
      "primitive": { "type": "cube", "size": {"x": 50, "y": 30, "z": 5} },
      "operations": [
        { "type": "hole", "diameter": 5.5, "at": {"x": 10, "y": 15} },
        { "type": "hole", "diameter": 5.5, "at": {"x": 40, "y": 15} },
        { "type": "fillet", "radius": 2 }
      ],
      "material": "aluminum"
    }
  ]
}

This creates a 50x30x5mm aluminum bracket with two M5 clearance holes and 2mm fillets on all edges.