Skip to main content
Glama

Add Surface

add_surface

Use this when you need an organic, freeform, or swept shape — a body shell, panel, fairing, ergonomic curve, lens, or sculpted form — authored as a NURBS Surface into the user's .kcad.ts, OR when you need to finish surfaces into a watertight solid or taper faces for moldability. One authoring/finishing path, selected by kind:

  • 'nurbs' — insert a nurbsSurface(...) / surfaceFromCurves(...) call. Pass either { controls, degree, weights?, knots?, periodic? } for direct construction, OR { section_sketch_ids } for skinning. Weights are honored: supply rational weights to build exact circles/cylinders/spheres/conics (the surface becomes rational); omit weights for a non-rational surface.

  • 'boundary' — insert a surfaceFromBoundary([c1,c2,c3,c4], opts?) call: one NURBS face through 4 boundary Curve3D refs (bottom, right, top, left in loop order; adjacent endpoints must coincide within 1e-6 mm) via OCCT BRepOffsetAPI_MakeFilling.

  • 'trim' — insert a <surface>.trimTo(<by>) or <surface>.split(<by>) call. Pass surface_binding (the Surface variable name), by_binding (the cutter Surface variable name; Shape/Curve3D cutters are deferred to a later slice), and op: 'trim' (keep the largest imprinted piece) or op: 'split' (return both halves as a [Surface, Surface] tuple).

  • 'sew' — insert a sew([s0, s1, ...], opts?) call to stitch N surfaces into a closed watertight solid via OCCT BRepBuilderAPI_Sewing. Pass surface_bindings (array of Surface variable names). Use after trim/boundary to close patches into a solid: trim → sew → solid pipeline. Optional tolerance (mm, default 1e-6) and require_closed (emits feature.surface-sew.open-shell if result is not watertight).

  • 'draft' — insert a <shape>.draft(angleDeg, { face, neutralPlane?, pullDir? }) call to taper the selected face(s) for mold release. Pass shape_binding, angle_deg (0–90), and face (canonical name, label, or FaceQuery descriptor). Lowering emits feature.draft.failed on invalid geometry. The returned Surface produces no Shape until you chain .thicken(t) or .toShape() (do that via add_feature on the binding name). Returns the modified code + diagnostics. Each kind fails closed on its own missing required params.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
