@vcad/mcp 0.9.4-main.16 → 0.9.4-main.18

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 63c1a040cf3352ca640144ec217f3f96271180c9 at 2026-07-24T17:21:48.535Z. Source: https://github.com/ecto/vcad
9
+ Built from 48276771946e67b08cb31a66d123bdc2d7af926d at 2026-07-24T22:30:13.865Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -151,6 +151,14 @@ __export(vcad_kernel_wasm_exports, {
151
151
  ecadVerifySubstitution: () => ecadVerifySubstitution,
152
152
  emSimulate: () => emSimulate,
153
153
  embroideryDesignToMesh: () => embroideryDesignToMesh,
154
+ enclosure_component_extents: () => enclosure_component_extents,
155
+ enclosure_connectors: () => enclosure_connectors,
156
+ enclosure_derive_board: () => enclosure_derive_board,
157
+ enclosure_features: () => enclosure_features,
158
+ enclosure_fit: () => enclosure_fit,
159
+ enclosure_mounting_holes: () => enclosure_mounting_holes,
160
+ enclosure_outline_aabb: () => enclosure_outline_aabb,
161
+ enclosure_to_world: () => enclosure_to_world,
154
162
  estimatePrintCost: () => estimatePrintCost,
155
163
  estimate_cost_for_process: () => estimate_cost_for_process,
156
164
  eulerXyzDegToQuat: () => eulerXyzDegToQuat,
@@ -190,6 +198,7 @@ __export(vcad_kernel_wasm_exports, {
190
198
  isGpuAvailable: () => isGpuAvailable,
191
199
  isPhysicsAvailable: () => isPhysicsAvailable,
192
200
  isSlicerAvailable: () => isSlicerAvailable,
201
+ latticeGaugeSimulate: () => latticeGaugeSimulate,
193
202
  mesh_clearance: () => mesh_clearance,
194
203
  nestSheetMetalParts: () => nestSheetMetalParts,
195
204
  nestedSheetMetalDxf: () => nestedSheetMetalDxf,
@@ -1530,6 +1539,184 @@ function embroideryDesignToMesh(design_json) {
1530
1539
  }
1531
1540
  return takeFromExternrefTable0(ret[0]);
1532
1541
  }
1542
+ function enclosure_component_extents(meshes_json, pcb_json) {
1543
+ let deferred4_0;
1544
+ let deferred4_1;
1545
+ try {
1546
+ const ptr0 = passStringToWasm0(meshes_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1547
+ const len0 = WASM_VECTOR_LEN;
1548
+ const ptr1 = passStringToWasm0(pcb_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1549
+ const len1 = WASM_VECTOR_LEN;
1550
+ const ret = wasm.enclosure_component_extents(ptr0, len0, ptr1, len1);
1551
+ var ptr3 = ret[0];
1552
+ var len3 = ret[1];
1553
+ if (ret[3]) {
1554
+ ptr3 = 0;
1555
+ len3 = 0;
1556
+ throw takeFromExternrefTable0(ret[2]);
1557
+ }
1558
+ deferred4_0 = ptr3;
1559
+ deferred4_1 = len3;
1560
+ return getStringFromWasm0(ptr3, len3);
1561
+ } finally {
1562
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
1563
+ }
1564
+ }
1565
+ function enclosure_connectors(pcb_json, outline_json) {
1566
+ let deferred4_0;
1567
+ let deferred4_1;
1568
+ try {
1569
+ const ptr0 = passStringToWasm0(pcb_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1570
+ const len0 = WASM_VECTOR_LEN;
1571
+ const ptr1 = passStringToWasm0(outline_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1572
+ const len1 = WASM_VECTOR_LEN;
1573
+ const ret = wasm.enclosure_connectors(ptr0, len0, ptr1, len1);
1574
+ var ptr3 = ret[0];
1575
+ var len3 = ret[1];
1576
+ if (ret[3]) {
1577
+ ptr3 = 0;
1578
+ len3 = 0;
1579
+ throw takeFromExternrefTable0(ret[2]);
1580
+ }
1581
+ deferred4_0 = ptr3;
1582
+ deferred4_1 = len3;
1583
+ return getStringFromWasm0(ptr3, len3);
1584
+ } finally {
1585
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
1586
+ }
1587
+ }
1588
+ function enclosure_derive_board(cavity_json, standoffs_json, options_json) {
1589
+ let deferred5_0;
1590
+ let deferred5_1;
1591
+ try {
1592
+ const ptr0 = passStringToWasm0(cavity_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1593
+ const len0 = WASM_VECTOR_LEN;
1594
+ const ptr1 = passStringToWasm0(standoffs_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1595
+ const len1 = WASM_VECTOR_LEN;
1596
+ const ptr2 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1597
+ const len2 = WASM_VECTOR_LEN;
1598
+ const ret = wasm.enclosure_derive_board(ptr0, len0, ptr1, len1, ptr2, len2);
1599
+ var ptr4 = ret[0];
1600
+ var len4 = ret[1];
1601
+ if (ret[3]) {
1602
+ ptr4 = 0;
1603
+ len4 = 0;
1604
+ throw takeFromExternrefTable0(ret[2]);
1605
+ }
1606
+ deferred5_0 = ptr4;
1607
+ deferred5_1 = len4;
1608
+ return getStringFromWasm0(ptr4, len4);
1609
+ } finally {
1610
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
1611
+ }
1612
+ }
1613
+ function enclosure_features(positions, indices) {
1614
+ let deferred4_0;
1615
+ let deferred4_1;
1616
+ try {
1617
+ const ptr0 = passArrayF64ToWasm0(positions, wasm.__wbindgen_malloc);
1618
+ const len0 = WASM_VECTOR_LEN;
1619
+ const ptr1 = passArray32ToWasm0(indices, wasm.__wbindgen_malloc);
1620
+ const len1 = WASM_VECTOR_LEN;
1621
+ const ret = wasm.enclosure_features(ptr0, len0, ptr1, len1);
1622
+ var ptr3 = ret[0];
1623
+ var len3 = ret[1];
1624
+ if (ret[3]) {
1625
+ ptr3 = 0;
1626
+ len3 = 0;
1627
+ throw takeFromExternrefTable0(ret[2]);
1628
+ }
1629
+ deferred4_0 = ptr3;
1630
+ deferred4_1 = len3;
1631
+ return getStringFromWasm0(ptr3, len3);
1632
+ } finally {
1633
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
1634
+ }
1635
+ }
1636
+ function enclosure_fit(input_json) {
1637
+ let deferred3_0;
1638
+ let deferred3_1;
1639
+ try {
1640
+ const ptr0 = passStringToWasm0(input_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1641
+ const len0 = WASM_VECTOR_LEN;
1642
+ const ret = wasm.enclosure_fit(ptr0, len0);
1643
+ var ptr2 = ret[0];
1644
+ var len2 = ret[1];
1645
+ if (ret[3]) {
1646
+ ptr2 = 0;
1647
+ len2 = 0;
1648
+ throw takeFromExternrefTable0(ret[2]);
1649
+ }
1650
+ deferred3_0 = ptr2;
1651
+ deferred3_1 = len2;
1652
+ return getStringFromWasm0(ptr2, len2);
1653
+ } finally {
1654
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1655
+ }
1656
+ }
1657
+ function enclosure_mounting_holes(pcb_json) {
1658
+ let deferred3_0;
1659
+ let deferred3_1;
1660
+ try {
1661
+ const ptr0 = passStringToWasm0(pcb_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1662
+ const len0 = WASM_VECTOR_LEN;
1663
+ const ret = wasm.enclosure_mounting_holes(ptr0, len0);
1664
+ var ptr2 = ret[0];
1665
+ var len2 = ret[1];
1666
+ if (ret[3]) {
1667
+ ptr2 = 0;
1668
+ len2 = 0;
1669
+ throw takeFromExternrefTable0(ret[2]);
1670
+ }
1671
+ deferred3_0 = ptr2;
1672
+ deferred3_1 = len2;
1673
+ return getStringFromWasm0(ptr2, len2);
1674
+ } finally {
1675
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1676
+ }
1677
+ }
1678
+ function enclosure_outline_aabb(outline_json) {
1679
+ let deferred3_0;
1680
+ let deferred3_1;
1681
+ try {
1682
+ const ptr0 = passStringToWasm0(outline_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1683
+ const len0 = WASM_VECTOR_LEN;
1684
+ const ret = wasm.enclosure_outline_aabb(ptr0, len0);
1685
+ var ptr2 = ret[0];
1686
+ var len2 = ret[1];
1687
+ if (ret[3]) {
1688
+ ptr2 = 0;
1689
+ len2 = 0;
1690
+ throw takeFromExternrefTable0(ret[2]);
1691
+ }
1692
+ deferred3_0 = ptr2;
1693
+ deferred3_1 = len2;
1694
+ return getStringFromWasm0(ptr2, len2);
1695
+ } finally {
1696
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1697
+ }
1698
+ }
1699
+ function enclosure_to_world(x, y, z, placement_json) {
1700
+ let deferred3_0;
1701
+ let deferred3_1;
1702
+ try {
1703
+ const ptr0 = passStringToWasm0(placement_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1704
+ const len0 = WASM_VECTOR_LEN;
1705
+ const ret = wasm.enclosure_to_world(x, y, z, ptr0, len0);
1706
+ var ptr2 = ret[0];
1707
+ var len2 = ret[1];
1708
+ if (ret[3]) {
1709
+ ptr2 = 0;
1710
+ len2 = 0;
1711
+ throw takeFromExternrefTable0(ret[2]);
1712
+ }
1713
+ deferred3_0 = ptr2;
1714
+ deferred3_1 = len2;
1715
+ return getStringFromWasm0(ptr2, len2);
1716
+ } finally {
1717
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1718
+ }
1719
+ }
1533
1720
  function estimatePrintCost(volume_mm3, infill_density, wall_count, line_width, material_name) {
1534
1721
  const ptr0 = passStringToWasm0(material_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1535
1722
  const len0 = WASM_VECTOR_LEN;
@@ -1940,6 +2127,15 @@ function isSlicerAvailable() {
1940
2127
  const ret = wasm.isSlicerAvailable();
1941
2128
  return ret !== 0;
1942
2129
  }
2130
+ function latticeGaugeSimulate(spec_json) {
2131
+ const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2132
+ const len0 = WASM_VECTOR_LEN;
2133
+ const ret = wasm.latticeGaugeSimulate(ptr0, len0);
2134
+ if (ret[2]) {
2135
+ throw takeFromExternrefTable0(ret[1]);
2136
+ }
2137
+ return takeFromExternrefTable0(ret[0]);
2138
+ }
1943
2139
  function mesh_clearance(positions_a, indices_a, positions_b, indices_b) {
1944
2140
  const ptr0 = passArrayF32ToWasm0(positions_a, wasm.__wbindgen_malloc);
1945
2141
  const len0 = WASM_VECTOR_LEN;
@@ -11269,6 +11465,7 @@ var init_dist = __esm({
11269
11465
  toleranceAnalyze: wasmModule7.toleranceAnalyze,
11270
11466
  thermalSolve: wasmModule7.thermalSolve,
11271
11467
  thermalSolveTransient: wasmModule7.thermalSolveTransient,
11468
+ simulateFlow: wasmModule7.simulateFlow,
11272
11469
  documentDiff: wasmModule7.documentDiff,
11273
11470
  documentDiffApply: wasmModule7.documentDiffApply,
11274
11471
  documentMerge: wasmModule7.documentMerge,
@@ -11283,6 +11480,7 @@ var init_dist = __esm({
11283
11480
  antennaAnalyze: wasmModule7.antennaAnalyze,
11284
11481
  photonicsSimulate: wasmModule7.photonicsSimulate,
11285
11482
  neutronicsSimulate: wasmModule7.neutronicsSimulate,
11483
+ latticeGaugeSimulate: wasmModule7.latticeGaugeSimulate,
11286
11484
  analyzeStaticsBox: wasmModule7.analyzeStaticsBox,
11287
11485
  analyzeStaticsMesh: wasmModule7.analyzeStaticsMesh
11288
11486
  }, compiledWasmModule);
@@ -11546,6 +11744,20 @@ var init_dist = __esm({
11546
11744
  }
11547
11745
  return fn(specJson, transientJson, paramsJson, optionsJson);
11548
11746
  }
11747
+ /**
11748
+ * Steady laminar flow solve (D3Q19 BGK lattice Boltzmann): pressure
11749
+ * drop, flow rates, mass audit, optional thermal pickup, and predicted
11750
+ * receipt claims. Per-voxel fields are only returned when
11751
+ * `includeFields` is true. Inputs are JSON strings (FlowSpec, options);
11752
+ * see `vcad-kernel-flow`.
11753
+ */
11754
+ simulateFlow(specJson, optionsJson, includeFields) {
11755
+ const fn = this.kernel.simulateFlow;
11756
+ if (typeof fn !== "function") {
11757
+ throw new Error("simulateFlow is not exported by this kernel WASM build \u2014 rebuild packages/kernel-wasm");
11758
+ }
11759
+ return fn(specJson, optionsJson, includeFields);
11760
+ }
11549
11761
  circuitFn(name) {
11550
11762
  const fn = this.kernel[name];
11551
11763
  if (typeof fn !== "function") {
@@ -11643,6 +11855,19 @@ var init_dist = __esm({
11643
11855
  }
11644
11856
  return fn(specJson, paramsJson);
11645
11857
  }
11858
+ /**
11859
+ * Lattice gauge theory Monte Carlo (quenched SU(2)/SU(3) Wilson
11860
+ * action): plaquette, Wilson loops, string tension, Polyakov order
11861
+ * parameter, flux-tube profile, field snapshots — jackknife errors
11862
+ * throughout; see `vcad-kernel-qcd`.
11863
+ */
11864
+ latticeGaugeSimulate(specJson) {
11865
+ const fn = this.kernel.latticeGaugeSimulate;
11866
+ if (typeof fn !== "function") {
11867
+ throw new Error("latticeGaugeSimulate is not exported by this kernel WASM build \u2014 rebuild packages/kernel-wasm");
11868
+ }
11869
+ return fn(specJson);
11870
+ }
11646
11871
  topologyOptimizeBox(min, max, spec) {
11647
11872
  const fn = this.kernel.topologyOptimizeBox;
11648
11873
  if (typeof fn !== "function") {
@@ -40609,6 +40834,37 @@ var init_CHANGELOG = __esm({
40609
40834
  "validate_for_fab"
40610
40835
  ]
40611
40836
  },
40837
+ {
40838
+ id: "2026-07-24-lattice-gauge-mcp",
40839
+ version: "0.9.4",
40840
+ date: "2026-07-24",
40841
+ category: "feat",
40842
+ title: "Lattice gauge theory simulation",
40843
+ summary: "New simulate_lattice_gauge tool: quenched SU(2)/SU(3) Monte Carlo \u2014 confinement, string tension, deconfinement, flux tubes and instantons, with jackknife error bars on every number.",
40844
+ features: [
40845
+ "simulation",
40846
+ "physics"
40847
+ ],
40848
+ mcpTools: [
40849
+ "simulate_lattice_gauge"
40850
+ ]
40851
+ },
40852
+ {
40853
+ id: "2026-07-24-flow-cfd-lbm",
40854
+ version: "0.9.4",
40855
+ date: "2026-07-24",
40856
+ category: "feat",
40857
+ title: "Laminar CFD: lattice-Boltzmann flow solver",
40858
+ summary: "New simulate_flow tool: steady laminar D3Q19 LBM on a voxel grid with pressure drop, flow rates, mass audit, thermal pickup, and predicted vcad.flow-claims/1 receipts.",
40859
+ features: [
40860
+ "flow",
40861
+ "cfd",
40862
+ "simulation"
40863
+ ],
40864
+ mcpTools: [
40865
+ "simulate_flow"
40866
+ ]
40867
+ },
40612
40868
  {
40613
40869
  id: "2026-07-23-router-post-route-legalization",
40614
40870
  version: "0.9.4",
@@ -51632,11 +51888,16 @@ var init_tool_metadata = __esm({
51632
51888
  simulate_photonics: { title: "Simulate Photonics", annotations: RO },
51633
51889
  analyze_antenna: { title: "Analyze Antenna", annotations: RO },
51634
51890
  solve_thermal: { title: "Solve Thermal", annotations: RO },
51891
+ simulate_flow: { title: "Simulate Flow", annotations: RO },
51635
51892
  analyze_structure: { title: "Analyze Structure", annotations: RO },
51636
51893
  simulate_neutron_shield: {
51637
51894
  title: "Simulate Neutron Shield",
51638
51895
  annotations: RO
51639
51896
  },
51897
+ simulate_lattice_gauge: {
51898
+ title: "Simulate Lattice Gauge Theory",
51899
+ annotations: RO
51900
+ },
51640
51901
  analyze_tolerance_stackup: {
51641
51902
  title: "Analyze Tolerance Stackup",
51642
51903
  annotations: RO
@@ -69352,7 +69613,7 @@ var init_thermal = __esm({
69352
69613
  }
69353
69614
  });
69354
69615
 
69355
- // src/tools/circuit.ts
69616
+ // src/tools/flow.ts
69356
69617
  function textResult5(payload) {
69357
69618
  return {
69358
69619
  content: [
@@ -69363,6 +69624,207 @@ function textResult5(payload) {
69363
69624
  ]
69364
69625
  };
69365
69626
  }
69627
+ var vec32, shapeSchema2, flowSpecSchema, toolDefs30;
69628
+ var init_flow = __esm({
69629
+ "src/tools/flow.ts"() {
69630
+ "use strict";
69631
+ init_tool_def();
69632
+ vec32 = {
69633
+ type: "array",
69634
+ minItems: 3,
69635
+ maxItems: 3,
69636
+ items: { type: "number" }
69637
+ };
69638
+ shapeSchema2 = {
69639
+ type: "object",
69640
+ required: ["type"],
69641
+ description: 'Region shape: `{"type":"Box","min_mm":[..],"size_mm":[..]}` or `{"type":"Tube","axis":"Z","center_mm":[..2],"span_mm":[..2],"outer_radius_mm":..,"inner_radius_mm":..}`.',
69642
+ properties: {
69643
+ type: { type: "string", enum: ["Box", "Tube"] },
69644
+ min_mm: vec32,
69645
+ size_mm: vec32,
69646
+ axis: { type: "string", enum: ["X", "Y", "Z"] },
69647
+ center_mm: {
69648
+ type: "array",
69649
+ minItems: 2,
69650
+ maxItems: 2,
69651
+ items: { type: "number" }
69652
+ },
69653
+ span_mm: {
69654
+ type: "array",
69655
+ minItems: 2,
69656
+ maxItems: 2,
69657
+ items: { type: "number" }
69658
+ },
69659
+ outer_radius_mm: { type: "number" },
69660
+ inner_radius_mm: { type: "number" }
69661
+ }
69662
+ };
69663
+ flowSpecSchema = {
69664
+ type: "object",
69665
+ required: ["origin_mm", "size_mm", "divisions"],
69666
+ description: "Voxelized flow domain: an axis-aligned box discretized into cubic voxels (`size_mm[a]/divisions[a]` must agree across axes), painted with regions in order (`background` first, then `regions`). Units mm / kg / m / s / Pa / degC.",
69667
+ properties: {
69668
+ origin_mm: vec32,
69669
+ size_mm: vec32,
69670
+ divisions: {
69671
+ type: "array",
69672
+ minItems: 3,
69673
+ maxItems: 3,
69674
+ items: { type: "number" },
69675
+ description: "Voxel counts per axis (voxels must come out cubic; the cost knob)."
69676
+ },
69677
+ background: {
69678
+ type: "string",
69679
+ enum: ["solid", "fluid"],
69680
+ description: "What unpainted voxels are. Default solid."
69681
+ },
69682
+ regions: {
69683
+ type: "array",
69684
+ items: {
69685
+ type: "object",
69686
+ required: ["shape", "role"],
69687
+ properties: {
69688
+ shape: shapeSchema2,
69689
+ role: {
69690
+ type: "string",
69691
+ enum: ["solid", "fluid", "inlet", "outlet"]
69692
+ }
69693
+ }
69694
+ },
69695
+ description: "Painted in order; later regions override earlier ones. Inlet and outlet patches must sit on the domain boundary."
69696
+ },
69697
+ fluid: {
69698
+ type: "object",
69699
+ properties: {
69700
+ density_kg_m3: { type: "number" },
69701
+ viscosity_pa_s: { type: "number" }
69702
+ },
69703
+ description: "Fluid properties. Default water (998, 1.002e-3)."
69704
+ },
69705
+ inlet_velocity_m_s: {
69706
+ ...vec32,
69707
+ description: "Plug-flow inlet velocity vector, m/s."
69708
+ },
69709
+ outlet_gauge_pa: {
69710
+ type: "number",
69711
+ description: "Outlet gauge pressure, Pa. Default 0."
69712
+ },
69713
+ body_force_n_m3: {
69714
+ ...vec32,
69715
+ description: "Volumetric body force, N/m^3 (periodic channel drive; needs `options.u_ref_m_s`)."
69716
+ },
69717
+ periodic: {
69718
+ type: "array",
69719
+ minItems: 3,
69720
+ maxItems: 3,
69721
+ items: { type: "boolean" },
69722
+ description: "Per-axis periodic boundaries."
69723
+ },
69724
+ re_envelope: {
69725
+ type: "number",
69726
+ description: "Reynolds gate: the solve refuses Re above this (laminar only). Default 2300."
69727
+ },
69728
+ thermal: {
69729
+ type: "object",
69730
+ properties: {
69731
+ inlet_temp_c: { type: "number" },
69732
+ initial_temp_c: { type: "number" },
69733
+ wall_temp_c: { type: "number" },
69734
+ diffusivity_m2_s: { type: "number" },
69735
+ heat_capacity_j_kg_k: { type: "number" },
69736
+ buoyancy: {
69737
+ type: "object",
69738
+ properties: {
69739
+ beta_per_k: { type: "number" },
69740
+ t_ref_c: { type: "number" },
69741
+ gravity_m_s2: { type: "number" }
69742
+ }
69743
+ }
69744
+ },
69745
+ description: "Enable the advected temperature field (film-averaged conjugate seam; optional Boussinesq buoyancy, gated at Ra <= 1e8)."
69746
+ },
69747
+ hot_walls: {
69748
+ type: "array",
69749
+ items: {
69750
+ type: "object",
69751
+ required: ["shape", "temp_c"],
69752
+ properties: {
69753
+ shape: shapeSchema2,
69754
+ temp_c: { type: "number" }
69755
+ }
69756
+ },
69757
+ description: "Isothermal wall patches (Dirichlet) for thermal runs, painted over solid voxels adjacent to fluid."
69758
+ }
69759
+ }
69760
+ };
69761
+ toolDefs30 = [
69762
+ {
69763
+ name: "simulate_flow",
69764
+ pack: null,
69765
+ description: 'Steady laminar CFD on a voxel grid: D3Q19 BGK lattice Boltzmann with half-way bounce-back walls, velocity inlets, pressure outlets, and an optional advected temperature field (isothermal walls, Boussinesq buoyancy). Returns pressure drop, inlet/outlet flow rates, the mass-balance audit, max speed, and thermal pickup \u2014 as data plus `vcad.flow-claims/1` and unified-receipt claims. Predictions carry basis "predicted" and roll up Provisional until hardware is measured. Laminar only: fail-closed gates at Re <= 2300, the stable tau window, and Ra <= 1e8; weakly compressible (pressure noise O(Ma^2)); walls are voxel staircases. Per-voxel velocity/pressure/temperature fields are only returned with `include_fields: true` \u2014 they are grid-sized (voxel cap 2M). Steadiness is detected, not assumed: a run that never goes steady is an error, not a result.',
69766
+ inputSchema: {
69767
+ type: "object",
69768
+ required: ["spec"],
69769
+ properties: {
69770
+ spec: flowSpecSchema,
69771
+ options: {
69772
+ type: "object",
69773
+ properties: {
69774
+ u_ref_m_s: {
69775
+ type: "number",
69776
+ description: "Reference speed for unit scaling, m/s. Defaults to the inlet speed; body-force-driven cases must supply it."
69777
+ },
69778
+ max_steps: {
69779
+ type: "number",
69780
+ description: "Step budget before failing. Default 400000."
69781
+ },
69782
+ check_every: {
69783
+ type: "number",
69784
+ description: "Steadiness check interval, steps. Default 200."
69785
+ },
69786
+ steady_tol: {
69787
+ type: "number",
69788
+ description: "Relative L-inf velocity change per check. Default 1e-6."
69789
+ },
69790
+ ramp_steps: {
69791
+ type: "number",
69792
+ description: "Inlet velocity ramp length, steps. Default 1000."
69793
+ }
69794
+ }
69795
+ },
69796
+ include_fields: {
69797
+ type: "boolean",
69798
+ description: "Return the per-voxel velocity/pressure/temperature fields (grid-sized). Default false."
69799
+ }
69800
+ }
69801
+ },
69802
+ handler: (args, ctx) => {
69803
+ const a = args;
69804
+ const out = ctx.engine.simulateFlow(
69805
+ JSON.stringify(a.spec),
69806
+ JSON.stringify(a.options ?? {}),
69807
+ !!a.include_fields
69808
+ );
69809
+ return textResult5(out);
69810
+ },
69811
+ behavior: behavior({})
69812
+ }
69813
+ ];
69814
+ }
69815
+ });
69816
+
69817
+ // src/tools/circuit.ts
69818
+ function textResult6(payload) {
69819
+ return {
69820
+ content: [
69821
+ {
69822
+ type: "text",
69823
+ text: JSON.stringify(payload, null, 2)
69824
+ }
69825
+ ]
69826
+ };
69827
+ }
69366
69828
  function frequencyGrid(ac) {
69367
69829
  const list = ac.frequenciesHz;
69368
69830
  if (Array.isArray(list) && list.length > 0) return list;
@@ -69378,7 +69840,7 @@ function frequencyGrid(ac) {
69378
69840
  }
69379
69841
  return out;
69380
69842
  }
69381
- var deviceSchema, devicesSchema, toolDefs30;
69843
+ var deviceSchema, devicesSchema, toolDefs31;
69382
69844
  var init_circuit = __esm({
69383
69845
  "src/tools/circuit.ts"() {
69384
69846
  "use strict";
@@ -69415,7 +69877,7 @@ var init_circuit = __esm({
69415
69877
  items: deviceSchema,
69416
69878
  description: "Netlist as data. Node ids are dense integers with 0 = ground; the device's index in this array is its device id (used by sourceId / freeDevices / outNode references)."
69417
69879
  };
69418
- toolDefs30 = [
69880
+ toolDefs31 = [
69419
69881
  {
69420
69882
  name: "simulate_circuit",
69421
69883
  pack: null,
@@ -69524,7 +69986,7 @@ var init_circuit = __esm({
69524
69986
  tr.sampleEvery ?? 1
69525
69987
  );
69526
69988
  }
69527
- return textResult5(out);
69989
+ return textResult6(out);
69528
69990
  },
69529
69991
  behavior: behavior({})
69530
69992
  },
@@ -69587,7 +70049,7 @@ var init_circuit = __esm({
69587
70049
  ...typeof a.maxIters === "number" ? { maxIters: a.maxIters } : {}
69588
70050
  };
69589
70051
  const specJson = JSON.stringify({ devices: a.devices });
69590
- return textResult5(ctx.engine.circuitTune(specJson, JSON.stringify(tune)));
70052
+ return textResult6(ctx.engine.circuitTune(specJson, JSON.stringify(tune)));
69591
70053
  },
69592
70054
  behavior: behavior({})
69593
70055
  }
@@ -69596,7 +70058,7 @@ var init_circuit = __esm({
69596
70058
  });
69597
70059
 
69598
70060
  // src/tools/structure.ts
69599
- function textResult6(payload) {
70061
+ function textResult7(payload) {
69600
70062
  return {
69601
70063
  content: [
69602
70064
  {
@@ -69606,7 +70068,7 @@ function textResult6(payload) {
69606
70068
  ]
69607
70069
  };
69608
70070
  }
69609
- var regionSchema2, toolDefs31;
70071
+ var regionSchema2, toolDefs32;
69610
70072
  var init_structure = __esm({
69611
70073
  "src/tools/structure.ts"() {
69612
70074
  "use strict";
@@ -69633,7 +70095,7 @@ var init_structure = __esm({
69633
70095
  }
69634
70096
  }
69635
70097
  };
69636
- toolDefs31 = [
70098
+ toolDefs32 = [
69637
70099
  {
69638
70100
  name: "analyze_structure",
69639
70101
  pack: null,
@@ -69745,7 +70207,7 @@ var init_structure = __esm({
69745
70207
  resolved.mesh.indices
69746
70208
  );
69747
70209
  const solveMs = Math.round(performance.now() - started);
69748
- return textResult6({
70210
+ return textResult7({
69749
70211
  document_id: a.document_id,
69750
70212
  part: resolved.name ?? a.part,
69751
70213
  solve_ms: solveMs,
@@ -69759,7 +70221,7 @@ var init_structure = __esm({
69759
70221
  });
69760
70222
 
69761
70223
  // src/tools/em.ts
69762
- function textResult7(payload) {
70224
+ function textResult8(payload) {
69763
70225
  return {
69764
70226
  content: [
69765
70227
  {
@@ -69769,7 +70231,7 @@ function textResult7(payload) {
69769
70231
  ]
69770
70232
  };
69771
70233
  }
69772
- var paramValue4, rectRegion, bcSchema, electroShape, emSpecSchema, toolDefs32;
70234
+ var paramValue4, rectRegion, bcSchema, electroShape, emSpecSchema, toolDefs33;
69773
70235
  var init_em = __esm({
69774
70236
  "src/tools/em.ts"() {
69775
70237
  "use strict";
@@ -69925,7 +70387,7 @@ var init_em = __esm({
69925
70387
  }
69926
70388
  }
69927
70389
  };
69928
- toolDefs32 = [
70390
+ toolDefs33 = [
69929
70391
  {
69930
70392
  name: "simulate_em",
69931
70393
  pack: null,
@@ -70003,7 +70465,7 @@ var init_em = __esm({
70003
70465
  JSON.stringify(a.parameters ?? {}),
70004
70466
  JSON.stringify(a.options ?? {})
70005
70467
  );
70006
- return textResult7(out);
70468
+ return textResult8(out);
70007
70469
  },
70008
70470
  behavior: behavior({})
70009
70471
  }
@@ -70012,7 +70474,7 @@ var init_em = __esm({
70012
70474
  });
70013
70475
 
70014
70476
  // src/tools/antenna.ts
70015
- function textResult8(payload) {
70477
+ function textResult9(payload) {
70016
70478
  return {
70017
70479
  content: [
70018
70480
  {
@@ -70022,7 +70484,7 @@ function textResult8(payload) {
70022
70484
  ]
70023
70485
  };
70024
70486
  }
70025
- var paramValue5, pointSpec, antennaSpecSchema, toolDefs33;
70487
+ var paramValue5, pointSpec, antennaSpecSchema, toolDefs34;
70026
70488
  var init_antenna = __esm({
70027
70489
  "src/tools/antenna.ts"() {
70028
70490
  "use strict";
@@ -70071,7 +70533,7 @@ var init_antenna = __esm({
70071
70533
  feed_mm: pointSpec
70072
70534
  }
70073
70535
  };
70074
- toolDefs33 = [
70536
+ toolDefs34 = [
70075
70537
  {
70076
70538
  name: "analyze_antenna",
70077
70539
  pack: null,
@@ -70129,7 +70591,7 @@ var init_antenna = __esm({
70129
70591
  JSON.stringify(a.parameters ?? {}),
70130
70592
  JSON.stringify({ band: a.band, ...a.options })
70131
70593
  );
70132
- return textResult8(out);
70594
+ return textResult9(out);
70133
70595
  },
70134
70596
  behavior: behavior({})
70135
70597
  }
@@ -70138,7 +70600,7 @@ var init_antenna = __esm({
70138
70600
  });
70139
70601
 
70140
70602
  // src/tools/photonics.ts
70141
- function textResult9(payload) {
70603
+ function textResult10(payload) {
70142
70604
  return {
70143
70605
  content: [
70144
70606
  {
@@ -70148,7 +70610,7 @@ function textResult9(payload) {
70148
70610
  ]
70149
70611
  };
70150
70612
  }
70151
- var photonicsSpecSchema, toolDefs34;
70613
+ var photonicsSpecSchema, toolDefs35;
70152
70614
  var init_photonics = __esm({
70153
70615
  "src/tools/photonics.ts"() {
70154
70616
  "use strict";
@@ -70234,7 +70696,7 @@ var init_photonics = __esm({
70234
70696
  }
70235
70697
  }
70236
70698
  };
70237
- toolDefs34 = [
70699
+ toolDefs35 = [
70238
70700
  {
70239
70701
  name: "simulate_photonics",
70240
70702
  pack: null,
@@ -70281,7 +70743,7 @@ var init_photonics = __esm({
70281
70743
  JSON.stringify(a.spec),
70282
70744
  JSON.stringify(a.options ?? {})
70283
70745
  );
70284
- return textResult9(out);
70746
+ return textResult10(out);
70285
70747
  },
70286
70748
  behavior: behavior({})
70287
70749
  }
@@ -70290,7 +70752,7 @@ var init_photonics = __esm({
70290
70752
  });
70291
70753
 
70292
70754
  // src/tools/neutronics.ts
70293
- function textResult10(payload) {
70755
+ function textResult11(payload) {
70294
70756
  return {
70295
70757
  content: [
70296
70758
  {
@@ -70300,7 +70762,7 @@ function textResult10(payload) {
70300
70762
  ]
70301
70763
  };
70302
70764
  }
70303
- var paramValue6, shieldSpecSchema, toolDefs35;
70765
+ var paramValue6, shieldSpecSchema, toolDefs36;
70304
70766
  var init_neutronics = __esm({
70305
70767
  "src/tools/neutronics.ts"() {
70306
70768
  "use strict";
@@ -70371,7 +70833,7 @@ var init_neutronics = __esm({
70371
70833
  }
70372
70834
  }
70373
70835
  };
70374
- toolDefs35 = [
70836
+ toolDefs36 = [
70375
70837
  {
70376
70838
  name: "simulate_neutron_shield",
70377
70839
  pack: null,
@@ -70394,7 +70856,129 @@ var init_neutronics = __esm({
70394
70856
  JSON.stringify(a.spec),
70395
70857
  JSON.stringify(a.parameters ?? {})
70396
70858
  );
70397
- return textResult10(out);
70859
+ return textResult11(out);
70860
+ },
70861
+ behavior: behavior({})
70862
+ }
70863
+ ];
70864
+ }
70865
+ });
70866
+
70867
+ // src/tools/qcd.ts
70868
+ function textResult12(payload) {
70869
+ return {
70870
+ content: [
70871
+ {
70872
+ type: "text",
70873
+ text: JSON.stringify(payload, null, 2)
70874
+ }
70875
+ ]
70876
+ };
70877
+ }
70878
+ var simSpecSchema, toolDefs37;
70879
+ var init_qcd = __esm({
70880
+ "src/tools/qcd.ts"() {
70881
+ "use strict";
70882
+ init_tool_def();
70883
+ simSpecSchema = {
70884
+ type: "object",
70885
+ required: [
70886
+ "dims",
70887
+ "beta",
70888
+ "thermalization_sweeps",
70889
+ "measurement_sweeps",
70890
+ "overrelax_per_heatbath",
70891
+ "bin_size",
70892
+ "max_wilson_extent",
70893
+ "seed",
70894
+ "hot_start"
70895
+ ],
70896
+ description: "Lattice simulation spec. Deterministic per seed. Direction 3 is time \u2014 shorten it (e.g. [6,6,6,2]) for finite temperature / deconfinement studies.",
70897
+ properties: {
70898
+ gauge: {
70899
+ type: "string",
70900
+ enum: ["Su2", "Su3"],
70901
+ description: "Gauge group. Su2 (default): quaternion links, exact Kennedy-Pendleton heatbath, fastest. Su3: the real QCD gauge group, Cabibbo-Marinari updates, ~6x cost per link."
70902
+ },
70903
+ dims: {
70904
+ type: "array",
70905
+ items: { type: "number" },
70906
+ minItems: 4,
70907
+ maxItems: 4,
70908
+ description: "Lattice extents [n0,n1,n2,n3], each >= 2. 4^4-8^4 are seconds-scale; 12^4+ is where the cost gate starts to bite."
70909
+ },
70910
+ beta: {
70911
+ type: "number",
70912
+ description: "Inverse coupling beta = 2N/g^2 (Wilson action). SU(2): strong coupling < ~1.5, crossover ~2.2-2.5, weak > 4. SU(3): strong < ~4, deconfinement at N_t=2 near 5.1, weak > 7."
70913
+ },
70914
+ thermalization_sweeps: {
70915
+ type: "number",
70916
+ description: "Discarded equilibration sweeps (>= 1). 50 is typical."
70917
+ },
70918
+ measurement_sweeps: {
70919
+ type: "number",
70920
+ description: "Measured sweeps. Must give >= 2 full jackknife bins (>= 5 bins to mint claims). 100-200 is typical."
70921
+ },
70922
+ overrelax_per_heatbath: {
70923
+ type: "number",
70924
+ description: "Overrelaxation sweeps interleaved per heatbath sweep (1-3 decorrelates much faster per unit work)."
70925
+ },
70926
+ bin_size: {
70927
+ type: "number",
70928
+ description: "Jackknife bin size in measurements (10-20 typical)."
70929
+ },
70930
+ max_wilson_extent: {
70931
+ type: "number",
70932
+ description: "Largest square Wilson loop W(r,t) to measure; 0 = plaquette only. Capped at half the smallest lattice extent."
70933
+ },
70934
+ seed: { type: "number" },
70935
+ hot_start: {
70936
+ type: "boolean",
70937
+ description: "Start from random links instead of cold (identity)."
70938
+ },
70939
+ smear: {
70940
+ type: "object",
70941
+ required: ["alpha", "iterations"],
70942
+ description: "APE spatial smearing applied to a measurement copy before loop observables (lifts the string-tension signal at intermediate coupling; plaquette stays unsmeared). alpha 0.5, 2-3 iterations is customary.",
70943
+ properties: {
70944
+ alpha: { type: "number" },
70945
+ iterations: { type: "number" }
70946
+ }
70947
+ },
70948
+ measure_temporal_loops: {
70949
+ type: "boolean",
70950
+ description: "Also measure spatial x temporal Wilson loops and derive the static quark potential V(r) (+ Cornell fit when >= 3 points resolve)."
70951
+ },
70952
+ measure_polyakov: {
70953
+ type: "boolean",
70954
+ description: "Measure <|L|>, the Polyakov-loop deconfinement order parameter (small = confined, O(1) = deconfined)."
70955
+ },
70956
+ flux_tube: {
70957
+ type: "object",
70958
+ required: ["separation"],
70959
+ description: "Measure the chromoelectric flux-tube profile between a static quark-antiquark pair at this separation (lattice units, spatial axis 0): the connected (Polyakov-pair x action-density) 3D excess field plus the pair correlator whose decay with separation IS confinement. Use a short time axis (N_t 2-4).",
70960
+ properties: { separation: { type: "number" } }
70961
+ },
70962
+ snapshot_cooling: {
70963
+ type: "number",
70964
+ description: "Export a rendering FieldSnapshot (action density per site + complex Polyakov field per spatial site) of the final configuration after this many cooling sweeps (0 = raw vacuum boil; 20-30 = classical lumps). SU(2) runs with cooling >= 1 also report the clover topological charge (near-integer = instanton content)."
70965
+ }
70966
+ }
70967
+ };
70968
+ toolDefs37 = [
70969
+ {
70970
+ name: "simulate_lattice_gauge",
70971
+ pack: null,
70972
+ description: "Lattice gauge theory Monte Carlo (quenched Wilson action, SU(2) or SU(3)): confinement from first principles on a laptop-scale 4D lattice. Returns the average plaquette, Wilson loops, Creutz ratios + static potential + Cornell fit (the string tension sigma*a^2), the Polyakov deconfinement order parameter, and optionally viewport-ready field snapshots (action density, Polyakov field, cooled topological charge) and the static-pair flux-tube profile \u2014 every observable a binned-jackknife mean +- error, bit-deterministic per seed. Fail-closed: starved statistics refuse to mint vcad.qcd-claims/1 (raise measurement_sweeps); logs require loops resolved >= 3-sigma from zero. Honesty bounds ride every claim: quenched (no dynamical fermions), lattice units at fixed coupling (no continuum limit) \u2014 model physics, not physical-QCD numbers. Cost ~ volume x sweeps (x6 for SU(3)); 6^4 with 150 sweeps runs in seconds. Recipes: confinement demo = Su2, [6,6,6,4], beta 2.2, flux_tube {separation 2}; deconfinement = [6,6,6,2], measure_polyakov, beta scan across ~1.88 (Su2) / ~5.1 (Su3); instantons = Su2, beta 2.4, snapshot_cooling 30.",
70973
+ inputSchema: {
70974
+ type: "object",
70975
+ required: ["spec"],
70976
+ properties: { spec: simSpecSchema }
70977
+ },
70978
+ handler: (args, ctx) => {
70979
+ const a = args;
70980
+ const out = ctx.engine.latticeGaugeSimulate(JSON.stringify(a.spec));
70981
+ return textResult12(out);
70398
70982
  },
70399
70983
  behavior: behavior({})
70400
70984
  }
@@ -70523,7 +71107,7 @@ function predictPhysicsTool(args, engine) {
70523
71107
  ]
70524
71108
  };
70525
71109
  }
70526
- var PHYSICS_DOMAIN, ORACLE, TIER_RESOLUTION, regionSchema3, predictPhysicsSchema, round52, toolDefs36;
71110
+ var PHYSICS_DOMAIN, ORACLE, TIER_RESOLUTION, regionSchema3, predictPhysicsSchema, round52, toolDefs38;
70527
71111
  var init_physics2 = __esm({
70528
71112
  "src/tools/physics.ts"() {
70529
71113
  "use strict";
@@ -70636,7 +71220,7 @@ var init_physics2 = __esm({
70636
71220
  }
70637
71221
  };
70638
71222
  round52 = (v) => Number(v.toPrecision(5));
70639
- toolDefs36 = [
71223
+ toolDefs38 = [
70640
71224
  {
70641
71225
  name: "predict_physics",
70642
71226
  pack: null,
@@ -70878,7 +71462,7 @@ function applySetParam(doc, node, path, value) {
70878
71462
  }
70879
71463
  cursor[parts[parts.length - 1]] = value;
70880
71464
  }
70881
- var lastReports, mechanicalProcessEnum, pcbProcessEnum, processEnum, dfmCheckSchema, dfmExplainSchema, dfmSuggestFixSchema, dfmApplyFixSchema, toolDefs37;
71465
+ var lastReports, mechanicalProcessEnum, pcbProcessEnum, processEnum, dfmCheckSchema, dfmExplainSchema, dfmSuggestFixSchema, dfmApplyFixSchema, toolDefs39;
70882
71466
  var init_dfm2 = __esm({
70883
71467
  "src/tools/dfm.ts"() {
70884
71468
  "use strict";
@@ -70975,7 +71559,7 @@ var init_dfm2 = __esm({
70975
71559
  },
70976
71560
  required: ["issue_id"]
70977
71561
  };
70978
- toolDefs37 = [
71562
+ toolDefs39 = [
70979
71563
  {
70980
71564
  name: "dfm_check",
70981
71565
  pack: "dfm",
@@ -71174,7 +71758,7 @@ function renderedOf(engine, doc) {
71174
71758
  "document has no sheet-metal part (evaluation produced no sheetMetal bundle)"
71175
71759
  );
71176
71760
  }
71177
- function textResult11(payload) {
71761
+ function textResult13(payload) {
71178
71762
  return {
71179
71763
  content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
71180
71764
  };
@@ -71216,7 +71800,7 @@ function sheetMetalCreate(input, engine) {
71216
71800
  const errors = rendered.violations.filter(
71217
71801
  (v) => v.severity === "Error"
71218
71802
  ).length;
71219
- return textResult11({
71803
+ return textResult13({
71220
71804
  document_id: documentId,
71221
71805
  model: rendered.model,
71222
71806
  flat: {
@@ -71232,7 +71816,7 @@ function sheetMetalUnfold(input, engine) {
71232
71816
  const doc = getSession(String(a.document_id ?? ""));
71233
71817
  const rendered = renderedOf(engine, doc);
71234
71818
  const includeDxf = a.include_dxf !== false;
71235
- return textResult11({
71819
+ return textResult13({
71236
71820
  flat_pattern: rendered.flatPattern,
71237
71821
  ...includeDxf ? { dxf: rendered.dxf } : {},
71238
71822
  note: "The DXF is a fab-ready merged silhouette: one closed exterior LWPOLYLINE plus hole loops on CUT, DASHED bend centerlines (on the allowance midline) on BEND_UP/BEND_DOWN, and any surface markings as open polylines on ENGRAVE (select the laser-marking/engraving service for that layer in the fab's UI). DXF carries no bend angles \u2014 you enter those in the fab's UI. For zero data entry, export the folded body as STEP instead (export_cad with a .step filename); bends are auto-detected by the shop, but radii/K must match their tooling at model time (use shop_profile in sheet_metal_create)."
@@ -71240,7 +71824,7 @@ function sheetMetalUnfold(input, engine) {
71240
71824
  }
71241
71825
  function sheetMetalMaterials(_input, engine) {
71242
71826
  const materials = engine.getSheetMetalMaterials();
71243
- return textResult11({
71827
+ return textResult13({
71244
71828
  materials,
71245
71829
  note: 'Pass any `name` (e.g. `"al-soft"`, `"steel-mild"`) as the `material` field of `sheet_metal_create`. Aliases like `"aluminum"`, `"stainless"`, `"6061-T6"` also resolve.'
71246
71830
  });
@@ -71249,13 +71833,13 @@ function sheetMetalBendTable(input, engine) {
71249
71833
  const a = input ?? {};
71250
71834
  if (typeof a.shop_profile === "string" && a.shop_profile.length > 0) {
71251
71835
  const catalog = engine.getSheetMetalShopCatalog(a.shop_profile);
71252
- return textResult11({
71836
+ return textResult13({
71253
71837
  catalog,
71254
71838
  note: `Published catalog for ${catalog.name} (retrieved ${catalog.retrieved}). inside_radius_mm is FIXED per material/thickness \u2014 pass shop_profile: "${catalog.id}" to sheet_metal_create and omit per-bend radius to use it.`
71255
71839
  });
71256
71840
  }
71257
71841
  const table = engine.getSheetMetalBendTable();
71258
- return textResult11({
71842
+ return textResult13({
71259
71843
  table,
71260
71844
  note: "K-factors are interpolated by closest R/t for the chosen material. To override K for a specific bend, pass `manual_k` on that flange in sheet_metal_create."
71261
71845
  });
@@ -71277,7 +71861,7 @@ function sheetMetalCheck(input, engine) {
71277
71861
  const errors = result.violations.filter(
71278
71862
  (v) => v.severity === "Error"
71279
71863
  ).length;
71280
- return textResult11({
71864
+ return textResult13({
71281
71865
  shop: result.shop,
71282
71866
  violations: result.violations,
71283
71867
  shop_ready: result.violations.length === 0,
@@ -71329,7 +71913,7 @@ function sheetMetalNest(input, engine) {
71329
71913
  footprints,
71330
71914
  params
71331
71915
  );
71332
- return textResult11({
71916
+ return textResult13({
71333
71917
  parts: footprints,
71334
71918
  result,
71335
71919
  summary: `${result.placements.length} placements across ${result.sheets_used} sheet(s); ${result.utilization_pct.toFixed(1)}% utilization${result.unplaceable.length > 0 ? `; ${result.unplaceable.length} unplaceable (oversize)` : ""}.`
@@ -71342,7 +71926,7 @@ function sheetMetalSequence3(input, engine) {
71342
71926
  if (!steps) {
71343
71927
  throw new Error("document has no sheet-metal part");
71344
71928
  }
71345
- return textResult11({
71929
+ return textResult13({
71346
71930
  count: steps.length,
71347
71931
  steps,
71348
71932
  note: "Form each bend in order. compensated_angle_rad is the angle to dial in on the brake \u2014 springs back to angle_rad once released."
@@ -71365,7 +71949,7 @@ function sheetMetalSuggestFix(input, engine) {
71365
71949
  violation: v,
71366
71950
  fix: suggestFix(v)
71367
71951
  }));
71368
- return textResult11({
71952
+ return textResult13({
71369
71953
  shop: result.shop,
71370
71954
  count: suggestions.length,
71371
71955
  suggestions,
@@ -71468,13 +72052,13 @@ function sheetMetalCost(input, engine) {
71468
72052
  if (!result) {
71469
72053
  throw new Error("document has no sheet-metal part");
71470
72054
  }
71471
- return textResult11({
72055
+ return textResult13({
71472
72056
  breakdown: result.breakdown,
71473
72057
  rates: result.rates,
71474
72058
  summary: `${result.breakdown.currency} ${result.breakdown.total_each.toFixed(2)} each @ qty ${result.breakdown.quantity} (mass ${result.breakdown.mass_kg_each.toFixed(3)} kg, ${result.breakdown.cut_length_m.toFixed(2)} m cut, ${result.breakdown.bends} bend(s)).`
71475
72059
  });
71476
72060
  }
71477
- var sheetMetalCreateSchema, sheetMetalUnfoldSchema, sheetMetalMaterialsSchema, sheetMetalBendTableSchema, sheetMetalCheckSchema, sheetMetalNestSchema, sheetMetalSequenceSchema, sheetMetalSuggestFixSchema, sheetMetalCostSchema, toolDefs38;
72061
+ var sheetMetalCreateSchema, sheetMetalUnfoldSchema, sheetMetalMaterialsSchema, sheetMetalBendTableSchema, sheetMetalCheckSchema, sheetMetalNestSchema, sheetMetalSequenceSchema, sheetMetalSuggestFixSchema, sheetMetalCostSchema, toolDefs40;
71478
72062
  var init_sheet_metal2 = __esm({
71479
72063
  "src/tools/sheet-metal.ts"() {
71480
72064
  "use strict";
@@ -71735,7 +72319,7 @@ var init_sheet_metal2 = __esm({
71735
72319
  },
71736
72320
  required: ["document_id"]
71737
72321
  };
71738
- toolDefs38 = [
72322
+ toolDefs40 = [
71739
72323
  {
71740
72324
  name: "sheet_metal_create",
71741
72325
  pack: "sheet_metal",
@@ -71980,7 +72564,7 @@ function simulateStrike(input, engine) {
71980
72564
  }
71981
72565
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
71982
72566
  }
71983
- var cents, MATERIAL_ALIASES, simulateStrikeSchema, round22, round4, toolDefs39;
72567
+ var cents, MATERIAL_ALIASES, simulateStrikeSchema, round22, round4, toolDefs41;
71984
72568
  var init_acoustics = __esm({
71985
72569
  "src/tools/acoustics.ts"() {
71986
72570
  "use strict";
@@ -72054,7 +72638,7 @@ var init_acoustics = __esm({
72054
72638
  };
72055
72639
  round22 = (x) => Math.round(x * 100) / 100;
72056
72640
  round4 = (x) => Math.round(x * 1e4) / 1e4;
72057
- toolDefs39 = [
72641
+ toolDefs41 = [
72058
72642
  {
72059
72643
  name: "simulate_strike",
72060
72644
  pack: "sheet_metal",
@@ -72205,7 +72789,7 @@ function importStep(input, engine) {
72205
72789
  ]
72206
72790
  };
72207
72791
  }
72208
- var MAX_STEP_BYTES, importStepSchema, toolDefs40;
72792
+ var MAX_STEP_BYTES, importStepSchema, toolDefs42;
72209
72793
  var init_import = __esm({
72210
72794
  "src/tools/import.ts"() {
72211
72795
  "use strict";
@@ -72237,7 +72821,7 @@ var init_import = __esm({
72237
72821
  }
72238
72822
  }
72239
72823
  };
72240
- toolDefs40 = [
72824
+ toolDefs42 = [
72241
72825
  {
72242
72826
  name: "import_step",
72243
72827
  pack: null,
@@ -72365,7 +72949,7 @@ function importEagle(_input) {
72365
72949
  "Eagle (.brd) import is not yet supported. Export your board from Eagle as KiCad (File > Export > KiCad .kicad_pcb) and use import_kicad instead."
72366
72950
  );
72367
72951
  }
72368
- var MAX_PCB_BYTES, importKicadSchema, importEagleSchema, toolDefs41;
72952
+ var MAX_PCB_BYTES, importKicadSchema, importEagleSchema, toolDefs43;
72369
72953
  var init_import_pcb = __esm({
72370
72954
  "src/tools/import-pcb.ts"() {
72371
72955
  "use strict";
@@ -72406,7 +72990,7 @@ var init_import_pcb = __esm({
72406
72990
  }
72407
72991
  }
72408
72992
  };
72409
- toolDefs41 = [
72993
+ toolDefs43 = [
72410
72994
  {
72411
72995
  name: "import_kicad",
72412
72996
  pack: "ecad",
@@ -72502,7 +73086,7 @@ Compressed URL param: ${encoded.length} bytes`
72502
73086
  ]
72503
73087
  };
72504
73088
  }
72505
- var openInBrowserSchema, toolDefs42;
73089
+ var openInBrowserSchema, toolDefs44;
72506
73090
  var init_share = __esm({
72507
73091
  "src/tools/share.ts"() {
72508
73092
  "use strict";
@@ -72526,7 +73110,7 @@ var init_share = __esm({
72526
73110
  }
72527
73111
  }
72528
73112
  };
72529
- toolDefs42 = [
73113
+ toolDefs44 = [
72530
73114
  {
72531
73115
  name: "open_in_browser",
72532
73116
  pack: null,
@@ -72851,7 +73435,7 @@ function batchReset(input) {
72851
73435
  };
72852
73436
  }
72853
73437
  }
72854
- var simulations, MAX_TRAJECTORY, envRecords, batchGroups, createRobotEnvSchema, gymStepSchema, gymResetSchema, gymObserveSchema, gymCloseSchema, batchCreateEnvsSchema, batchStepSchema, batchResetSchema, toolDefs43;
73438
+ var simulations, MAX_TRAJECTORY, envRecords, batchGroups, createRobotEnvSchema, gymStepSchema, gymResetSchema, gymObserveSchema, gymCloseSchema, batchCreateEnvsSchema, batchStepSchema, batchResetSchema, toolDefs45;
72855
73439
  var init_gym = __esm({
72856
73440
  "src/tools/gym.ts"() {
72857
73441
  "use strict";
@@ -73003,7 +73587,7 @@ var init_gym = __esm({
73003
73587
  },
73004
73588
  required: ["batch_id"]
73005
73589
  };
73006
- toolDefs43 = [
73590
+ toolDefs45 = [
73007
73591
  {
73008
73592
  name: "create_robot_env",
73009
73593
  pack: "physics",
@@ -73361,7 +73945,7 @@ async function renderMolecule(input) {
73361
73945
  return fail(err7);
73362
73946
  }
73363
73947
  }
73364
- var loadStructureSchema, inspectMoleculeSchema, configSchema, minimizeEnergySchema, mdRunSchema, designMaterialSchema, homogenizeMaterialSchema, renderMoleculeSchema, CPK, DEFAULT_RADIUS, toolDefs44;
73948
+ var loadStructureSchema, inspectMoleculeSchema, configSchema, minimizeEnergySchema, mdRunSchema, designMaterialSchema, homogenizeMaterialSchema, renderMoleculeSchema, CPK, DEFAULT_RADIUS, toolDefs46;
73365
73949
  var init_atoms2 = __esm({
73366
73950
  "src/tools/atoms.ts"() {
73367
73951
  "use strict";
@@ -73496,7 +74080,7 @@ var init_atoms2 = __esm({
73496
74080
  S: 1.05,
73497
74081
  P: 1.07
73498
74082
  };
73499
- toolDefs44 = [
74083
+ toolDefs46 = [
73500
74084
  {
73501
74085
  name: "load_structure",
73502
74086
  pack: "atoms",
@@ -74704,7 +75288,7 @@ function errorResult(text) {
74704
75288
  isError: true
74705
75289
  };
74706
75290
  }
74707
- var recordSimulationSchema, SVG_SCALE2, MAX_STEPS, MIN_STEPS, DEFAULT_WIDTH_PX2, MIN_WIDTH_PX, MAX_WIDTH_PX, DEFAULT_FPS, MIN_FPS, MAX_FPS, toolDefs45;
75291
+ var recordSimulationSchema, SVG_SCALE2, MAX_STEPS, MIN_STEPS, DEFAULT_WIDTH_PX2, MIN_WIDTH_PX, MAX_WIDTH_PX, DEFAULT_FPS, MIN_FPS, MAX_FPS, toolDefs47;
74708
75292
  var init_record2 = __esm({
74709
75293
  "src/tools/record.ts"() {
74710
75294
  "use strict";
@@ -74768,7 +75352,7 @@ var init_record2 = __esm({
74768
75352
  DEFAULT_FPS = 30;
74769
75353
  MIN_FPS = 1;
74770
75354
  MAX_FPS = 60;
74771
- toolDefs45 = [
75355
+ toolDefs47 = [
74772
75356
  {
74773
75357
  name: "record_simulation",
74774
75358
  pack: "physics",
@@ -74861,7 +75445,7 @@ ${text}`
74861
75445
  ]
74862
75446
  };
74863
75447
  }
74864
- var getChangelogSchema, toolDefs46;
75448
+ var getChangelogSchema, toolDefs48;
74865
75449
  var init_changelog2 = __esm({
74866
75450
  "src/tools/changelog.ts"() {
74867
75451
  "use strict";
@@ -74901,7 +75485,7 @@ var init_changelog2 = __esm({
74901
75485
  }
74902
75486
  }
74903
75487
  };
74904
- toolDefs46 = [
75488
+ toolDefs48 = [
74905
75489
  {
74906
75490
  name: "get_changelog",
74907
75491
  pack: null,
@@ -75050,7 +75634,7 @@ function getSimVersion(input) {
75050
75634
  ]
75051
75635
  };
75052
75636
  }
75053
- var getSimReplaySchema, getSimVersionSchema, toolDefs47;
75637
+ var getSimReplaySchema, getSimVersionSchema, toolDefs49;
75054
75638
  var init_sim_replay = __esm({
75055
75639
  "src/tools/sim-replay.ts"() {
75056
75640
  "use strict";
@@ -75078,7 +75662,7 @@ var init_sim_replay = __esm({
75078
75662
  },
75079
75663
  required: ["env_id"]
75080
75664
  };
75081
- toolDefs47 = [
75665
+ toolDefs49 = [
75082
75666
  {
75083
75667
  name: "get_sim_replay",
75084
75668
  pack: null,
@@ -75197,7 +75781,7 @@ async function getOrderFeed(input, store, user) {
75197
75781
  version: version2
75198
75782
  });
75199
75783
  }
75200
- var toUsd4, getOrderFeedSchema, toolDefs48;
75784
+ var toUsd4, getOrderFeedSchema, toolDefs50;
75201
75785
  var init_order_feed = __esm({
75202
75786
  "src/tools/order-feed.ts"() {
75203
75787
  "use strict";
@@ -75216,7 +75800,7 @@ var init_order_feed = __esm({
75216
75800
  },
75217
75801
  required: ["document_id"]
75218
75802
  };
75219
- toolDefs48 = [
75803
+ toolDefs50 = [
75220
75804
  {
75221
75805
  name: "get_order_feed",
75222
75806
  pack: "fabricate",
@@ -75421,7 +76005,7 @@ ${issues.map((i) => i.track >= 0 ? `track[${i.track}]: ${i.problem}` : i.problem
75421
76005
  note: "Timeline set. Preview with render_sequence, ship with export_video."
75422
76006
  });
75423
76007
  }
75424
- function vec32(v) {
76008
+ function vec33(v) {
75425
76009
  return v ? [v.x, v.y, v.z] : [0, 0, 0];
75426
76010
  }
75427
76011
  function hasParamTracks(timeline) {
@@ -75464,7 +76048,7 @@ function cameraChannels(frames) {
75464
76048
  }
75465
76049
  function explodeDirections(doc, transforms) {
75466
76050
  const ids = [...transforms.keys()];
75467
- const pts = ids.map((id) => vec32(transforms.get(id).translation));
76051
+ const pts = ids.map((id) => vec33(transforms.get(id).translation));
75468
76052
  const c = pts.reduce((acc, p) => [acc[0] + p[0], acc[1] + p[1], acc[2] + p[2]], [0, 0, 0]).map((v) => v / Math.max(1, pts.length));
75469
76053
  let extent = 0;
75470
76054
  for (const p of pts) {
@@ -75522,7 +76106,7 @@ function buildSequenceGlb(doc, timeline, frames, engine) {
75522
76106
  for (const inst of instances) {
75523
76107
  const rec = perInstance.get(inst.instanceId);
75524
76108
  const t2 = world.get(inst.instanceId) ?? inst.transform;
75525
- const translation = vec32(t2?.translation);
76109
+ const translation = vec33(t2?.translation);
75526
76110
  if (frame.explode > 0) {
75527
76111
  const d = dirs.get(inst.instanceId) ?? [0, 0, 0];
75528
76112
  translation[0] += d[0] * frame.explode;
@@ -76118,7 +76702,7 @@ ${issues.map((i) => i.problem).join("\n")}`
76118
76702
  note: "Rollout compiled to the document timeline. Preview with render_sequence, ship with export_video."
76119
76703
  });
76120
76704
  }
76121
- var MAX_FRAMES, MAX_GEO_SAMPLES, MAX_VERIFY_FRAMES, INLINE_GLB_MAX_BASE64, DEFAULT_WIDTH_PX3, MIN_WIDTH_PX2, MAX_WIDTH_PX2, SVG_SCALE3, KEYFRAMES_DESCRIPTION, animateSchema, renderSequenceSchema, CAMERA_NODE, exportVideoSchema, ffmpegAvailable, timelineFromSimulationSchema, toolDefs49;
76705
+ var MAX_FRAMES, MAX_GEO_SAMPLES, MAX_VERIFY_FRAMES, INLINE_GLB_MAX_BASE64, DEFAULT_WIDTH_PX3, MIN_WIDTH_PX2, MAX_WIDTH_PX2, SVG_SCALE3, KEYFRAMES_DESCRIPTION, animateSchema, renderSequenceSchema, CAMERA_NODE, exportVideoSchema, ffmpegAvailable, timelineFromSimulationSchema, toolDefs51;
76122
76706
  var init_animate = __esm({
76123
76707
  "src/tools/animate.ts"() {
76124
76708
  "use strict";
@@ -76270,7 +76854,7 @@ var init_animate = __esm({
76270
76854
  },
76271
76855
  required: ["env_id", "document_id"]
76272
76856
  };
76273
- toolDefs49 = [
76857
+ toolDefs51 = [
76274
76858
  {
76275
76859
  name: "animate",
76276
76860
  pack: null,
@@ -77109,12 +77693,14 @@ var init_server3 = __esm({
77109
77693
  init_particle();
77110
77694
  init_tolerance();
77111
77695
  init_thermal();
77696
+ init_flow();
77112
77697
  init_circuit();
77113
77698
  init_structure();
77114
77699
  init_em();
77115
77700
  init_antenna();
77116
77701
  init_photonics();
77117
77702
  init_neutronics();
77703
+ init_qcd();
77118
77704
  init_physics2();
77119
77705
  init_loon_macros();
77120
77706
  init_dfm2();
@@ -77133,8 +77719,8 @@ var init_server3 = __esm({
77133
77719
  init_order_feed();
77134
77720
  init_animate();
77135
77721
  PKG_VERSION = (() => {
77136
- if ("0.9.4-main.16") {
77137
- return "0.9.4-main.16";
77722
+ if ("0.9.4-main.18") {
77723
+ return "0.9.4-main.18";
77138
77724
  }
77139
77725
  try {
77140
77726
  const req = createRequire2(import.meta.url);
@@ -77143,8 +77729,8 @@ var init_server3 = __esm({
77143
77729
  return "0.0.0";
77144
77730
  }
77145
77731
  })();
77146
- BUILD_SHA = "63c1a040cf3352ca640144ec217f3f96271180c9";
77147
- BUILD_TIME = "2026-07-24T17:21:48.535Z";
77732
+ BUILD_SHA = "48276771946e67b08cb31a66d123bdc2d7af926d";
77733
+ BUILD_TIME = "2026-07-24T22:30:13.865Z";
77148
77734
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
77149
77735
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
77150
77736
  INSTANCE_ID = randomUUID6().slice(0, 8);
@@ -77204,9 +77790,9 @@ var init_server3 = __esm({
77204
77790
  ...toolDefs34,
77205
77791
  ...toolDefs35,
77206
77792
  ...toolDefs36,
77207
- ...toolDefs2,
77208
77793
  ...toolDefs37,
77209
77794
  ...toolDefs38,
77795
+ ...toolDefs2,
77210
77796
  ...toolDefs39,
77211
77797
  ...toolDefs40,
77212
77798
  ...toolDefs41,
@@ -77215,11 +77801,13 @@ var init_server3 = __esm({
77215
77801
  ...toolDefs44,
77216
77802
  ...toolDefs45,
77217
77803
  ...toolDefs46,
77218
- ...toolDefs20,
77219
- ...toolDefs19,
77220
77804
  ...toolDefs47,
77221
77805
  ...toolDefs48,
77222
- ...toolDefs49
77806
+ ...toolDefs20,
77807
+ ...toolDefs19,
77808
+ ...toolDefs49,
77809
+ ...toolDefs50,
77810
+ ...toolDefs51
77223
77811
  ];
77224
77812
  LIST_TOOL_ORDER = [
77225
77813
  // ── Session lifecycle ──────────────────────────────────────
@@ -77288,8 +77876,10 @@ var init_server3 = __esm({
77288
77876
  "simulate_photonics",
77289
77877
  "analyze_antenna",
77290
77878
  "solve_thermal",
77879
+ "simulate_flow",
77291
77880
  "analyze_structure",
77292
77881
  "simulate_neutron_shield",
77882
+ "simulate_lattice_gauge",
77293
77883
  "analyze_tolerance_stackup",
77294
77884
  "simulate_circuit",
77295
77885
  "tune_circuit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.9.4-main.16",
3
+ "version": "0.9.4-main.18",
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": "63c1a040cf3352ca640144ec217f3f96271180c9",
23
- "builtAt": "2026-07-24T17:21:48.535Z"
22
+ "sha": "48276771946e67b08cb31a66d123bdc2d7af926d",
23
+ "builtAt": "2026-07-24T22:30:13.865Z"
24
24
  }
25
25
  }
Binary file