@vcad/mcp 0.9.4-main.77 → 0.9.4-main.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,4 +6,4 @@ vcad's MCP server as a self-contained bundle (server + BRep kernel WASM).
6
6
  { "mcpServers": { "vcad": { "command": "npx", "args": ["-y", "@vcad/mcp"] } } }
7
7
  ```
8
8
 
9
- Built from 47bac49e0b31af1164ed47e5b81d72861ea5ce0f at 2026-08-28T13:11:01.217Z. Source: https://github.com/ecto/vcad
9
+ Built from 0e2be365be04f9575150d95283330258f30e1c69 at 2026-09-01T14:43:15.880Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -9911,8 +9911,10 @@ function evaluateOp(op, nodes, Solid2, cache2, depth = 0) {
9911
9911
  op.path.end.z
9912
9912
  ]);
9913
9913
  return Solid2.sweepLine(profileJson, start, end, op.twist_angle, op.scale_start, op.scale_end, op.orientation);
9914
- } else {
9914
+ } else if (op.path.type === "Helix") {
9915
9915
  return Solid2.sweepHelix(profileJson, op.path.radius, op.path.pitch, op.path.height, op.path.turns, op.twist_angle, op.scale_start, op.scale_end, op.path_segments, op.arc_segments, op.orientation);
9916
+ } else {
9917
+ throw new Error("Cylindrical sweep paths are not yet supported in the web engine (use the native pipeline)");
9916
9918
  }
9917
9919
  }
9918
9920
  case "Loft": {
@@ -41631,6 +41633,51 @@ var init_CHANGELOG = __esm({
41631
41633
  CHANGELOG_default = {
41632
41634
  $schema: "./changelog.schema.json",
41633
41635
  entries: [
41636
+ {
41637
+ id: "2026-09-01-solid-query-probe-suites",
41638
+ version: "0.9.4",
41639
+ date: "2026-09-01",
41640
+ category: "feat",
41641
+ title: "Solid query API and probe suites",
41642
+ summary: "Classify points against posed assemblies, measure part-to-part clearance, and run JSON probe suites with `vcad probe` (nonzero exit on failure).",
41643
+ features: [
41644
+ "query",
41645
+ "probe",
41646
+ "clearance",
41647
+ "assembly",
41648
+ "cli"
41649
+ ]
41650
+ },
41651
+ {
41652
+ id: "2026-09-01-helix-path-and-sweep",
41653
+ version: "0.9.4",
41654
+ date: "2026-09-01",
41655
+ category: "feat",
41656
+ title: "loon: helix / cam-path paths and a sweep that takes them",
41657
+ summary: "Cam tracks, bayonet and J-slots, lead-in ramps and threads are now a primitive: a path dimensioned as rise-per-degree, swept as a closed polyline profile.",
41658
+ details: "[helix r rate-mm-per-deg start-deg arc-deg] is a first-class Path, and [cam-path r #[deg z ...]] is the general form whose extra knots express a rise-plateau-drop detent or a flat pocket directly. [sweep path profile] carries a closed polyline section along it, holding the cross-section in the radial/axial plane so floor(theta) = path z(theta) + min(profile y) exactly. Knots always land on path samples, the facet step is 0.5 deg by default and settable per path, and the solid is capped at both ends so it is watertight standing alone and can be subtracted through a wall.",
41659
+ features: [
41660
+ "loon",
41661
+ "primitives",
41662
+ "sweep"
41663
+ ],
41664
+ mcpTools: []
41665
+ },
41666
+ {
41667
+ id: "2026-08-28-multitool-difference-manifold",
41668
+ version: "0.9.4",
41669
+ date: "2026-08-28",
41670
+ category: "fix",
41671
+ title: "Manifold exports for multi-tool differences",
41672
+ summary: "Subtracting a multi-stage union tool (bore + groove + patterned slots) no longer exports slit or doubled surface; broken analytic results now swap to a repaired mesh boolean.",
41673
+ features: [
41674
+ "booleans",
41675
+ "export",
41676
+ "stl",
41677
+ "printing"
41678
+ ],
41679
+ mcpTools: []
41680
+ },
41634
41681
  {
41635
41682
  id: "2026-08-28-manifold-nested-ring-unions",
41636
41683
  version: "0.9.4",
@@ -50536,7 +50583,7 @@ var init_loon = __esm({
50536
50583
  {
50537
50584
  name: "create_cad_loon",
50538
50585
  pack: null,
50539
- description: 'The preferred authoring tool for whole parts and multi-feature models \u2014 one call, full vocabulary. Create a CAD document from loon source code. Loon is a Lisp-like language for parametric CAD \u2014 the FULL modeling vocabulary (patterns, sketches, extrude/revolve/sweep/loft, assemblies) is available here even where no dedicated MCP tool exists. For incremental single-node edits to an open session, use create/update/delete instead.\n\nPrimitives: [cube x y z], [cylinder r h], [sphere r], [cone r-bottom r-top h], [torus major-r minor-r], [wedge x y z], [prism sides radius height]. Segment count is the kernel default (32); pin it with [cylinder-n r h n] / [sphere-n r n] / [cone-n rb rt h n] / [torus-n R r n] where the facets are load-bearing (a bore that must accept a real shaft)\nImports \u2014 place a purchased part instead of approximating it, so fit checks test the real envelope and not one you invented: [import-step "vendor/x6-60.step"], [import-step-body path index] for a multi-body file, [import-mesh "part.stl"], [import-mesh-scaled sx sy sz path]. Relative paths resolve against base_dir / the module source\nSheet metal (subject-last, so it threads through pipe) \u2014 author a cut-and-bent part as a bend chain and it KEEPS its bends, so sheet_metal_unfold is exact instead of inferred back out of a solid by flat_pattern_from_solid: [sheet-base-flange-rect width depth thickness "al-soft"] (or [sheet-base-flange #[x0 y0 \u2026] #[holes] t material] for an arbitrary outline) then [sheet-edge-flange edge length angle-deg s], [sheet-jog edge offset length s], [sheet-hem edge length s], [sheet-bend-relief s]. `edge` is an outline index, or "south"/"east"/"north"/"west" on a rectangular base flange (edge 0 is the -Y edge, CCW from there). Each has an -at form taking panel id, radius, direction ("up"/"down") and K-factor, where 0.0 means the default; -shop variants resolve every bend through a shop table. Sheet nodes are a bend graph, NOT solids \u2014 never union, transform or fillet them\nBooleans (subject-last): [difference tool subject], [union other subject], [intersection other subject]\nTransforms (subject-last): [translate x y z s], [rotate rx ry rz s], [scale sx sy sz s], [mirror ox oy oz nx ny nz s] (plane through the origin point with that normal) \u2014 plus the axis sugar [mirror-x s] / [mirror-y s] / [mirror-z s], which mirror through the origin, negating that one coordinate. NEVER hand-mirror by negating coordinates; use these.\nFeatures: [fillet r s], [chamfer d s], [shell t s]\nPatterns (subject-last): [linear-pattern dx dy dz count spacing s], [circular-pattern ox oy oz ax ay az count angle s] \u2014 e.g. a bolt circle is [circular-pattern 0 0 0 0 0 1 6 360 bolt-hole]\nSymmetric patterns (subject-last): [mirror-pattern nx ny nz s] and its sugar [mirror-pattern-x s] / -y / -z union a solid with its mirror image (a left/right pair in one expression, so the halves can\'t drift apart); [quad-pattern s] is the 4-fold X-and-Y version \u2014 a quadruped\'s legs, a 4-post frame, a vehicle chassis\nSketches: [sketch ox oy oz xx xy xz yx yy yz #[segments]] with [line x1 y1 x2 y2] and [arc x1 y1 x2 y2 cx cy ccw]\nSketch ops (sketch-last): [extrude dx dy dz sk], [revolve aox aoy aoz adx ady adz angle sk], [sweep-line sx sy sz ex ey ez sk], [sweep-helix radius pitch height turns sk], [loft #[sk1 sk2 \u2026]], [loft-closed #[sk1 sk2 \u2026]]\nAssemblies: [assembly #[parts] #[instances] #[joints] ground-id] with [part name solid "material"], [instance name part-name x y z], [revolute-joint \u2026], [prismatic-joint \u2026], [fixed-joint \u2026], [ball-joint \u2026]\nAssembly symmetry: author ONE side as an assembly, then [mirror-group-x "-r" side] (or -y / -z) returns it plus a mirrored, suffixed copy \u2014 parts reflected, placements and joint anchors mirrored, and joint axes flipped by the correct rule (a hinge across its own mirror normal keeps its axis; the other two flip), so the same joint state drives both sides symmetrically. Splice it back with [assembly-join chassis mirrored]. NEVER hand-mirror an assembly.\nPipe: [pipe [cube 50 30 5] [difference [cylinder 3 10]] [fillet 1.0]]\nLet bindings: [let body [cube 50 30 5]] \u2014 note these are inlined and do NOT survive into the document; use [defparam ...] for a value you want to change later\nParameters (survive into the document and are settable afterwards with set_parameters, and differentiable with parameter_gradient): [defparam pitch_axis_x 310.0], [defparam wall "bore * 0.2"] for derived values, plus optional :unit/:min/:max/:description. Names must be identifier-safe (underscores, not dashes)\nDatums \u2014 named reference geometry, so two parts cannot each hold their own copy of a shared plane: [datum-plane "femur_inner" y 131.0], [datum-axis "pitch" x 0 0 310], [datum-point "hip" 0 0 310], read back with [datum "femur_inner"], [datum+ "femur_inner" 3.0] (3 mm outboard), [datum-x/-y/-z "pitch"]\nStacks \u2014 declarative packing, where each running clearance is a named value instead of an arbitrary number: [stack y "leg" 131.0 [lane "femur_inner" 5.0] [gap "idler_run" 1.0] [lane "idler_boss" 3.0]] declares datum planes leg_femur_inner_lo/_hi, leg_idler_boss_lo/_hi and leg_end; widening leg_idler_run slides everything outboard of it\nScene: [root solid "material-name"], with [material name r g b metallic roughness] to define one\nModules: [use bracket] then [bracket.plate] \u2014 multi-file projects work here, with sources passed in `modules` (or read from `base_dir`); [use bracket :as b] aliases, [use bracket [plate]] imports selectively, and `pub` in a module picks what it exports',
50586
+ description: 'The preferred authoring tool for whole parts and multi-feature models \u2014 one call, full vocabulary. Create a CAD document from loon source code. Loon is a Lisp-like language for parametric CAD \u2014 the FULL modeling vocabulary (patterns, sketches, extrude/revolve/sweep/loft, assemblies) is available here even where no dedicated MCP tool exists. For incremental single-node edits to an open session, use create/update/delete instead.\n\nPrimitives: [cube x y z], [cylinder r h], [sphere r], [cone r-bottom r-top h], [torus major-r minor-r], [wedge x y z], [prism sides radius height]. Segment count is the kernel default (32); pin it with [cylinder-n r h n] / [sphere-n r n] / [cone-n rb rt h n] / [torus-n R r n] where the facets are load-bearing (a bore that must accept a real shaft)\nImports \u2014 place a purchased part instead of approximating it, so fit checks test the real envelope and not one you invented: [import-step "vendor/x6-60.step"], [import-step-body path index] for a multi-body file, [import-mesh "part.stl"], [import-mesh-scaled sx sy sz path]. Relative paths resolve against base_dir / the module source\nSheet metal (subject-last, so it threads through pipe) \u2014 author a cut-and-bent part as a bend chain and it KEEPS its bends, so sheet_metal_unfold is exact instead of inferred back out of a solid by flat_pattern_from_solid: [sheet-base-flange-rect width depth thickness "al-soft"] (or [sheet-base-flange #[x0 y0 \u2026] #[holes] t material] for an arbitrary outline) then [sheet-edge-flange edge length angle-deg s], [sheet-jog edge offset length s], [sheet-hem edge length s], [sheet-bend-relief s]. `edge` is an outline index, or "south"/"east"/"north"/"west" on a rectangular base flange (edge 0 is the -Y edge, CCW from there). Each has an -at form taking panel id, radius, direction ("up"/"down") and K-factor, where 0.0 means the default; -shop variants resolve every bend through a shop table. Sheet nodes are a bend graph, NOT solids \u2014 never union, transform or fillet them\nBooleans (subject-last): [difference tool subject], [union other subject], [intersection other subject]\nTransforms (subject-last): [translate x y z s], [rotate rx ry rz s], [scale sx sy sz s], [mirror ox oy oz nx ny nz s] (plane through the origin point with that normal) \u2014 plus the axis sugar [mirror-x s] / [mirror-y s] / [mirror-z s], which mirror through the origin, negating that one coordinate. NEVER hand-mirror by negating coordinates; use these.\nFeatures: [fillet r s], [chamfer d s], [shell t s]\nPatterns (subject-last): [linear-pattern dx dy dz count spacing s], [circular-pattern ox oy oz ax ay az count angle s] \u2014 e.g. a bolt circle is [circular-pattern 0 0 0 0 0 1 6 360 bolt-hole]\nSymmetric patterns (subject-last): [mirror-pattern nx ny nz s] and its sugar [mirror-pattern-x s] / -y / -z union a solid with its mirror image (a left/right pair in one expression, so the halves can\'t drift apart); [quad-pattern s] is the 4-fold X-and-Y version \u2014 a quadruped\'s legs, a 4-post frame, a vehicle chassis\nSketches: [sketch ox oy oz xx xy xz yx yy yz #[segments]] with [line x1 y1 x2 y2] and [arc x1 y1 x2 y2 cx cy ccw]\nSketch ops (sketch-last): [extrude dx dy dz sk], [revolve aox aoy aoz adx ady adz angle sk], [sweep-line sx sy sz ex ey ez sk], [sweep-helix radius pitch height turns sk], [loft #[sk1 sk2 \u2026]], [loft-closed #[sk1 sk2 \u2026]]\nCam tracks, bayonet/J-slots, lead-in ramps and threads (profile-last): [sweep path profile], where the path is [helix r rate-mm-per-deg start-deg arc-deg] or, for a track whose height is not a constant rate, [cam-path r #[deg0 z0 deg1 z1 \u2026]] \u2014 a rise-plateau-drop detent or a flat pocket is just more knots. The profile is [profile-rect radial axial] or [profile-polyline #[x0 y0 x1 y1 \u2026]], with x = RADIAL offset from the path radius (outward +) and y = AXIAL offset (up +); the section is held in that radial/axial plane, so floor(theta) = path z(theta) + min(profile y) exactly. Facet step defaults to 0.5 deg \u2014 pin it with [helix-res seg-deg \u2026] / [cam-path-res seg-deg \u2026]. The swept solid is capped at both ends, so it is watertight standing alone and can be subtracted through a wall. Do NOT approximate a cam track with stacked z-bands or a circular-pattern of boxes\nAssemblies: [assembly #[parts] #[instances] #[joints] ground-id] with [part name solid "material"], [instance name part-name x y z], [revolute-joint \u2026], [prismatic-joint \u2026], [fixed-joint \u2026], [ball-joint \u2026]\nAssembly symmetry: author ONE side as an assembly, then [mirror-group-x "-r" side] (or -y / -z) returns it plus a mirrored, suffixed copy \u2014 parts reflected, placements and joint anchors mirrored, and joint axes flipped by the correct rule (a hinge across its own mirror normal keeps its axis; the other two flip), so the same joint state drives both sides symmetrically. Splice it back with [assembly-join chassis mirrored]. NEVER hand-mirror an assembly.\nPipe: [pipe [cube 50 30 5] [difference [cylinder 3 10]] [fillet 1.0]]\nLet bindings: [let body [cube 50 30 5]] \u2014 note these are inlined and do NOT survive into the document; use [defparam ...] for a value you want to change later\nParameters (survive into the document and are settable afterwards with set_parameters, and differentiable with parameter_gradient): [defparam pitch_axis_x 310.0], [defparam wall "bore * 0.2"] for derived values, plus optional :unit/:min/:max/:description. Names must be identifier-safe (underscores, not dashes)\nDatums \u2014 named reference geometry, so two parts cannot each hold their own copy of a shared plane: [datum-plane "femur_inner" y 131.0], [datum-axis "pitch" x 0 0 310], [datum-point "hip" 0 0 310], read back with [datum "femur_inner"], [datum+ "femur_inner" 3.0] (3 mm outboard), [datum-x/-y/-z "pitch"]\nStacks \u2014 declarative packing, where each running clearance is a named value instead of an arbitrary number: [stack y "leg" 131.0 [lane "femur_inner" 5.0] [gap "idler_run" 1.0] [lane "idler_boss" 3.0]] declares datum planes leg_femur_inner_lo/_hi, leg_idler_boss_lo/_hi and leg_end; widening leg_idler_run slides everything outboard of it\nScene: [root solid "material-name"], with [material name r g b metallic roughness] to define one\nModules: [use bracket] then [bracket.plate] \u2014 multi-file projects work here, with sources passed in `modules` (or read from `base_dir`); [use bracket :as b] aliases, [use bracket [plate]] imports selectively, and `pub` in a module picks what it exports',
50540
50587
  inputSchema: createCadLoonSchema,
50541
50588
  handler: async (args, ctx) => {
50542
50589
  const useLoons = Array.isArray(args.use_loons) ? args.use_loons : void 0;
@@ -84317,8 +84364,8 @@ var init_server3 = __esm({
84317
84364
  init_order_feed();
84318
84365
  init_animate();
84319
84366
  PKG_VERSION = (() => {
84320
- if ("0.9.4-main.77") {
84321
- return "0.9.4-main.77";
84367
+ if ("0.9.4-main.78") {
84368
+ return "0.9.4-main.78";
84322
84369
  }
84323
84370
  try {
84324
84371
  const req = createRequire2(import.meta.url);
@@ -84327,8 +84374,8 @@ var init_server3 = __esm({
84327
84374
  return "0.0.0";
84328
84375
  }
84329
84376
  })();
84330
- BUILD_SHA = "47bac49e0b31af1164ed47e5b81d72861ea5ce0f";
84331
- BUILD_TIME = "2026-08-28T13:11:01.217Z";
84377
+ BUILD_SHA = "0e2be365be04f9575150d95283330258f30e1c69";
84378
+ BUILD_TIME = "2026-09-01T14:43:15.880Z";
84332
84379
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
84333
84380
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
84334
84381
  INSTANCE_ID = randomUUID7().slice(0, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.9.4-main.77",
3
+ "version": "0.9.4-main.78",
4
4
  "description": "vcad MCP server — parametric CAD + PCB design tools for AI agents (self-contained: bundled server + kernel WASM)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "homepage": "https://vcad.io",
21
21
  "vcadBuild": {
22
- "sha": "47bac49e0b31af1164ed47e5b81d72861ea5ce0f",
23
- "builtAt": "2026-08-28T13:11:01.217Z"
22
+ "sha": "0e2be365be04f9575150d95283330258f30e1c69",
23
+ "builtAt": "2026-09-01T14:43:15.880Z"
24
24
  }
25
25
  }
Binary file