opNokind:'trim' — 'trim' discards the smaller half (calls .trimTo()); 'split' retains both halves (calls .split()).
codeYesCurrent .kcad.ts source.
faceNokind:'draft' — face selector for the face(s) to taper. Accepts a canonical name (top/bottom/front/back/left/right), a user label declared via faceLabels, or a FaceQuery descriptor string.
kindYesWhich surface-construction or surface-finishing path to use: 'nurbs' | 'boundary' | 'trim' | 'sew' | 'draft'.
knotsNokind:'nurbs' — optional explicit knot vectors; missing => clamped uniform inferred.
degreeNokind:'nurbs' — degrees in U and V; each in [1, nU-1] / [1, nV-1].
weightsNokind:'nurbs' — optional rational weights, same grid shape as controls. Ignored in slice-1.
controlsNokind:'nurbs' — control-point grid for direct construction (controls[u][v] = [x, y, z], mm).
periodicNokind:'nurbs' — optional periodic flags per parametric direction.
pull_dirNokind:'draft' — demoulding direction as [x, y, z]. Defaults to the face normal at lower time.
samplingNokind:'boundary' — OCCT NbPtsOnCur sampling parameter (default 15).
angle_degNokind:'draft' — draft angle in degrees [0, 90]. The face is tapered outward by this angle relative to the pull direction.
toleranceNokind:'sew' — edge-merging tolerance in mm (default 1e-6). Edges within this distance are merged.
by_bindingNokind:'trim' — JS variable name of the cutter Surface (must be declared in source). Shape/Curve3D cutters are deferred.
continuityNokind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge, bottom/right/top/left order). Default 'C0'.
binding_nameNoJS const name for the new binding (kind:'nurbs' default surface_<N>; kind:'boundary' default _surface_<N>; kind:'trim' default _trimmed_<N>; kind:'sew' default _sewn_<N>; kind:'draft' default _drafted_<N>).
neutral_planeNokind:'draft' — parting-line face (the plane where drafted faces remain fixed). Defaults to `face` if omitted.
shape_bindingNokind:'draft' — JS variable name of the Shape to taper (must be declared in source).
curve_bindingsNokind:'boundary' — tuple of 4 existing Curve3D variable names (bottom, right, top, left) declared earlier in the source.
require_closedNokind:'sew' — when true the lowerer emits feature.surface-sew.open-shell if the stitched result is not a watertight solid.
surface_bindingNokind:'trim' — JS variable name of the Surface to trim/split (must be declared in source).
surface_bindingsNokind:'sew' — JS variable names of the surfaces to stitch into a solid (each must be declared in source).
section_sketch_idsNokind:'nurbs' — existing sketch FeatureIds (2 or more) to skin a surface through, in order.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
okYesWhether the edit applied and re-evaluated cleanly.
errorNoFailure message (present when ok is false).
new_codeNoModified .kcad.ts source (present on success). Caller persists it.
diagnosticsNoDiagnostics from re-evaluating the modified source.
binding_nameNoJS const name bound to the new construct (when one was created).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed14 schema fields changed
    • addedInput schema / properties / angle_deg
      Added value: +{
      +  "description": "kind:'draft' — draft angle in degrees [0, 90]. The face is tapered outward by this angle relative to the pull direction.",
      +  "maximum": 90,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • changedInput schema / properties / binding_name / description
      Previous value: -"JS const name for the new Surface binding (kind:'nurbs' default surface_<N>; kind:'boundary' default _surface_<N>)."New value: +"JS const name for the new binding (kind:'nurbs' default surface_<N>; kind:'boundary' default _surface_<N>; kind:'trim' default _trimmed_<N>; kind:'sew' default _sewn_<N>; kind:'draft' default _drafted_<N>)."
    • addedInput schema / properties / by_binding
      Added value: +{
      +  "description": "kind:'trim' — JS variable name of the cutter Surface (must be declared in source). Shape/Curve3D cutters are deferred.",
      +  "type": "string"
      +}
    • addedInput schema / properties / face
      Added value: +{
      +  "description": "kind:'draft' — face selector for the face(s) to taper. Accepts a canonical name (top/bottom/front/back/left/right), a user label declared via faceLabels, or a FaceQuery descriptor string.",
      +  "type": "string"
      +}
    • changedInput schema / properties / kind / description
      Previous value: -"Which surface-construction path to use."New value: +"Which surface-construction or surface-finishing path to use: 'nurbs' | 'boundary' | 'trim' | 'sew' | 'draft'."
    • changedInput schema / properties / kind / enum
      Previous value: -[
      -  "nurbs",
      -  "boundary"
      -]New value: +[
      +  "nurbs",
      +  "boundary",
      +  "trim",
      +  "sew",
      +  "draft"
      +]
    • addedInput schema / properties / neutral_plane
      Added value: +{
      +  "description": "kind:'draft' — parting-line face (the plane where drafted faces remain fixed). Defaults to `face` if omitted.",
      +  "type": "string"
      +}
    • addedInput schema / properties / op
      Added value: +{
      +  "description": "kind:'trim' — 'trim' discards the smaller half (calls .trimTo()); 'split' retains both halves (calls .split()).",
      +  "enum": [
      +    "trim",
      +    "split"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / pull_dir
      Added value: +{
      +  "description": "kind:'draft' — demoulding direction as [x, y, z]. Defaults to the face normal at lower time.",
      +  "items": {
      +    "type": "number"
      +  },
      +  "maxItems": 3,
      +  "minItems": 3,
      +  "type": "array"
      +}
    • addedInput schema / properties / require_closed
      Added value: +{
      +  "description": "kind:'sew' — when true the lowerer emits feature.surface-sew.open-shell if the stitched result is not a watertight solid.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / shape_binding
      Added value: +{
      +  "description": "kind:'draft' — JS variable name of the Shape to taper (must be declared in source).",
      +  "type": "string"
      +}
    • addedInput schema / properties / surface_binding
      Added value: +{
      +  "description": "kind:'trim' — JS variable name of the Surface to trim/split (must be declared in source).",
      +  "type": "string"
      +}
    • addedInput schema / properties / surface_bindings
      Added value: +{
      +  "description": "kind:'sew' — JS variable names of the surfaces to stitch into a solid (each must be declared in source).",
      +  "items": {
      +    "type": "string"
      +  },
      +  "minItems": 1,
      +  "type": "array"
      +}
    • addedInput schema / properties / tolerance
      Added value: +{
      +  "description": "kind:'sew' — edge-merging tolerance in mm (default 1e-6). Edges within this distance are merged.",
      +  "type": "number"
      +}
  2. Changed2 schema fields changed
    • changedInput schema / properties / continuity / description
      Previous value: -"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge). Default 'C0'."New value: +"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge, bottom/right/top/left order). Default 'C0'."
    • addedInput schema / properties / continuity / oneOf
      Added value: +[
      +  {
      +    "enum": [
      +      "C0",
      +      "C1",
      +      "C2"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "items": {
      +      "enum": [
      +        "C0",
      +        "C1",
      +        "C2"
      +      ],
      +      "type": "string"
      +    },
      +    "maxItems": 4,
      +    "minItems": 4,
      +    "type": "array"
      +  }
      +]
  3. Changed2 schema fields changed
    • changedInput schema / properties / continuity / description
      Previous value: -"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge, bottom/right/top/left order). Default 'C0'."New value: +"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge). Default 'C0'."
    • removedInput schema / properties / continuity / oneOf
      Removed value: -[
      -  {
      -    "enum": [
      -      "C0",
      -      "C1",
      -      "C2"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "items": {
      -      "enum": [
      -        "C0",
      -        "C1",
      -        "C2"
      -      ],
      -      "type": "string"
      -    },
      -    "maxItems": 4,
      -    "minItems": 4,
      -    "type": "array"
      -  }
      -]
  4. Changed2 schema fields changed
    • changedInput schema / properties / continuity / description
      Previous value: -"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge). Default 'C0'."New value: +"kind:'boundary' — continuity grade applied to every edge ('C0' | 'C1' | 'C2'), or an array of 4 grades (one per edge, bottom/right/top/left order). Default 'C0'."
    • addedInput schema / properties / continuity / oneOf
      Added value: +[
      +  {
      +    "enum": [
      +      "C0",
      +      "C1",
      +      "C2"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "items": {
      +      "enum": [
      +        "C0",
      +        "C1",
      +        "C2"
      +      ],
      +      "type": "string"
      +    },
      +    "maxItems": 4,
      +    "minItems": 4,
      +    "type": "array"
      +  }
      +]
  5. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "properties": {
      +    "binding_name": {
      +      "description": "JS const name bound to the new construct (when one was created).",
      +      "type": "string"
      +    },
      +    "diagnostics": {
      +      "description": "Diagnostics from re-evaluating the modified source.",
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "error": {
      +      "description": "Failure message (present when ok is false).",
      +      "type": "string"
      +    },
      +    "new_code": {
      +      "description": "Modified .kcad.ts source (present on success). Caller persists it.",
      +      "type": "string"
      +    },
      +    "ok": {
      +      "description": "Whether the edit applied and re-evaluated cleanly.",
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "ok"
      +  ],
      +  "type": "object"
      +}
  6. Added

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description reveals non-obvious behaviors: weights are honored for rational surfaces, trim keeps the largest imprinted piece, split returns a tuple, sew produces a watertight solid and emits open-shell diagnostics, and draft emits feature.draft.failed on invalid geometry. It also notes that returned surfaces produce no Shape until .thicken/.toShape() via add_feature, and that Shape/Curve3D cutters are deferred. This all goes beyond the sparse annotations and is consistent with them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but appropriately structured: a purpose sentence followed by five bulleted modes, each with the generated call, required data, and edge-case behavior. The front-loaded opening and bullet hierarchy make it skimmable. Some verbosity is justified by the tool's 5 modes and 23 parameters, and no sentence is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all five modes, specifying required data, defaults (tolerance, degree bounds), failure semantics (fails closed, open-shell, draft.failed), and the follow-up pipeline (add_feature for thickening/toShape). With an output schema present and annotations minimal, it provides all context an agent needs to select and invoke the correct path.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by grouping parameters into construction modes (e.g., controls/degree/weights/knots/periodic vs section_sketch_ids for nurbs), documenting boundary edge ordering and the 1e-6 mm coincidence constraint not present in the schema, and clarifying trim/split and continuity defaults. It doesn't restate every schema field, which is appropriate given the schema is rich.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description immediately states the tool's purpose: 'Use this when you need an organic, freeform, or swept shape... authored as a NURBS Surface' and enumerates five concrete modes (nurbs, boundary, trim, sew, draft). It distinguishes itself from siblings by naming add_feature as the follow-up step and clarifying the surface-authoring/finishing domain.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description opens with explicit usage context ('Use this when you need...') and provides conditional guidance per kind ('Pass either { controls, ... } or { section_sketch_ids }'). It also points to add_feature as the alternative for converting a surface to a Shape. However, it doesn't explicitly state when not to use the tool, such as for primitive geometry that belongs in add_part.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.