DEV Community

Cover image for "Make the hole 2 mm bigger" is now one command for an STL you converted to CAD
Emir Mrkaljević
Emir Mrkaljević

Posted on

"Make the hole 2 mm bigger" is now one command for an STL you converted to CAD

When I started mesh2cad, the sentence I kept in my head was "make the hole 2 mm bigger". You have an STL of a bracket, the hole is a little too tight for your bolt, and the original CAD file is gone. Editing triangles is miserable, so mesh2cad fits the mesh and writes a CadQuery, OpenSCAD or FreeCAD script with named numbers at the top.

That got you a file where hole_1_d = 10.0 was sitting right there. You still had to open it, find the line, change it, run the script and hope the result was sane. 0.17.0 closes that loop with two commands: params and edit.

pip install -U "mesh2cad[cadquery]"
mesh2cad convert bracket.stl --cadquery bracket.py
mesh2cad params bracket.py
mesh2cad edit bracket.py --set hole_1_d=+2 --output-script bracket_12.py -o bracket_12.step
Enter fullscreen mode Exit fullscreen mode

What you can change

The demo part is a 50 x 30 x 6 mm plate with rounded corners, a 10 mm hole in the middle and two 5.5 mm holes for M5 bolts. After convert, params prints this (real output):

name      value  kind      unit  note
base_x    50.0   length    mm    base length (X)
base_y    30.0   length    mm    base width (Y)
base_t    6.0    length    mm    base thickness (Z)
base_cx   0.0    position  mm
base_cy   0.0    position  mm
base_z0   -3.0   position  mm    bottom face height
fillet_r  3.0    radius    mm    vertical corner radius
hole_1_d  10.0   diameter  mm    diameter
hole_1_x  0.0    position  mm
hole_1_y  0.0    position  mm
hole_2_d  5.5    diameter  mm    diameter
hole_2_x  -15.0  position  mm
hole_2_y  0.0    position  mm
hole_3_d  5.5    diameter  mm    diameter
hole_3_x  15.0   position  mm
hole_3_y  0.0    position  mm
Enter fullscreen mode Exit fullscreen mode

It works the same on .py, .scad and .FCMacro files, because all three backends use the same names.

Making the hole 2 mm bigger

A value with a leading + or - is a delta, a plain number is an absolute value:

$ mesh2cad edit bracket.py --set hole_1_d=+2 --output-script bracket_12.py -o bracket_12.step
hole_1_d: 10.0 -> 12.0 (diameter, mm)
volume: 8197.31 -> 7989.96 mm^3 (delta -207.35)
bbox min: [-25.000, -15.000, -3.000] -> [-25.000, -15.000, -3.000]
bbox max: [25.000, 15.000, 3.000] -> [25.000, 15.000, 3.000]
valid solid: yes
wrote script bracket_12.py
wrote bracket_12.step
Enter fullscreen mode Exit fullscreen mode

The volume delta is a quick sanity check you can do by hand: a ring between 10 mm and 12 mm through 6 mm of plate is pi x (36 - 25) x 6 = 207.35 mm^3. The bounding box did not move, which is what you expect when only a hole changes.

The script diff is exactly one line:

< hole_1_d = 10.0  # diameter
---
> hole_1_d = 12.0  # diameter
Enter fullscreen mode Exit fullscreen mode

edit replaces the number and leaves every other byte alone, so the file stays readable and you can keep editing it by hand. You can pass several --set flags at once, for example opening both bolt holes for M8 clearance:

$ mesh2cad edit bracket.py --set hole_2_d=+4 --set hole_3_d=+4 -o b2.step
hole_2_d: 5.5 -> 9.5 (diameter, mm)
hole_3_d: 5.5 -> 9.5 (diameter, mm)
volume: 8197.31 -> 7631.82 mm^3 (delta -565.49)
...
valid solid: yes
script unchanged on disk
wrote b2.step
Enter fullscreen mode Exit fullscreen mode

Without --in-place or --output-script, the script on disk is not touched and you only get the new solid.

Edits that cannot work are refused

I cared more about this part than about the happy path. A 40 mm hole in a 30 mm wide plate is not a part:

$ mesh2cad edit bracket.py --set hole_1_d=40 -o bad.step
hole_1_d=40.0 does not fit: the hole is larger than the wall it sits in (30.0 mm on the shorter side)
$ echo $?
2
Enter fullscreen mode Exit fullscreen mode

Nothing is written. The same goes for a counterbore that no longer clears its through-hole, a fillet that eats the short side of the base, a draft that closes a boss, an unknown parameter name (the error lists the names that exist), or a render that is empty or not one valid solid.

For agents: list_params and edit_params

The MCP server got the same two tools. list_params(script_path) returns the table above as data, and edit_params(script_path, changes, output_path?) takes something like {"hole_1_d": "+2"} and returns old and new values, validity, the volume and bounding-box delta, and warnings. So in Claude Desktop or Cursor you can literally say "make the hole 2 mm bigger" about an STL and the agent has a safe, checked way to do it instead of rewriting the script itself.

{ "mcpServers": { "mesh2cad": { "command": "mesh2cad", "args": ["mcp"] } } }
Enter fullscreen mode Exit fullscreen mode

Limits, plainly

  • It only edits scripts mesh2cad generated. A hand-written CadQuery file is refused.
  • The fit-checks are the obvious ones (does the hole fit in that face), not a constraint solver.
  • Outline and cutout point lists are listed but not edited as one number. Moving a corner of an outline is still a text edit.
  • Simple parts give short, readable parameter lists. Complex ones do not: the Prusa MK3S Y belt holder converts to a valid script, but with 282 parameters, most of them small cut positions and lengths. You can edit them, but nobody would call that list friendly yet.
  • OpenSCAD and FreeCAD need the openscad and freecadcmd programs on PATH to render. Without them the script is still rewritten and the command says the solid was not rendered.
  • It is not a PartDesign body or a constrained sketch. The number changes, and the same script runs again.

If you want to try it without installing anything, the gallery on Hugging Face has precomputed Prusa parts with STEP, CadQuery and OpenSCAD downloads. Issues with STLs that do not convert are the most useful thing you can send me: github.com/emirmrkaljevic/mesh2cad.

Top comments (0)