root-ext-cad
# root-ext-cad
CAD-engineering MCP tool server — code-CAD builds (build123d/CadQuery),
model inspection, meshing, DFM-lite validation, and mechanical
calculators. Built as the mechanical-engineering pack for
[ROOT Workspace], but it speaks plain MCP stdio and works with any MCP
host.
The workspace client stays domain-free by doctrine; **this repo is
where the CAD knowledge lives.** Tools reach both ROOT runtimes (the
brain-governed deployment and the lite Tier-0 harness) through the
client's mcp-bridge, and every call is governed — write-class tools
gate like any write; network tools park for approval.
## The charter (binding)
**Source is truth; artifacts are derived.** The pack never overwrites
a user's file in place: geometry writes land in a caller-named output
directory (default `derived/` beside the source), and every write tool
refuses an output path that collides with its input.
`tests/test_server.py::test_no_inplace_mutation_tools_exist` and the
collision-refusal tests enforce this in CI, not just in prose.
Parametric **source** (a build123d or CadQuery `.py` script) is the
model; STEP/STL/glTF/3MF are exports. `model_build` executes scripts —
it says so plainly, runs them in this pack's own venv as a
resource-capped subprocess, and is classed write, never read.
## Tools
| Tool | Class* | What it does |
|---|---|---|
| `model_inspect` | read | STEP/BREP/STL → bounding box, volume/area, mass (given density), topology counts, per-solid summary |
| `model_validate` | read | DFM-lite lint: open (non-watertight) shells, invalid B-rep, tiny edges/faces, pairwise interference & clearance — every finding carries its evidence and threshold |
| `model_build` | **write** | Run a build123d/CadQuery parametric script (sandboxed subprocess, CPU/memory/wall caps) → STEP/STL/glTF/3MF into the output dir + a build report |
| `model_mesh` | **write** | STEP/BREP → tessellated STL/glTF/3MF with linear + angular tolerance controls |
| `calc_fits` | read | ISO 286 limits & fits (hole-basis subset), clearance/interference verdicts |
| `calc_fastener` | read | Metric coarse threads: pitch, stress area, tap & clearance drills, preload/torque first-cut |
| `calc_beam` | read | Beam bending first-cut: cantilever / simply-supported, point / UDL, rect / round / tube sections |
| `calc_mass_rollup` | read | Assembly mass + 3D center of gravity from a component list, envelope check |
| `model_diff` | read | Geometric diff of two revisions: volume/area/bbox deltas, bodies unchanged/moved/added/removed by shape signature — geometry, not a feature tree, and the report says so |
| `drawing_project` | **write** | Named-view (front/top/…/iso) SVG or DXF projection: visible edges + dashed hidden layer — a silhouette for hand-off, not a dimensioned drawing |
| `text_to_cad` | **external** | Starter model from a text prompt via Zoo's ML-ephant API (+ its editable KCL source when returned); needs `ZOO_API_KEY`, refuses by name without it |
\* Classes derive fail-safe from annotations in the ROOT client:
read tools declare `readOnlyHint: true, openWorldHint: false`; write
tools declare `readOnlyHint: false, openWorldHint: false` (the
closed-world write class); network tools (Phase CAD-D: `text_to_cad`)
will declare `openWorldHint: true` and refuse by name without their
key.
## Connect it to ROOT Workspace
Settings → **Connected tools** → the connect form:
- **Name:** `cad-eng`
- **Command:** `uv run --project /path/to/root-ext-cad root-ext-cad`
(a local checkout), or once published: `uvx root-ext-cad`
Run the row's **Check** (doctor) after connecting. Keep model files
and build scripts inside granted folders so the agent can cross-read
them with `fs.*`. Builds must finish inside the bridge's call ceiling
(120 s; 90 s once promoted) — the default subprocess wall cap is 75 s.
## Development
```sh
uv venv .venv
uv pip install --python .venv/bin/python -e ".[dev]"
.venv/bin/pytest
```
Layering rule: `server.py` is wiring only; every capability lives in a
plain-Python module (`inspection.py`, `meshing.py`, `validate.py`,
`buildrun.py`, `calc.py`, `geometry.py`) with logic separated from
I/O so the rules stay unit-testable on synthetic shapes — no fixture
model files required.
## Roadmap
- Later, each behind its own ADR: FreeCAD GUI-bridge companion,
Onshape connector, KCL as a second source dialect, FEA hand-off
recipes, PMI/GD&T presence reporting
TDQS
Scored across 11 tools
Each tool has a clearly distinct purpose: model_inspect summarizes, model_validate checks manufacturability, model_build executes scripts, model_mesh tessellates, model_diff compares, drawing_project projects to 2D, text_to_cad generates from text, and the calc_* tools cover specific engineering calculations with no overlap.
Tool names consistently use a verb_noun pattern with model_ and calc_ prefixes. Minor deviations: drawing_project uses noun_verb, and text_to_cad uses a different form, but they are still clear and fit the overall scheme.
11 tools is well-scoped for a CAD server covering both model operations and engineering calculations. Each tool serves a specific need without being overwhelming or too sparse.
Covers core CAD workflows: inspect, validate, build, mesh, diff, project, and text generation. Calculation tools cover common mechanical engineering needs. Minor gaps like direct export to common formats or more advanced analysis, but overall complete for its stated purpose.