@vcad/mcp 0.10.0-main.132 → 0.10.0-main.134

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.mjs +157 -47
  3. package/package.json +3 -3
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 362c46b798588ed58f200c9d529b3d11b2b2ff73 at 2026-10-21T17:31:51.205Z. Source: https://github.com/ecto/vcad
9
+ Built from 50d4e0c1c282745ef88e456dca033ceabdee9c31 at 2026-10-21T17:58:04.042Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -10887,6 +10887,15 @@ function handleEngineRequest(host, req) {
10887
10887
  const engine2 = host.engine;
10888
10888
  if (!engine2)
10889
10889
  return { ok: false, message: "engine not initialized" };
10890
+ if ((req.op === "apply" || req.op === "applyTool") && req.expectHash !== void 0 && engine2.stateHash() !== req.expectHash) {
10891
+ return {
10892
+ ok: true,
10893
+ stale: true,
10894
+ hash: engine2.stateHash(),
10895
+ canUndo: engine2.can_undo(),
10896
+ canRedo: engine2.can_redo()
10897
+ };
10898
+ }
10890
10899
  if (req.op === "apply")
10891
10900
  envelope = engine2.applyDelta(JSON.stringify(req.command));
10892
10901
  else if (req.op === "applyTool")
@@ -10920,6 +10929,19 @@ function inProcessTransport(Engine2) {
10920
10929
  }
10921
10930
  };
10922
10931
  }
