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
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
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
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
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
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
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"] } } }
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
openscadandfreecadcmdprograms onPATHto 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)