Skip to main content
Glama

Add Surface

add_surface
Idempotent

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).

  • '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. 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

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' — points sampled along each boundary (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

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • removedOutput schema / properties
      Removed value: -{
      -  "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"
      -  }
      -}
    • removedOutput schema / required
      Removed value: -[
      -  "ok"
      -]
  2. Changed1 schema field changed
    • changedInput schema / properties / sampling / description
      Previous value: -"kind:'boundary' — OCCT NbPtsOnCur sampling parameter (default 15)."New value: +"kind:'boundary' — points sampled along each boundary (default 15)."
  3. 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"
      +}
  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. 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"
      -  }
      -]
  6. 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"
      +  }
      +]
  7. 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"
      +}
  8. Added

TDQS

A4.3/5.0
Behavior3/5

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

Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description adds real behavioral context: each kind fails closed on missing params, specific diagnostic codes are emitted (feature.surface-sew.open-shell, feature.draft.failed), and a Surface yields no Shape until chained. However, it asserts 'Weights are honored: supply rational weights to build exact circles/cylinders/spheres' while the schema for the same field says 'Ignored in slice-1' — a direct contradiction that could mislead an agent into expecting rational geometry it will not get.

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 for 23 parameters and five distinct sub-APIs the content is load-bearing, and the trigger condition plus the kind list is front-loaded. Some per-kind prose duplicates the schema's own parameter descriptions (e.g. tolerance defaults, angle range), which costs a point but not more.

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

Completeness4/5

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

With 23 params, nested objects, and an output schema present, the description covers what an agent needs: what each kind emits, ordering constraints, failure modes, defaults, and the fact that the result is not a solid until chained. The remaining gap is the unresolved weights/slice-1 conflict, which leaves ambiguous whether rational input is actually consumed.

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 earns above that by explaining intent per kind — e.g. that 4 boundary curves are in bottom/right/top/left loop order with endpoints coinciding within 1e-6 mm, and that knots are optional and clamped-uniform when omitted. A small deduction for the same weights contradiction and for the 'trim' gloss ('keep the largest imprinted piece') drifting from the schema's 'discards the smaller half'.

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 names a specific verb (author a NURBS Surface) and resource, then enumerates every path ('nurbs', 'boundary', 'trim', 'sew', 'draft') with the exact API call each emits. An agent can distinguish this from add_curve or apply_surface_blend without opening the schema, because the opening sentence scopes it to freeform/swept surface authoring and surface finishing.

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

Usage Guidelines5/5

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

It states when to use the tool ('organic, freeform, or swept shape — a body shell, panel, fairing...'), how the paths compose ('trim → sew → solid pipeline'), and explicitly routes post-authoring work elsewhere ('chain .thicken(t) or .toShape() ... do that via add_feature on the binding name'). The usage guidance is explicit, not inferred.

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.