10932
+ function sharedEngineTransport(getEngine) {
10933
+ const ownerOnly = function() {
10934
+ throw new Error("shared engine: the owner constructs engines");
10935
+ };
10936
+ return {
10937
+ request: async (req) => {
10938
+ const host = { Engine: ownerOnly, engine: getEngine() };
10939
+ const r = req.op === "init" || req.op === "load" ? { op: "state" } : req;
10940
+ return handleEngineRequest(host, r);
10941
+ },
10942
+ dispose: () => void 0
10943
+ };
10944
+ }
10923
10945
  function workerTransport(worker) {
10924
10946
  let next = 0;
10925
10947
  const pending2 = /* @__PURE__ */ new Map();
@@ -11009,10 +11031,17 @@ var init_engine_host = __esm({
11009
11031
  }
11010
11032
  delta(req) {
11011
11033
  return this.enqueue(async () => {
11012
- const base = this.view;
11013
- if (!base)
11034
+ if (!this.view)
11014
11035
  throw new EngineHostError("engine not initialized");
11015
- const r = this.check(await this.transport.request(req));
11036
+ let r = this.check(await this.transport.request({ ...req, expectHash: this.flags.hash }));
11037
+ if (r.stale) {
11038
+ const full = this.check(await this.transport.request({ op: "state" }));
11039
+ this.view = stateFromEnvelope(full.envelope);
11040
+ r = this.check(await this.transport.request({ ...req, expectHash: this.flags.hash }));
11041
+ if (r.stale)
11042
+ throw new EngineHostError("engine changed during resync");
11043
+ }
11044
+ const base = this.view;
11016
11045
  const delta = parseDeltaEnvelope(r.envelope);
11017
11046
  const { state, changes } = applyEngineDelta(base, delta);
11018
11047
  this.view = state;
@@ -12310,6 +12339,7 @@ __export(dist_exports, {
12310
12339
  searchEcadParts: () => searchEcadParts,
12311
12340
  searchParts: () => searchParts,
12312
12341
  semanticDiff: () => semanticDiff,
12342
+ sharedEngineTransport: () => sharedEngineTransport,
12313
12343
  solveDesignConstraints: () => solveDesignConstraints2,
12314
12344
  solveForwardKinematics: () => solveForwardKinematics2,
12315
12345
  stateFromEnvelope: () => stateFromEnvelope,
@@ -31847,6 +31877,7 @@ var init_document_store = __esm({
31847
31877
  init_esm2();
31848
31878
  init_wasm_singleton2();
31849
31879
  init_engine_command();
31880
+ init_dist();
31850
31881
  init_sketch_constraint_persist();
31851
31882
  init_dist2();
31852
31883
  init_dist2();
@@ -31873,6 +31904,27 @@ var init_document_store = __esm({
31873
31904
  // CRDT bridge state
31874
31905
  _crdtEngine: null,
31875
31906
  _crdtEngineClass: null,
31907
+ _engineClient: new DocumentEngineClient(sharedEngineTransport(() => get()._crdtEngine)),
31908
+ dispatch: async (command) => {
31909
+ const readOnly = useUiStore.getState().readOnlyShare;
31910
+ if (readOnly) {
31911
+ if (typeof window !== "undefined") {
31912
+ window.dispatchEvent(new CustomEvent("vcad:fork-prompt", { detail: readOnly }));
31913
+ }
31914
+ return void 0;
31915
+ }
31916
+ const client = get()._engineClient;
31917
+ if (!client.state)
31918
+ await client.init();
31919
+ const outcome = await client.apply(command);
31920
+ for (const w of outcome.warnings)
31921
+ console.warn(`[vcad] ${w}`);
31922
+ set(applyLegacyResult({
31923
+ document: outcome.state.document,
31924
+ parts: outcome.state.parts
31925
+ }));
31926
+ return outcome.createdFeatureId;
31927
+ },
31876
31928
  _initCrdt: (EngineClass) => {
31877
31929
  const existing = get()._crdtEngine;
31878
31930
  const existingClass = get()._crdtEngineClass;
@@ -31977,10 +32029,8 @@ var init_document_store = __esm({
31977
32029
  return "";
31978
32030
  }
31979
32031
  },
31980
- removePart: (partId) => {
31981
- const engine = get()._crdtEngine;
31982
- const result = applyCommand(engine, { type: "delete_feature", id: partId });
31983
- set(applyApiResult(result));
32032
+ removePart: async (partId) => {
32033
+ await get().dispatch({ type: "delete_feature", id: partId });
31984
32034
  },
31985
32035
  setTranslation: (partId, offset) => {
31986
32036
  const engine = get()._crdtEngine;
@@ -32064,10 +32114,8 @@ var init_document_store = __esm({
32064
32114
  const result = applyCommand(engine, { type: "set_param", id: partId, key: key3, value });
32065
32115
  set(applyLegacyResult(result));
32066
32116
  },
32067
- updateBooleanType: (partId, newType) => {
32068
- const engine = get()._crdtEngine;
32069
- const result = applyCommand(engine, { type: "set_param", id: partId, key: "boolean_type", value: crdtStr(newType) });
32070
- set(applyLegacyResult(result));
32117
+ updateBooleanType: async (partId, newType) => {
32118
+ await get().dispatch({ type: "set_param", id: partId, key: "boolean_type", value: crdtStr(newType) });
32071
32119
  },
32072
32120
  applyBoolean: (type, partIdA, partIdB) => {
32073
32121
  const engine = get()._crdtEngine;
@@ -32341,9 +32389,8 @@ var init_document_store = __esm({
32341
32389
  return null;
32342
32390
  }
32343
32391
  },
32344
- setThreadColor: (nodeId, threadIdx, color) => {
32392
+ setThreadColor: async (nodeId, threadIdx, color) => {
32345
32393
  const state = get();
32346
- const engine = state._crdtEngine;
32347
32394
  const part = state.parts.find((p) => p.kind === "embroidery-pattern" && p.patternNodeId === nodeId);
32348
32395
  if (!part)
32349
32396
  return;
@@ -32353,12 +32400,10 @@ var init_document_store = __esm({
32353
32400
  const d = structuredClone(design);
32354
32401
  if (d.threads[threadIdx])
32355
32402
  d.threads[threadIdx].color = color;
32356
- const result = applyCommand(engine, { type: "set_param", id: part.id, key: "design", value: crdtStr(JSON.stringify(d)) });
32357
- set(applyLegacyResult(result));
32403
+ await get().dispatch({ type: "set_param", id: part.id, key: "design", value: crdtStr(JSON.stringify(d)) });
32358
32404
  },
32359
- setThreadName: (nodeId, threadIdx, name) => {
32405
+ setThreadName: async (nodeId, threadIdx, name) => {
32360
32406
  const state = get();
32361
- const engine = state._crdtEngine;
32362
32407
  const part = state.parts.find((p) => p.kind === "embroidery-pattern" && p.patternNodeId === nodeId);
32363
32408
  if (!part)
32364
32409
  return;
@@ -32368,8 +32413,7 @@ var init_document_store = __esm({
32368
32413
  const d = structuredClone(design);
32369
32414
  if (d.threads[threadIdx])
32370
32415
  d.threads[threadIdx].name = name;
32371
- const result = applyCommand(engine, { type: "set_param", id: part.id, key: "design", value: crdtStr(JSON.stringify(d)) });
32372
- set(applyLegacyResult(result));
32416
+ await get().dispatch({ type: "set_param", id: part.id, key: "design", value: crdtStr(JSON.stringify(d)) });
32373
32417
  },
32374
32418
  setStitchGroupFillParams: (nodeId, groupIdx, params) => {
32375
32419
  const state = get();
@@ -32604,15 +32648,11 @@ var init_document_store = __esm({
32604
32648
  set(applyApiResult(result));
32605
32649
  return result.createdFeatureId ?? null;
32606
32650
  },
32607
- setPartMaterial: (partId, materialKey) => {
32608
- const engine = get()._crdtEngine;
32609
- const result = applyCommand(engine, { type: "set_material", id: partId, material: materialKey });
32610
- set(applyApiResult(result));
32651
+ setPartMaterial: async (partId, materialKey) => {
32652
+ await get().dispatch({ type: "set_material", id: partId, material: materialKey });
32611
32653
  },
32612
- renamePart: (partId, name) => {
32613
- const engine = get()._crdtEngine;
32614
- const result = applyCommand(engine, { type: "rename", id: partId, name });
32615
- set(applyApiResult(result));
32654
+ renamePart: async (partId, name) => {
32655
+ await get().dispatch({ type: "rename", id: partId, name });
32616
32656
  },
32617
32657
  undo: () => {
32618
32658
  const engine = get()._crdtEngine;
@@ -32645,10 +32685,8 @@ var init_document_store = __esm({
32645
32685
  const result = applyCommand(engine, { type: "set_param", id: instanceId, key: "transform", value: crdtStr(JSON.stringify(transform2)) });
32646
32686
  set(applyLegacyResult(result));
32647
32687
  },
32648
- setInstanceMaterial: (instanceId, materialKey) => {
32649
- const engine = get()._crdtEngine;
32650
- const result = applyCommand(engine, { type: "set_param", id: instanceId, key: "material", value: crdtStr(materialKey) });
32651
- set(applyLegacyResult(result));
32688
+ setInstanceMaterial: async (instanceId, materialKey) => {
32689
+ await get().dispatch({ type: "set_param", id: instanceId, key: "material", value: crdtStr(materialKey) });
32652
32690
  },
32653
32691
  setJointState: (jointId, jointState) => {
32654
32692
  const engine = get()._crdtEngine;
@@ -32719,10 +32757,8 @@ var init_document_store = __esm({
32719
32757
  const result = applyCommand(engine, { type: "delete_feature", id: instanceId });
32720
32758
  set(applyApiResult(result));
32721
32759
  },
32722
- deleteJoint: (jointId) => {
32723
- const engine = get()._crdtEngine;
32724
- const result = applyCommand(engine, { type: "delete_feature", id: jointId });
32725
- set(applyApiResult(result));
32760
+ deleteJoint: async (jointId) => {
32761
+ await get().dispatch({ type: "delete_feature", id: jointId });
32726
32762
  },
32727
32763
  setGroundInstance: (instanceId) => {
32728
32764
  const state = get();
@@ -32738,10 +32774,8 @@ var init_document_store = __esm({
32738
32774
  const result = applyCommand(engine, { type: "set_param", id: instanceId, key: "is_ground", value: crdtBool(true) });
32739
32775
  set(applyLegacyResult(result));
32740
32776
  },
32741
- renameInstance: (instanceId, name) => {
32742
- const engine = get()._crdtEngine;
32743
- const result = applyCommand(engine, { type: "set_param", id: instanceId, key: "name", value: crdtStr(name) });
32744
- set(applyLegacyResult(result));
32777
+ renameInstance: async (instanceId, name) => {
32778
+ await get().dispatch({ type: "set_param", id: instanceId, key: "name", value: crdtStr(name) });
32745
32779
  },
32746
32780
  setDocumentMeta: (id, name) => {
32747
32781
  set({ documentId: id, documentName: name });
@@ -32800,10 +32834,8 @@ var init_document_store = __esm({
32800
32834
  set(applyApiResult(envelope.result));
32801
32835
  return envelope;
32802
32836
  },
32803
- setPartVisible: (partId, visible) => {
32804
- const engine = get()._crdtEngine;
32805
- const result = applyCommand(engine, { type: "set_visible", id: partId, visible });
32806
- set(applyApiResult(result));
32837
+ setPartVisible: async (partId, visible) => {
32838
+ await get().dispatch({ type: "set_visible", id: partId, visible });
32807
32839
  },
32808
32840
  reorderPart: (partId, newIndex) => {
32809
32841
  const state = get();
@@ -41664,6 +41696,31 @@ var init_CHANGELOG = __esm({
41664
41696
  CHANGELOG_default = {
41665
41697
  $schema: "./changelog.schema.json",
41666
41698
  entries: [
41699
+ {
41700
+ id: "2026-10-21-vcad-printer-cli",
41701
+ version: "0.10.0",
41702
+ date: "2026-10-21",
41703
+ category: "feat",
41704
+ title: "vcad printer: LAN control of a Bambu P1S",
41705
+ summary: "New `vcad printer` CLI: discover, status, camera snapshot and upload test over LAN; printing refuses without --confirm-print and a passing printcheck and file/printer match.",
41706
+ features: [
41707
+ "printing",
41708
+ "bambu",
41709
+ "cli"
41710
+ ]
41711
+ },
41712
+ {
41713
+ id: "2026-10-21-slicer-first-layer-z",
41714
+ version: "0.10.0",
41715
+ date: "2026-10-21",
41716
+ category: "fix",
41717
+ title: "Slicer: layers print at full height, not half",
41718
+ summary: "Sliced G-code sent the nozzle to each layer's mid-plane, so the first layer was squashed to half height into the plate. Layers now print at their top.",
41719
+ features: [
41720
+ "printing",
41721
+ "slicer"
41722
+ ]
41723
+ },
41667
41724
  {
41668
41725
  id: "2026-10-21-planar-cap-normals",
41669
41726
  version: "0.10.0",
@@ -41690,6 +41747,19 @@ var init_CHANGELOG = __esm({
41690
41747
  "lighting"
41691
41748
  ]
41692
41749
  },
41750
+ {
41751
+ id: "2026-10-21-photoreal-look-textures",
41752
+ version: "0.10.0",
41753
+ date: "2026-10-21",
41754
+ category: "feat",
41755
+ title: "Material looks and wood/fabric textures in photoreal",
41756
+ summary: "--look applies render-time material overrides by material or part (colours, roughness, emission) plus procedural oak, fabric and triplanar image textures.",
41757
+ features: [
41758
+ "photoreal",
41759
+ "render",
41760
+ "materials"
41761
+ ]
41762
+ },
41693
41763
  {
41694
41764
  id: "2026-10-21-photoreal-focus-dist",
41695
41765
  version: "0.10.0",
@@ -41715,6 +41785,20 @@ var init_CHANGELOG = __esm({
41715
41785
  "render"
41716
41786
  ]
41717
41787
  },
41788
+ {
41789
+ id: "2026-10-21-mac-welcome",
41790
+ version: "0.10.0",
41791
+ date: "2026-10-21",
41792
+ category: "feat",
41793
+ title: "Mac app welcome window with samples and a loon tutorial",
41794
+ summary: "First launch opens a welcome window with four sample projects bundled in the app and a short tutorial, \u201Cyour first part in loon\u201D. Help \u25B8 Welcome to vcad reopens it.",
41795
+ features: [
41796
+ "desktop",
41797
+ "mac",
41798
+ "onboarding",
41799
+ "loon"
41800
+ ]
41801
+ },
41718
41802
  {
41719
41803
  id: "2026-10-21-mac-sim-teardown-race",
41720
41804
  version: "0.10.0",
@@ -41752,6 +41836,19 @@ var init_CHANGELOG = __esm({
41752
41836
  "file-io"
41753
41837
  ]
41754
41838
  },
41839
+ {
41840
+ id: "2026-10-21-mac-loon-loop",
41841
+ version: "0.10.0",
41842
+ date: "2026-10-21",
41843
+ category: "feat",
41844
+ title: "Mac app: loon errors inline, last good model kept",
41845
+ summary: "Open a .loon file or project folder and every save rebuilds; a broken edit shows file:line with Go to Line and keeps the last good model on screen. Module edits rebuild too.",
41846
+ features: [
41847
+ "desktop",
41848
+ "mac",
41849
+ "loon"
41850
+ ]
41851
+ },
41755
41852
  {
41756
41853
  id: "2026-10-21-mac-labs-toggle",
41757
41854
  version: "0.10.0",
@@ -41804,6 +41901,19 @@ var init_CHANGELOG = __esm({
41804
41901
  "cli"
41805
41902
  ]
41806
41903
  },
41904
+ {
41905
+ id: "2026-10-21-incremental-eval-hosts",
41906
+ version: "0.10.0",
41907
+ date: "2026-10-21",
41908
+ category: "perf",
41909
+ title: "Parameter scrubs re-evaluate only what changed",
41910
+ summary: "The Mac app and web eval worker keep an incremental evaluation session per document, so scrubbing a parameter rebuilds only the features downstream of it.",
41911
+ features: [
41912
+ "engine",
41913
+ "evaluation",
41914
+ "performance"
41915
+ ]
41916
+ },
41807
41917
  {
41808
41918
  id: "2026-10-21-gpu-photoreal-limits",
41809
41919
  version: "0.10.0",
@@ -87061,8 +87171,8 @@ var init_server3 = __esm({
87061
87171
  init_order_feed();
87062
87172
  init_animate();
87063
87173
  PKG_VERSION = (() => {
87064
- if ("0.10.0-main.132") {
87065
- return "0.10.0-main.132";
87174
+ if ("0.10.0-main.134") {
87175
+ return "0.10.0-main.134";
87066
87176
  }
87067
87177
  try {
87068
87178
  const req = createRequire2(import.meta.url);
@@ -87071,8 +87181,8 @@ var init_server3 = __esm({
87071
87181
  return "0.0.0";
87072
87182
  }
87073
87183
  })();
87074
- BUILD_SHA = "362c46b798588ed58f200c9d529b3d11b2b2ff73";
87075
- BUILD_TIME = "2026-10-21T17:31:51.205Z";
87184
+ BUILD_SHA = "50d4e0c1c282745ef88e456dca033ceabdee9c31";
87185
+ BUILD_TIME = "2026-10-21T17:58:04.042Z";
87076
87186
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
87077
87187
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
87078
87188
  INSTANCE_ID = randomUUID7().slice(0, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.10.0-main.132",
3
+ "version": "0.10.0-main.134",
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": "362c46b798588ed58f200c9d529b3d11b2b2ff73",
23
- "builtAt": "2026-10-21T17:31:51.205Z"
22
+ "sha": "50d4e0c1c282745ef88e456dca033ceabdee9c31",
23
+ "builtAt": "2026-10-21T17:58:04.042Z"
24
24
  }
25
25
  }