---
name: fieldcad
description: Design and edit FieldCAD implicit-CAD documents (signed-distance-field modeling, Matterhorn-style blocks) through the FieldCAD MCP server — creating primitives, booleans, shells, lattices, and measuring the result.
---

# FieldCAD

FieldCAD is an implicit-modeling (signed-distance-field) CAD system. A design
is a **graph** of nodes (blocks), not a feature tree: primitives and fields
flow through booleans, shells, lattices, and mesh operations to one `output`
node. You edit documents through the FieldCAD MCP tools; every applied edit
is validated, measured, and saved into the document's history, where the user
sees it in the web editor.

## Workflow

1. `list_documents` → pick the document (or ask the user which one).
2. `read_graph` → understand what exists. Node ids are opaque and stable —
   never rename ids, only `name` labels.
3. `search_blocks` / `block_doc` → ground yourself before adding ANY node you
   haven't seen the spec for this conversation. Param names and shapes are
   not guessable; the spec is authoritative.
4. `apply_edits` with one atomic batch per coherent change. The response is an
   evaluation report: fix every error `diagnostics` reports (each has a stable
   `code`, a `location` JSON Pointer, and often a `suggestion`), then check
   `measurements` (volume, bbox_size, watertight, components) against the
   user's intent before declaring success.
5. `evaluate` re-measures without changing anything.

## Graph semantics (the parts models get wrong)

- A param value is exactly one of: a **reference** (bare string = another
  node's id, `"id.Port.Prop"` navigates record outputs), a **dimensioned
  value** `{ "value": 18, "unit": "mm" }` (`"unit": ""` = dimensionless), an
  **inline node** `{ "func": "multiply", "params": { … } }` (single-use), an
  **enum member** `{ "enum": "name" }`, free text `{ "text": "…" }`, a bool,
  a vector `[x, y, z]`, or a list of ids `["a", "b"]`.
- Booleans take their solids as a list param (e.g. `boolean_union`'s `items`;
  `boolean_subtract` has `primary` + `items`).
- Variables are ordinary `var` nodes referenced by id — there is no expression
  syntax; arithmetic is math nodes (`add`, `multiply`, …), inline or named.
- **Prefer inline subnodes** for single-use helpers (a boss region, a math
  step feeding one param) — they keep the notebook short — but nest at most
  **3 levels** deep; anything deeper (or used twice) becomes a named node.
- **Derive, don't copy**: when a value follows from another node's geometry,
  reference its record property (`"hole.StartPoint"`, `"hole.Radius"`) and
  derive offsets with math nodes (e.g. radius = inline `add` of
  `"hole.Radius"` + 1 mm) instead of re-typing the number — a copied number
  silently breaks the design when the source node is edited.
- Always leave the graph with a sensible `output` (set_output) — that is what
  the viewport shows and what exports.
- Prefer minimal edit deltas; use `replace_graph` only for from-scratch
  builds. Keep untouched nodes' ids identical so the user's review diff reads.
- **Notebook order**: the user reads sections top-to-bottom like a document.
  Place variables at the top (a Variables section, or `add_node` with
  `index: 0`), keep producers above their consumers, results last — never
  append a variable to the end.

## Common recipes

- **Hollow part**: solid → `shell` (`in`, `thickness`, direction enum).
- **Cavity**: `boolean_subtract` { primary: body, items: [cutters…] }.
- **Gyroid infill**: `gyroid` (period/thickness) → `boolean_intersect` with
  the body; union with a `shell` of the body for a skinned lattice.
- **Imported CAD**: `import_part` (asset) → `cad_body` (body index) →
  `implicit_body_from_cad_body` (tolerance) — then it composes with any
  implicit op.
- **Meshing for export**: `mesh_from_solid` (tolerance in mm) →
  `remesh_surface` / `quadrangulate_mesh` → `cad_body_from_quad_mesh` →
  `export_part`.

## Units and sanity

Everything is millimeters unless a unit says otherwise. After edits, compare
`measurements.bbox_size` with what the user asked for — a 30 mm part that
measures 300 mm means a unit slipped. `watertight: true` and
`components: 1` are the default expectation for a printable part; say so
explicitly when they don't hold.
