@vcad/mcp 0.9.4-main.13 → 0.9.4-main.14

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 70552964e3760fb5b103235917b00364f6d45763 at 2026-07-24T16:29:07.170Z. Source: https://github.com/ecto/vcad
9
+ Built from 292cf10c5c65aec57d1c40f8bd5bdb0a1222acaf at 2026-07-24T16:37:44.101Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -68,8 +68,11 @@ __export(vcad_kernel_wasm_exports, {
68
68
  atoms_minimize: () => atoms_minimize,
69
69
  atoms_parse_xyz: () => atoms_parse_xyz,
70
70
  atoms_write_xyz: () => atoms_write_xyz,
71
+ buildCalibrationReportJson: () => buildCalibrationReportJson,
71
72
  buildPart: () => buildPart,
72
73
  build_chat_system_prompt: () => build_chat_system_prompt,
74
+ calibrationDefaultTolerance: () => calibrationDefaultTolerance,
75
+ calibrationFingerprintDocument: () => calibrationFingerprintDocument,
73
76
  camDropCutter: () => camDropCutter,
74
77
  camExportGcode: () => camExportGcode,
75
78
  camExportLinuxCnc: () => camExportLinuxCnc,
@@ -155,6 +158,9 @@ __export(vcad_kernel_wasm_exports, {
155
158
  exportKicadProject: () => exportKicadProject,
156
159
  exportKicadSch: () => exportKicadSch,
157
160
  exportProjectedViewToDxf: () => exportProjectedViewToDxf,
161
+ exprEvalAst: () => exprEvalAst,
162
+ exprEvaluate: () => exprEvaluate,
163
+ exprParse: () => exprParse,
158
164
  feaAnalyzeMesh: () => feaAnalyzeMesh,
159
165
  generate3mf: () => generate3mf,
160
166
  generate3mfWithGcode: () => generate3mfWithGcode,
@@ -184,6 +190,7 @@ __export(vcad_kernel_wasm_exports, {
184
190
  nestSheetMetalParts: () => nestSheetMetalParts,
185
191
  nestedSheetMetalDxf: () => nestedSheetMetalDxf,
186
192
  neutronicsSimulate: () => neutronicsSimulate,
193
+ noteToHz: () => noteToHz,
187
194
  offsetSectionMesh: () => offsetSectionMesh,
188
195
  op_chamfer: () => op_chamfer,
189
196
  op_circular_pattern: () => op_circular_pattern,
@@ -218,11 +225,14 @@ __export(vcad_kernel_wasm_exports, {
218
225
  render_svg_view: () => render_svg_view,
219
226
  render_svg_view_highlight: () => render_svg_view_highlight,
220
227
  render_svg_view_section: () => render_svg_view_section,
228
+ resolveDocumentJson: () => resolveDocumentJson,
229
+ resolveParametersJson: () => resolveParametersJson,
221
230
  sample_timeline_sequence: () => sample_timeline_sequence,
222
231
  sample_timeline_track: () => sample_timeline_track,
223
232
  sectionMesh: () => sectionMesh,
224
233
  sheetMetalFoldedStep: () => sheetMetalFoldedStep,
225
234
  sheetMetalSequence: () => sheetMetalSequence,
235
+ simulateStrikeKernel: () => simulateStrikeKernel,
226
236
  sketchCircleSegments: () => sketchCircleSegments,
227
237
  sketchHitTest: () => sketchHitTest,
228
238
  sketchPlaneBasis: () => sketchPlaneBasis,
@@ -428,6 +438,31 @@ function atoms_write_xyz(molecule_json) {
428
438
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
429
439
  }
430
440
  }
441
+ function buildCalibrationReportJson(prediction_json, measurements_json, options_json) {
442
+ let deferred5_0;
443
+ let deferred5_1;
444
+ try {
445
+ const ptr0 = passStringToWasm0(prediction_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
446
+ const len0 = WASM_VECTOR_LEN;
447
+ const ptr1 = passStringToWasm0(measurements_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
448
+ const len1 = WASM_VECTOR_LEN;
449
+ const ptr2 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
450
+ const len2 = WASM_VECTOR_LEN;
451
+ const ret = wasm.buildCalibrationReportJson(ptr0, len0, ptr1, len1, ptr2, len2);
452
+ var ptr4 = ret[0];
453
+ var len4 = ret[1];
454
+ if (ret[3]) {
455
+ ptr4 = 0;
456
+ len4 = 0;
457
+ throw takeFromExternrefTable0(ret[2]);
458
+ }
459
+ deferred5_0 = ptr4;
460
+ deferred5_1 = len4;
461
+ return getStringFromWasm0(ptr4, len4);
462
+ } finally {
463
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
464
+ }
465
+ }
431
466
  function buildPart(path, params_json) {
432
467
  let deferred4_0;
433
468
  let deferred4_1;
@@ -467,6 +502,36 @@ function build_chat_system_prompt(parts_json, selection_json) {
467
502
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
468
503
  }
469
504
  }
505
+ function calibrationDefaultTolerance(kind, predicted) {
506
+ const ptr0 = passStringToWasm0(kind, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
507
+ const len0 = WASM_VECTOR_LEN;
508
+ const ret = wasm.calibrationDefaultTolerance(ptr0, len0, predicted);
509
+ if (ret[2]) {
510
+ throw takeFromExternrefTable0(ret[1]);
511
+ }
512
+ return ret[0];
513
+ }
514
+ function calibrationFingerprintDocument(doc_json) {
515
+ let deferred3_0;
516
+ let deferred3_1;
517
+ try {
518
+ const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
519
+ const len0 = WASM_VECTOR_LEN;
520
+ const ret = wasm.calibrationFingerprintDocument(ptr0, len0);
521
+ var ptr2 = ret[0];
522
+ var len2 = ret[1];
523
+ if (ret[3]) {
524
+ ptr2 = 0;
525
+ len2 = 0;
526
+ throw takeFromExternrefTable0(ret[2]);
527
+ }
528
+ deferred3_0 = ptr2;
529
+ deferred3_1 = len2;
530
+ return getStringFromWasm0(ptr2, len2);
531
+ } finally {
532
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
533
+ }
534
+ }
470
535
  function camDropCutter(vertices_json, indices_json, tool_json, bounds_json, resolution) {
471
536
  let deferred6_0;
472
537
  let deferred6_1;
@@ -1548,6 +1613,31 @@ function exportProjectedViewToDxf(view_json) {
1548
1613
  wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
1549
1614
  return v2;
1550
1615
  }
1616
+ function exprEvalAst(ast, env) {
1617
+ const ret = wasm.exprEvalAst(ast, env);
1618
+ if (ret[2]) {
1619
+ throw takeFromExternrefTable0(ret[1]);
1620
+ }
1621
+ return ret[0];
1622
+ }
1623
+ function exprEvaluate(src, env) {
1624
+ const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1625
+ const len0 = WASM_VECTOR_LEN;
1626
+ const ret = wasm.exprEvaluate(ptr0, len0, env);
1627
+ if (ret[2]) {
1628
+ throw takeFromExternrefTable0(ret[1]);
1629
+ }
1630
+ return ret[0];
1631
+ }
1632
+ function exprParse(src) {
1633
+ const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1634
+ const len0 = WASM_VECTOR_LEN;
1635
+ const ret = wasm.exprParse(ptr0, len0);
1636
+ if (ret[2]) {
1637
+ throw takeFromExternrefTable0(ret[1]);
1638
+ }
1639
+ return takeFromExternrefTable0(ret[0]);
1640
+ }
1551
1641
  function feaAnalyzeMesh(spec_json, options_json, positions, indices) {
1552
1642
  const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1553
1643
  const len0 = WASM_VECTOR_LEN;
@@ -1856,6 +1946,15 @@ function neutronicsSimulate(spec_json, params_json) {
1856
1946
  }
1857
1947
  return takeFromExternrefTable0(ret[0]);
1858
1948
  }
1949
+ function noteToHz(note) {
1950
+ const ptr0 = passStringToWasm0(note, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1951
+ const len0 = WASM_VECTOR_LEN;
1952
+ const ret = wasm.noteToHz(ptr0, len0);
1953
+ if (ret[2]) {
1954
+ throw takeFromExternrefTable0(ret[1]);
1955
+ }
1956
+ return ret[0];
1957
+ }
1859
1958
  function offsetSectionMesh(mesh_js, plane_json, hatch_json) {
1860
1959
  const ptr0 = passStringToWasm0(plane_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1861
1960
  const len0 = WASM_VECTOR_LEN;
@@ -2344,6 +2443,48 @@ function render_svg_view_section(vcad_json, scale, view, section) {
2344
2443
  wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
2345
2444
  }
2346
2445
  }
2446
+ function resolveDocumentJson(doc_json) {
2447
+ let deferred3_0;
2448
+ let deferred3_1;
2449
+ try {
2450
+ const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2451
+ const len0 = WASM_VECTOR_LEN;
2452
+ const ret = wasm.resolveDocumentJson(ptr0, len0);
2453
+ var ptr2 = ret[0];
2454
+ var len2 = ret[1];
2455
+ if (ret[3]) {
2456
+ ptr2 = 0;
2457
+ len2 = 0;
2458
+ throw takeFromExternrefTable0(ret[2]);
2459
+ }
2460
+ deferred3_0 = ptr2;
2461
+ deferred3_1 = len2;
2462
+ return getStringFromWasm0(ptr2, len2);
2463
+ } finally {
2464
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2465
+ }
2466
+ }
2467
+ function resolveParametersJson(params_json) {
2468
+ let deferred3_0;
2469
+ let deferred3_1;
2470
+ try {
2471
+ const ptr0 = passStringToWasm0(params_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2472
+ const len0 = WASM_VECTOR_LEN;
2473
+ const ret = wasm.resolveParametersJson(ptr0, len0);
2474
+ var ptr2 = ret[0];
2475
+ var len2 = ret[1];
2476
+ if (ret[3]) {
2477
+ ptr2 = 0;
2478
+ len2 = 0;
2479
+ throw takeFromExternrefTable0(ret[2]);
2480
+ }
2481
+ deferred3_0 = ptr2;
2482
+ deferred3_1 = len2;
2483
+ return getStringFromWasm0(ptr2, len2);
2484
+ } finally {
2485
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2486
+ }
2487
+ }
2347
2488
  function sample_timeline_sequence(timeline_json) {
2348
2489
  let deferred3_0;
2349
2490
  let deferred3_1;
@@ -2410,6 +2551,27 @@ function sheetMetalSequence(chain_json) {
2410
2551
  wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
2411
2552
  }
2412
2553
  }
2554
+ function simulateStrikeKernel(input_json) {
2555
+ let deferred3_0;
2556
+ let deferred3_1;
2557
+ try {
2558
+ const ptr0 = passStringToWasm0(input_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2559
+ const len0 = WASM_VECTOR_LEN;
2560
+ const ret = wasm.simulateStrikeKernel(ptr0, len0);
2561
+ var ptr2 = ret[0];
2562
+ var len2 = ret[1];
2563
+ if (ret[3]) {
2564
+ ptr2 = 0;
2565
+ len2 = 0;
2566
+ throw takeFromExternrefTable0(ret[2]);
2567
+ }
2568
+ deferred3_0 = ptr2;
2569
+ deferred3_1 = len2;
2570
+ return getStringFromWasm0(ptr2, len2);
2571
+ } finally {
2572
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2573
+ }
2574
+ }
2413
2575
  function sketchCircleSegments(cx, cy, radius, segments) {
2414
2576
  let deferred2_0;
2415
2577
  let deferred2_1;
@@ -2793,6 +2955,12 @@ function __wbg_get_imports() {
2793
2955
  const ret = arg0.WorkerGlobalScope;
2794
2956
  return ret;
2795
2957
  },
2958
+ __wbg___wbindgen_bigint_get_as_i64_8fcf4ce7f1ca72a2: function(arg0, arg1) {
2959
+ const v = arg1;
2960
+ const ret = typeof v === "bigint" ? v : void 0;
2961
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
2962
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
2963
+ },
2796
2964
  __wbg___wbindgen_boolean_get_bbbb1c18aa2f5e25: function(arg0) {
2797
2965
  const v = arg0;
2798
2966
  const ret = typeof v === "boolean" ? v : void 0;
@@ -2809,6 +2977,10 @@ function __wbg_get_imports() {
2809
2977
  const ret = arg0 in arg1;
2810
2978
  return ret;
2811
2979
  },
2980
+ __wbg___wbindgen_is_bigint_31b12575b56f32fc: function(arg0) {
2981
+ const ret = typeof arg0 === "bigint";
2982
+ return ret;
2983
+ },
2812
2984
  __wbg___wbindgen_is_function_0095a73b8b156f76: function(arg0) {
2813
2985
  const ret = typeof arg0 === "function";
2814
2986
  return ret;
@@ -2830,6 +3002,10 @@ function __wbg_get_imports() {
2830
3002
  const ret = arg0 === void 0;
2831
3003
  return ret;
2832
3004
  },
3005
+ __wbg___wbindgen_jsval_eq_11888390b0186270: function(arg0, arg1) {
3006
+ const ret = arg0 === arg1;
3007
+ return ret;
3008
+ },
2833
3009
  __wbg___wbindgen_jsval_loose_eq_9dd77d8cd6671811: function(arg0, arg1) {
2834
3010
  const ret = arg0 == arg1;
2835
3011
  return ret;
@@ -3385,6 +3561,10 @@ function __wbg_get_imports() {
3385
3561
  __wbg_end_6f776519f1faa582: function(arg0) {
3386
3562
  arg0.end();
3387
3563
  },
3564
+ __wbg_entries_58c7934c745daac7: function(arg0) {
3565
+ const ret = Object.entries(arg0);
3566
+ return ret;
3567
+ },
3388
3568
  __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
3389
3569
  let deferred0_0;
3390
3570
  let deferred0_1;
@@ -3730,6 +3910,16 @@ function __wbg_get_imports() {
3730
3910
  const ret = result;
3731
3911
  return ret;
3732
3912
  },
3913
+ __wbg_instanceof_Map_53af74335dec57f4: function(arg0) {
3914
+ let result;
3915
+ try {
3916
+ result = arg0 instanceof Map;
3917
+ } catch (_) {
3918
+ result = false;
3919
+ }
3920
+ const ret = result;
3921
+ return ret;
3922
+ },
3733
3923
  __wbg_instanceof_Object_1c6af87502b733ed: function(arg0) {
3734
3924
  let result;
3735
3925
  try {
@@ -40800,6 +40990,7 @@ var init_part_labels = __esm({
40800
40990
  var init_export_stl = __esm({
40801
40991
  "../core/dist/utils/export-stl.js"() {
40802
40992
  "use strict";
40993
+ init_dist();
40803
40994
  }
40804
40995
  });
40805
40996
 
@@ -40807,6 +40998,7 @@ var init_export_stl = __esm({
40807
40998
  var init_export_gltf = __esm({
40808
40999
  "../core/dist/utils/export-gltf.js"() {
40809
41000
  "use strict";
41001
+ init_dist();
40810
41002
  }
40811
41003
  });
40812
41004
 
@@ -49177,6 +49369,15 @@ var init_loon = __esm({
49177
49369
  });
49178
49370
 
49179
49371
  // src/export/glb.ts
49372
+ function exportKernel() {
49373
+ const mod = getKernelWasmSync();
49374
+ if (!mod) {
49375
+ throw new Error(
49376
+ "kernel WASM not initialized \u2014 await getKernelWasm() before exporting"
49377
+ );
49378
+ }
49379
+ return mod;
49380
+ }
49180
49381
  function buildPartLabels(doc) {
49181
49382
  return doc.roots.filter((entry) => entry.visible !== false).map((entry) => {
49182
49383
  const name = doc.nodes[String(entry.root)]?.name;
@@ -49184,363 +49385,71 @@ function buildPartLabels(doc) {
49184
49385
  });
49185
49386
  }
49186
49387
  function eulerXyzDegToQuat(rotation) {
49187
- const rad = Math.PI / 180;
49188
- const hx = rotation.x * rad / 2;
49189
- const hy = rotation.y * rad / 2;
49190
- const hz = rotation.z * rad / 2;
49191
- const c1 = Math.cos(hx);
49192
- const s1 = Math.sin(hx);
49193
- const c2 = Math.cos(hy);
49194
- const s2 = Math.sin(hy);
49195
- const c3 = Math.cos(hz);
49196
- const s3 = Math.sin(hz);
49197
- return [
49198
- s1 * c2 * c3 - c1 * s2 * s3,
49199
- c1 * s2 * c3 + s1 * c2 * s3,
49200
- c1 * c2 * s3 - s1 * s2 * c3,
49201
- c1 * c2 * c3 + s1 * s2 * s3
49202
- ];
49388
+ const q = exportKernel().eulerXyzDegToQuat(rotation.x, rotation.y, rotation.z);
49389
+ return [q[0], q[1], q[2], q[3]];
49203
49390
  }
49204
49391
  function buildGlb(inputMeshes, name, animation) {
49205
- const materialMap = /* @__PURE__ */ new Map();
49206
- const materials = [];
49207
- const materialIndexFor = (m) => {
49208
- const emissive = m.emissive ?? [0, 0, 0];
49209
- const emissiveStrength = m.emissiveStrength ?? 1;
49210
- const clearcoat = m.clearcoat ?? 0;
49211
- const clearcoatRoughness = m.clearcoatRoughness ?? 0;
49212
- const alpha = m.alpha ?? 1;
49213
- const key = `${m.color[0]},${m.color[1]},${m.color[2]},${m.metallic},${m.roughness},${emissive[0]},${emissive[1]},${emissive[2]},${emissiveStrength},${clearcoat},${clearcoatRoughness},${alpha}`;
49214
- const existing = materialMap.get(key);
49215
- if (existing !== void 0) return existing;
49216
- const idx = materials.length;
49217
- materialMap.set(key, idx);
49218
- materials.push({
49219
- name: m.name.includes(":") ? m.name.split(":")[0] : m.name,
49220
- color: m.color,
49221
- metallic: m.metallic,
49222
- roughness: m.roughness,
49223
- emissive,
49224
- emissiveStrength,
49225
- clearcoat,
49226
- clearcoatRoughness,
49227
- alpha
49228
- });
49229
- return idx;
49392
+ let f32Len = 0;
49393
+ let u32Len = 0;
49394
+ for (const m of inputMeshes) {
49395
+ f32Len += m.positions.length;
49396
+ u32Len += m.indices.length;
49397
+ if (m.normals && m.normals.length === m.positions.length) {
49398
+ f32Len += m.normals.length;
49399
+ }
49400
+ }
49401
+ for (const ch of animation?.channels ?? []) {
49402
+ f32Len += ch.times.length + ch.values.length;
49403
+ }
49404
+ const f32Data = new Float32Array(f32Len);
49405
+ const u32Data = new Uint32Array(u32Len);
49406
+ let f32Off = 0;
49407
+ let u32Off = 0;
49408
+ const pushF32 = (data) => {
49409
+ f32Data.set(data, f32Off);
49410
+ const span = [f32Off, data.length];
49411
+ f32Off += data.length;
49412
+ return span;
49230
49413
  };
49231
- if (inputMeshes.length === 0) {
49232
- materials.push({
49233
- ...DEFAULT_MATERIAL,
49234
- emissive: [0, 0, 0],
49235
- emissiveStrength: 1,
49236
- clearcoat: 0,
49237
- clearcoatRoughness: 0,
49238
- alpha: 1
49239
- });
49240
- }
49241
- const bufferChunks = [];
49242
- const bufferViews = [];
49243
- const accessors = [];
49244
- const meshes = [];
49245
- const nodes = [];
49246
- let bufferOffset = 0;
49247
- const meshKeyToIdx = /* @__PURE__ */ new Map();
49248
- for (let inputIdx = 0; inputIdx < inputMeshes.length; inputIdx++) {
49249
- const input = inputMeshes[inputIdx];
49250
- const dedupIdx = input.meshKey !== void 0 ? meshKeyToIdx.get(input.meshKey) : void 0;
49251
- if (dedupIdx !== void 0) {
49252
- nodes.push(makeNode(input, dedupIdx));
49253
- continue;
49254
- }
49255
- const positions = f32(input.positions);
49256
- const normals = input.normals && input.normals.length === positions.length ? f32(input.normals) : void 0;
49257
- const vertexCount = positions.length / 3;
49258
- const indexCount = input.indices.length;
49259
- let minX = Infinity, minY = Infinity, minZ = Infinity;
49260
- let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
49261
- for (let i = 0; i < vertexCount; i++) {
49262
- const x = positions[i * 3];
49263
- const y = positions[i * 3 + 1];
49264
- const z = positions[i * 3 + 2];
49265
- minX = Math.min(minX, x);
49266
- minY = Math.min(minY, y);
49267
- minZ = Math.min(minZ, z);
49268
- maxX = Math.max(maxX, x);
49269
- maxY = Math.max(maxY, y);
49270
- maxZ = Math.max(maxZ, z);
49271
- }
49272
- const indicesBytes = new Uint8Array(indexCount * 4);
49273
- const indicesView = new DataView(indicesBytes.buffer);
49274
- for (let i = 0; i < indexCount; i++) {
49275
- indicesView.setUint32(i * 4, input.indices[i], true);
49276
- }
49277
- const indicesPadded = padTo4(indicesBytes);
49278
- bufferChunks.push(indicesPadded);
49279
- const indicesBvIdx = bufferViews.length;
49280
- bufferViews.push({
49281
- buffer: 0,
49282
- byteOffset: bufferOffset,
49283
- byteLength: indexCount * 4,
49284
- target: 34963
49285
- // ELEMENT_ARRAY_BUFFER
49286
- });
49287
- bufferOffset += indicesPadded.length;
49288
- const indicesAccIdx = accessors.length;
49289
- accessors.push({
49290
- bufferView: indicesBvIdx,
49291
- componentType: 5125,
49292
- // UNSIGNED_INT
49293
- count: indexCount,
49294
- type: "SCALAR"
49295
- });
49296
- const positionsBytes = new Uint8Array(
49297
- positions.buffer.slice(
49298
- positions.byteOffset,
49299
- positions.byteOffset + vertexCount * 12
49300
- )
49301
- );
49302
- const positionsPadded = padTo4(positionsBytes);
49303
- bufferChunks.push(positionsPadded);
49304
- const positionsBvIdx = bufferViews.length;
49305
- bufferViews.push({
49306
- buffer: 0,
49307
- byteOffset: bufferOffset,
49308
- byteLength: vertexCount * 12,
49309
- target: 34962
49310
- // ARRAY_BUFFER
49311
- });
49312
- bufferOffset += positionsPadded.length;
49313
- const positionsAccIdx = accessors.length;
49314
- accessors.push({
49315
- bufferView: positionsBvIdx,
49316
- componentType: 5126,
49317
- // FLOAT
49318
- count: vertexCount,
49319
- type: "VEC3",
49320
- min: [minX, minY, minZ],
49321
- max: [maxX, maxY, maxZ]
49322
- });
49323
- const attributes = {
49324
- POSITION: positionsAccIdx
49325
- };
49326
- if (normals) {
49327
- const normalsBytes = new Uint8Array(
49328
- normals.buffer.slice(
49329
- normals.byteOffset,
49330
- normals.byteOffset + vertexCount * 12
49331
- )
49332
- );
49333
- const normalsPadded = padTo4(normalsBytes);
49334
- bufferChunks.push(normalsPadded);
49335
- const normalsBvIdx = bufferViews.length;
49336
- bufferViews.push({
49337
- buffer: 0,
49338
- byteOffset: bufferOffset,
49339
- byteLength: vertexCount * 12,
49340
- target: 34962
49341
- // ARRAY_BUFFER
49342
- });
49343
- bufferOffset += normalsPadded.length;
49344
- const normalsAccIdx = accessors.length;
49345
- accessors.push({
49346
- bufferView: normalsBvIdx,
49347
- componentType: 5126,
49348
- // FLOAT
49349
- count: vertexCount,
49350
- type: "VEC3"
49351
- });
49352
- attributes.NORMAL = normalsAccIdx;
49353
- }
49354
- const meshIdx = meshes.length;
49355
- meshes.push({
49356
- name: `mesh_${meshIdx}`,
49357
- primitives: [
49358
- {
49359
- attributes,
49360
- indices: indicesAccIdx,
49361
- material: materialIndexFor(input)
49362
- }
49363
- ]
49364
- });
49365
- if (input.meshKey !== void 0) meshKeyToIdx.set(input.meshKey, meshIdx);
49366
- nodes.push(makeNode(input, meshIdx));
49367
- }
49368
- let sceneNodeIndices = nodes.map((_, i) => i);
49369
- if (animation?.rootNodeName !== void 0) {
49370
- const rootIdx = nodes.length;
49371
- nodes.push({
49372
- name: animation.rootNodeName,
49373
- children: sceneNodeIndices
49374
- });
49375
- sceneNodeIndices = [rootIdx];
49376
- }
49377
- for (const extra of animation?.extraNodes ?? []) {
49378
- const idx = nodes.length;
49379
- nodes.push({ name: extra });
49380
- sceneNodeIndices = [...sceneNodeIndices, idx];
49381
- }
49382
- let animationsJson;
49383
- if (animation && animation.channels.length > 0) {
49384
- const nodeIndexByName = /* @__PURE__ */ new Map();
49385
- for (let i = 0; i < nodes.length; i++) {
49386
- nodeIndexByName.set(nodes[i].name, i);
49387
- }
49388
- const writeF32Accessor = (data, type, withMinMax) => {
49389
- const arr = new Float32Array(data);
49390
- const bytes = new Uint8Array(arr.buffer.slice(0));
49391
- const padded = padTo4(bytes);
49392
- bufferChunks.push(padded);
49393
- const bvIdx = bufferViews.length;
49394
- bufferViews.push({
49395
- buffer: 0,
49396
- byteOffset: bufferOffset,
49397
- byteLength: bytes.length
49398
- });
49399
- bufferOffset += padded.length;
49400
- const components = type === "SCALAR" ? 1 : type === "VEC3" ? 3 : 4;
49401
- const accIdx = accessors.length;
49402
- const acc = {
49403
- bufferView: bvIdx,
49404
- componentType: 5126,
49405
- // FLOAT
49406
- count: data.length / components,
49407
- type
49408
- };
49409
- if (withMinMax) {
49410
- acc.min = [Math.min(...data)];
49411
- acc.max = [Math.max(...data)];
49412
- }
49413
- accessors.push(acc);
49414
- return accIdx;
49415
- };
49416
- const samplers = [];
49417
- const channels = [];
49418
- for (const ch of animation.channels) {
49419
- const nodeIdx = nodeIndexByName.get(ch.nodeName);
49420
- if (nodeIdx === void 0) {
49421
- console.warn(
49422
- `buildGlb: animation channel targets unknown node "${ch.nodeName}" \u2014 skipped`
49423
- );
49424
- continue;
49425
- }
49426
- const inputAcc = writeF32Accessor(ch.times, "SCALAR", true);
49427
- const outputAcc = writeF32Accessor(
49428
- ch.values,
49429
- ch.path === "rotation" ? "VEC4" : "VEC3",
49430
- false
49431
- );
49432
- const samplerIdx = samplers.length;
49433
- samplers.push({
49434
- input: inputAcc,
49435
- output: outputAcc,
49436
- interpolation: ch.interpolation ?? "LINEAR"
49437
- });
49438
- channels.push({
49439
- sampler: samplerIdx,
49440
- target: { node: nodeIdx, path: ch.path }
49441
- });
49442
- }
49443
- if (channels.length > 0) {
49444
- animationsJson = [
49445
- { name: animation.name ?? "timeline", samplers, channels }
49446
- ];
49447
- }
49448
- }
49449
- let usesClearcoat = false;
49450
- let usesEmissiveStrength = false;
49451
- const materialJson = materials.map((m) => {
49452
- const mat = {
49453
- name: m.name,
49454
- pbrMetallicRoughness: {
49455
- baseColorFactor: [...m.color, m.alpha],
49456
- metallicFactor: m.metallic,
49457
- roughnessFactor: m.roughness
49458
- }
49459
- };
49460
- if (m.alpha < 1) {
49461
- mat.alphaMode = "BLEND";
49462
- mat.doubleSided = true;
49463
- }
49464
- if (isEmissive(m.emissive)) {
49465
- mat.emissiveFactor = m.emissive;
49466
- }
49467
- const extensions = {};
49468
- if (m.clearcoat > 0) {
49469
- usesClearcoat = true;
49470
- extensions.KHR_materials_clearcoat = {
49471
- clearcoatFactor: m.clearcoat,
49472
- clearcoatRoughnessFactor: m.clearcoatRoughness
49473
- };
49474
- }
49475
- if (isEmissive(m.emissive) && m.emissiveStrength !== 1) {
49476
- usesEmissiveStrength = true;
49477
- extensions.KHR_materials_emissive_strength = {
49478
- emissiveStrength: m.emissiveStrength
49479
- };
49480
- }
49481
- if (Object.keys(extensions).length > 0) mat.extensions = extensions;
49482
- return mat;
49483
- });
49484
- const extensionsUsed = [];
49485
- if (usesClearcoat) extensionsUsed.push("KHR_materials_clearcoat");
49486
- if (usesEmissiveStrength)
49487
- extensionsUsed.push("KHR_materials_emissive_strength");
49488
- const json = {
49489
- asset: { version: "2.0", generator: "vcad-mcp" },
49490
- scene: 0,
49491
- scenes: [{ name, nodes: sceneNodeIndices }],
49492
- nodes,
49414
+ const pushU32 = (data) => {
49415
+ u32Data.set(data, u32Off);
49416
+ const span = [u32Off, data.length];
49417
+ u32Off += data.length;
49418
+ return span;
49419
+ };
49420
+ const meshes = inputMeshes.map((m) => ({
49421
+ name: m.name,
49422
+ positions: pushF32(m.positions),
49423
+ indices: pushU32(m.indices),
49424
+ normals: m.normals && m.normals.length === m.positions.length ? pushF32(m.normals) : void 0,
49425
+ color: m.color,
49426
+ metallic: m.metallic,
49427
+ roughness: m.roughness,
49428
+ emissive: m.emissive,
49429
+ emissiveStrength: m.emissiveStrength,
49430
+ clearcoat: m.clearcoat,
49431
+ clearcoatRoughness: m.clearcoatRoughness,
49432
+ alpha: m.alpha,
49433
+ transform: m.transform,
49434
+ meshKey: m.meshKey
49435
+ }));
49436
+ const spec = {
49437
+ name,
49493
49438
  meshes,
49494
- materials: materialJson,
49495
- accessors,
49496
- bufferViews,
49497
- buffers: [{ byteLength: bufferOffset }]
49439
+ animation: animation ? {
49440
+ name: animation.name,
49441
+ channels: animation.channels.map((ch) => ({
49442
+ nodeName: ch.nodeName,
49443
+ path: ch.path,
49444
+ times: pushF32(ch.times),
49445
+ values: pushF32(ch.values),
49446
+ interpolation: ch.interpolation
49447
+ })),
49448
+ rootNodeName: animation.rootNodeName,
49449
+ extraNodes: animation.extraNodes
49450
+ } : void 0
49498
49451
  };
49499
- if (extensionsUsed.length > 0) json.extensionsUsed = extensionsUsed;
49500
- if (animationsJson) json.animations = animationsJson;
49501
- const jsonStr = JSON.stringify(json);
49502
- const jsonBytes = new TextEncoder().encode(jsonStr);
49503
- const jsonPadded = padTo4(jsonBytes, 32);
49504
- const binBuffer = new Uint8Array(bufferOffset);
49505
- let binOffset = 0;
49506
- for (const chunk of bufferChunks) {
49507
- binBuffer.set(chunk, binOffset);
49508
- binOffset += chunk.length;
49509
- }
49510
- const totalLength = 12 + 8 + jsonPadded.length + 8 + binBuffer.length;
49511
- const glb = new Uint8Array(totalLength);
49512
- const glbView = new DataView(glb.buffer);
49513
- let offset = 0;
49514
- glb.set(new TextEncoder().encode("glTF"), offset);
49515
- offset += 4;
49516
- glbView.setUint32(offset, 2, true);
49517
- offset += 4;
49518
- glbView.setUint32(offset, totalLength, true);
49519
- offset += 4;
49520
- glbView.setUint32(offset, jsonPadded.length, true);
49521
- offset += 4;
49522
- glbView.setUint32(offset, 1313821514, true);
49523
- offset += 4;
49524
- glb.set(jsonPadded, offset);
49525
- offset += jsonPadded.length;
49526
- glbView.setUint32(offset, binBuffer.length, true);
49527
- offset += 4;
49528
- glbView.setUint32(offset, 5130562, true);
49529
- offset += 4;
49530
- glb.set(binBuffer, offset);
49531
- return glb;
49532
- }
49533
- function makeNode(input, meshIdx) {
49534
- const node = { mesh: meshIdx, name: input.name };
49535
- const t2 = input.transform;
49536
- if (!t2) return node;
49537
- const [tx, ty, tz] = t2.translation;
49538
- if (tx !== 0 || ty !== 0 || tz !== 0) node.translation = t2.translation;
49539
- const [qx, qy, qz, qw] = t2.rotationQuat;
49540
- if (qx !== 0 || qy !== 0 || qz !== 0 || qw !== 1) node.rotation = t2.rotationQuat;
49541
- const [sx, sy, sz] = t2.scale;
49542
- if (sx !== 1 || sy !== 1 || sz !== 1) node.scale = t2.scale;
49543
- return node;
49452
+ return exportKernel().buildGlbBytes(JSON.stringify(spec), f32Data, u32Data);
49544
49453
  }
49545
49454
  function toGlbBytes(scene, name, partLabels) {
49546
49455
  const meshes = scene.parts.map((part, i) => ({
@@ -49554,28 +49463,17 @@ function toGlbBytes(scene, name, partLabels) {
49554
49463
  }));
49555
49464
  return buildGlb(meshes, name);
49556
49465
  }
49557
- function padTo4(bytes, padByte = 0) {
49558
- const paddedLength = bytes.length + 3 & ~3;
49559
- if (paddedLength === bytes.length) return bytes;
49560
- const padded = new Uint8Array(paddedLength);
49561
- padded.set(bytes);
49562
- for (let i = bytes.length; i < paddedLength; i++) {
49563
- padded[i] = padByte;
49564
- }
49565
- return padded;
49566
- }
49567
- var DEFAULT_MATERIAL, isEmissive, f32;
49466
+ var DEFAULT_MATERIAL;
49568
49467
  var init_glb = __esm({
49569
49468
  "src/export/glb.ts"() {
49570
49469
  "use strict";
49470
+ init_dist();
49571
49471
  DEFAULT_MATERIAL = {
49572
49472
  name: "default",
49573
49473
  color: [0.8, 0.8, 0.8],
49574
49474
  metallic: 0.1,
49575
49475
  roughness: 0.5
49576
49476
  };
49577
- isEmissive = (e) => e[0] > 0 || e[1] > 0 || e[2] > 0;
49578
- f32 = (a) => a instanceof Float32Array ? a : new Float32Array(a);
49579
49477
  }
49580
49478
  });
49581
49479
 
@@ -56362,80 +56260,37 @@ var init_parts2 = __esm({
56362
56260
 
56363
56261
  // src/export/stl.ts
56364
56262
  function toStlBytes(scene, name) {
56365
- let totalTriangles = 0;
56263
+ let f32Len = 0;
56264
+ let u32Len = 0;
56366
56265
  for (const part of scene.parts) {
56367
- totalTriangles += part.mesh.indices.length / 3;
56368
- }
56369
- const buffer = new ArrayBuffer(84 + totalTriangles * 50);
56370
- const view = new DataView(buffer);
56371
- const uint8 = new Uint8Array(buffer);
56372
- const header = name.slice(0, 80).padEnd(80, " ");
56373
- for (let i = 0; i < 80; i++) {
56374
- uint8[i] = header.charCodeAt(i);
56375
- }
56376
- view.setUint32(80, totalTriangles, true);
56377
- let offset = 84;
56378
- for (const part of scene.parts) {
56379
- offset = writeMeshTriangles(part.mesh, view, offset);
56380
- }
56381
- return uint8;
56382
- }
56383
- function writeMeshTriangles(mesh, view, offset) {
56384
- const positions = mesh.positions;
56385
- const indices = mesh.indices;
56386
- const numTriangles = indices.length / 3;
56387
- for (let t2 = 0; t2 < numTriangles; t2++) {
56388
- const i0 = indices[t2 * 3];
56389
- const i1 = indices[t2 * 3 + 1];
56390
- const i2 = indices[t2 * 3 + 2];
56391
- const v0x = positions[i0 * 3];
56392
- const v0y = positions[i0 * 3 + 1];
56393
- const v0z = positions[i0 * 3 + 2];
56394
- const v1x = positions[i1 * 3];
56395
- const v1y = positions[i1 * 3 + 1];
56396
- const v1z = positions[i1 * 3 + 2];
56397
- const v2x = positions[i2 * 3];
56398
- const v2y = positions[i2 * 3 + 1];
56399
- const v2z = positions[i2 * 3 + 2];
56400
- const e1x = v1x - v0x;
56401
- const e1y = v1y - v0y;
56402
- const e1z = v1z - v0z;
56403
- const e2x = v2x - v0x;
56404
- const e2y = v2y - v0y;
56405
- const e2z = v2z - v0z;
56406
- let nx = e1y * e2z - e1z * e2y;
56407
- let ny = e1z * e2x - e1x * e2z;
56408
- let nz = e1x * e2y - e1y * e2x;
56409
- const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
56410
- if (len > 1e-10) {
56411
- nx /= len;
56412
- ny /= len;
56413
- nz /= len;
56414
- }
56415
- view.setFloat32(offset, nx, true);
56416
- view.setFloat32(offset + 4, ny, true);
56417
- view.setFloat32(offset + 8, nz, true);
56418
- offset += 12;
56419
- view.setFloat32(offset, v0x, true);
56420
- view.setFloat32(offset + 4, v0y, true);
56421
- view.setFloat32(offset + 8, v0z, true);
56422
- offset += 12;
56423
- view.setFloat32(offset, v1x, true);
56424
- view.setFloat32(offset + 4, v1y, true);
56425
- view.setFloat32(offset + 8, v1z, true);
56426
- offset += 12;
56427
- view.setFloat32(offset, v2x, true);
56428
- view.setFloat32(offset + 4, v2y, true);
56429
- view.setFloat32(offset + 8, v2z, true);
56430
- offset += 12;
56431
- view.setUint16(offset, 0, true);
56432
- offset += 2;
56433
- }
56434
- return offset;
56266
+ f32Len += part.mesh.positions.length;
56267
+ u32Len += part.mesh.indices.length;
56268
+ }
56269
+ const f32Data = new Float32Array(f32Len);
56270
+ const u32Data = new Uint32Array(u32Len);
56271
+ let f32Off = 0;
56272
+ let u32Off = 0;
56273
+ const meshes = scene.parts.map((part) => {
56274
+ f32Data.set(part.mesh.positions, f32Off);
56275
+ u32Data.set(part.mesh.indices, u32Off);
56276
+ const spec = {
56277
+ positions: [f32Off, part.mesh.positions.length],
56278
+ indices: [u32Off, part.mesh.indices.length]
56279
+ };
56280
+ f32Off += part.mesh.positions.length;
56281
+ u32Off += part.mesh.indices.length;
56282
+ return spec;
56283
+ });
56284
+ return exportKernel().buildStlBytes(
56285
+ JSON.stringify({ name, meshes }),
56286
+ f32Data,
56287
+ u32Data
56288
+ );
56435
56289
  }
56436
56290
  var init_stl = __esm({
56437
56291
  "src/export/stl.ts"() {
56438
56292
  "use strict";
56293
+ init_glb();
56439
56294
  }
56440
56295
  });
56441
56296
 
@@ -77903,8 +77758,8 @@ var init_server3 = __esm({
77903
77758
  init_order_feed();
77904
77759
  init_animate();
77905
77760
  PKG_VERSION = (() => {
77906
- if ("0.9.4-main.13") {
77907
- return "0.9.4-main.13";
77761
+ if ("0.9.4-main.14") {
77762
+ return "0.9.4-main.14";
77908
77763
  }
77909
77764
  try {
77910
77765
  const req = createRequire2(import.meta.url);
@@ -77913,8 +77768,8 @@ var init_server3 = __esm({
77913
77768
  return "0.0.0";
77914
77769
  }
77915
77770
  })();
77916
- BUILD_SHA = "70552964e3760fb5b103235917b00364f6d45763";
77917
- BUILD_TIME = "2026-07-24T16:29:07.170Z";
77771
+ BUILD_SHA = "292cf10c5c65aec57d1c40f8bd5bdb0a1222acaf";
77772
+ BUILD_TIME = "2026-07-24T16:37:44.101Z";
77918
77773
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
77919
77774
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
77920
77775
  INSTANCE_ID = randomUUID6().slice(0, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.9.4-main.13",
3
+ "version": "0.9.4-main.14",
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": "70552964e3760fb5b103235917b00364f6d45763",
23
- "builtAt": "2026-07-24T16:29:07.170Z"
22
+ "sha": "292cf10c5c65aec57d1c40f8bd5bdb0a1222acaf",
23
+ "builtAt": "2026-07-24T16:37:44.101Z"
24
24
  }
25
25
  }
Binary file