@vcad/mcp 0.10.0-main.131 → 0.10.0-main.133
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 +1 -1
- package/index.mjs +163 -90
- 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
|
|
9
|
+
Built from ed9b701622258f961cdbb3fa2c2430c283a8fc5b at 2026-10-21T17:47:36.984Z. Source: https://github.com/ecto/vcad
|
package/index.mjs
CHANGED
|
@@ -12492,6 +12492,7 @@ var init_dist = __esm({
|
|
|
12492
12492
|
evaluateDocument: wasmModule7.evaluateDocument,
|
|
12493
12493
|
evalVcadSource: wasmModule7.evalVcadSource,
|
|
12494
12494
|
evalVcadSourceWithModules: wasmModule7.evalVcadSourceWithModules,
|
|
12495
|
+
evalLoonDocument: wasmModule7.evalLoonDocument,
|
|
12495
12496
|
evalVcadSourceParametric: wasmModule7.evalVcadSourceParametric,
|
|
12496
12497
|
documentParameterGradient: wasmModule7.documentParameterGradient,
|
|
12497
12498
|
documentSensitivities: wasmModule7.documentSensitivities,
|
|
@@ -13394,6 +13395,22 @@ var init_dist = __esm({
|
|
|
13394
13395
|
* With an empty map this is exactly {@link evalVcadSource}. Returns null
|
|
13395
13396
|
* if the kernel doesn't support module-aware loon evaluation.
|
|
13396
13397
|
*/
|
|
13398
|
+
/**
|
|
13399
|
+
* Evaluate loon source to a session document stamped with its provenance
|
|
13400
|
+
* (`doc.source`: program, modules, origin dir/file, SHA-256), in the kernel.
|
|
13401
|
+
* Null on kernels predating the export.
|
|
13402
|
+
*/
|
|
13403
|
+
evalLoonDocument(source, modules, origin = {}) {
|
|
13404
|
+
if (typeof this.kernel.evalLoonDocument !== "function")
|
|
13405
|
+
return null;
|
|
13406
|
+
const doc = JSON.parse(this.kernel.evalLoonDocument(source, JSON.stringify(modules), origin.baseDir, origin.path));
|
|
13407
|
+
if (doc.source) {
|
|
13408
|
+
doc.source.diverged ??= false;
|
|
13409
|
+
doc.source.diverged_by ??= [];
|
|
13410
|
+
doc.source.modules ??= {};
|
|
13411
|
+
}
|
|
13412
|
+
return doc;
|
|
13413
|
+
}
|
|
13397
13414
|
evalVcadSourceWithModules(source, modules) {
|
|
13398
13415
|
if (!Object.keys(modules).length)
|
|
13399
13416
|
return this.evalVcadSource(source);
|
|
@@ -41647,6 +41664,31 @@ var init_CHANGELOG = __esm({
|
|
|
41647
41664
|
CHANGELOG_default = {
|
|
41648
41665
|
$schema: "./changelog.schema.json",
|
|
41649
41666
|
entries: [
|
|
41667
|
+
{
|
|
41668
|
+
id: "2026-10-21-vcad-printer-cli",
|
|
41669
|
+
version: "0.10.0",
|
|
41670
|
+
date: "2026-10-21",
|
|
41671
|
+
category: "feat",
|
|
41672
|
+
title: "vcad printer: LAN control of a Bambu P1S",
|
|
41673
|
+
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.",
|
|
41674
|
+
features: [
|
|
41675
|
+
"printing",
|
|
41676
|
+
"bambu",
|
|
41677
|
+
"cli"
|
|
41678
|
+
]
|
|
41679
|
+
},
|
|
41680
|
+
{
|
|
41681
|
+
id: "2026-10-21-slicer-first-layer-z",
|
|
41682
|
+
version: "0.10.0",
|
|
41683
|
+
date: "2026-10-21",
|
|
41684
|
+
category: "fix",
|
|
41685
|
+
title: "Slicer: layers print at full height, not half",
|
|
41686
|
+
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.",
|
|
41687
|
+
features: [
|
|
41688
|
+
"printing",
|
|
41689
|
+
"slicer"
|
|
41690
|
+
]
|
|
41691
|
+
},
|
|
41650
41692
|
{
|
|
41651
41693
|
id: "2026-10-21-planar-cap-normals",
|
|
41652
41694
|
version: "0.10.0",
|
|
@@ -41686,6 +41728,32 @@ var init_CHANGELOG = __esm({
|
|
|
41686
41728
|
"cli"
|
|
41687
41729
|
]
|
|
41688
41730
|
},
|
|
41731
|
+
{
|
|
41732
|
+
id: "2026-10-21-photoreal-cyclorama",
|
|
41733
|
+
version: "0.10.0",
|
|
41734
|
+
date: "2026-10-21",
|
|
41735
|
+
category: "feat",
|
|
41736
|
+
title: "Seamless cyclorama backdrop for photoreal renders",
|
|
41737
|
+
summary: "--backdrop cyclorama (vcad render --cyclorama) puts the subject on a matte floor that curves into a back wall, with no horizon line or edge in frame.",
|
|
41738
|
+
features: [
|
|
41739
|
+
"photoreal",
|
|
41740
|
+
"render"
|
|
41741
|
+
]
|
|
41742
|
+
},
|
|
41743
|
+
{
|
|
41744
|
+
id: "2026-10-21-mac-welcome",
|
|
41745
|
+
version: "0.10.0",
|
|
41746
|
+
date: "2026-10-21",
|
|
41747
|
+
category: "feat",
|
|
41748
|
+
title: "Mac app welcome window with samples and a loon tutorial",
|
|
41749
|
+
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.",
|
|
41750
|
+
features: [
|
|
41751
|
+
"desktop",
|
|
41752
|
+
"mac",
|
|
41753
|
+
"onboarding",
|
|
41754
|
+
"loon"
|
|
41755
|
+
]
|
|
41756
|
+
},
|
|
41689
41757
|
{
|
|
41690
41758
|
id: "2026-10-21-mac-sim-teardown-race",
|
|
41691
41759
|
version: "0.10.0",
|
|
@@ -41723,6 +41791,19 @@ var init_CHANGELOG = __esm({
|
|
|
41723
41791
|
"file-io"
|
|
41724
41792
|
]
|
|
41725
41793
|
},
|
|
41794
|
+
{
|
|
41795
|
+
id: "2026-10-21-mac-loon-loop",
|
|
41796
|
+
version: "0.10.0",
|
|
41797
|
+
date: "2026-10-21",
|
|
41798
|
+
category: "feat",
|
|
41799
|
+
title: "Mac app: loon errors inline, last good model kept",
|
|
41800
|
+
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.",
|
|
41801
|
+
features: [
|
|
41802
|
+
"desktop",
|
|
41803
|
+
"mac",
|
|
41804
|
+
"loon"
|
|
41805
|
+
]
|
|
41806
|
+
},
|
|
41726
41807
|
{
|
|
41727
41808
|
id: "2026-10-21-mac-labs-toggle",
|
|
41728
41809
|
version: "0.10.0",
|
|
@@ -41775,6 +41856,19 @@ var init_CHANGELOG = __esm({
|
|
|
41775
41856
|
"cli"
|
|
41776
41857
|
]
|
|
41777
41858
|
},
|
|
41859
|
+
{
|
|
41860
|
+
id: "2026-10-21-incremental-eval-hosts",
|
|
41861
|
+
version: "0.10.0",
|
|
41862
|
+
date: "2026-10-21",
|
|
41863
|
+
category: "perf",
|
|
41864
|
+
title: "Parameter scrubs re-evaluate only what changed",
|
|
41865
|
+
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.",
|
|
41866
|
+
features: [
|
|
41867
|
+
"engine",
|
|
41868
|
+
"evaluation",
|
|
41869
|
+
"performance"
|
|
41870
|
+
]
|
|
41871
|
+
},
|
|
41778
41872
|
{
|
|
41779
41873
|
id: "2026-10-21-gpu-photoreal-limits",
|
|
41780
41874
|
version: "0.10.0",
|
|
@@ -51705,79 +51799,8 @@ var init_loon_assets = __esm({
|
|
|
51705
51799
|
}
|
|
51706
51800
|
});
|
|
51707
51801
|
|
|
51708
|
-
// src/tools/source-provenance.ts
|
|
51709
|
-
import { createHash } from "node:crypto";
|
|
51710
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
51711
|
-
function sourceHash(text) {
|
|
51712
|
-
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
51713
|
-
}
|
|
51714
|
-
function attachLoonSource(doc, { text, modules, base_dir, path }) {
|
|
51715
|
-
const source = {
|
|
51716
|
-
language: "loon",
|
|
51717
|
-
text,
|
|
51718
|
-
modules: modules && Object.keys(modules).length ? { ...modules } : {},
|
|
51719
|
-
hash: sourceHash(text),
|
|
51720
|
-
diverged: false,
|
|
51721
|
-
diverged_by: []
|
|
51722
|
-
};
|
|
51723
|
-
if (base_dir) source.base_dir = base_dir;
|
|
51724
|
-
if (path) source.path = path;
|
|
51725
|
-
doc.source = source;
|
|
51726
|
-
}
|
|
51727
|
-
function markSourceDiverged(documentId, tool) {
|
|
51728
|
-
const src = documents.get(documentId)?.source;
|
|
51729
|
-
if (!src) return false;
|
|
51730
|
-
const firstTime = !src.diverged;
|
|
51731
|
-
src.diverged = true;
|
|
51732
|
-
const by = src.diverged_by ??= [];
|
|
51733
|
-
if (by[by.length - 1] !== tool) by.push(tool);
|
|
51734
|
-
if (by.length > MAX_DIVERGED_BY) by.splice(0, by.length - MAX_DIVERGED_BY);
|
|
51735
|
-
return firstTime;
|
|
51736
|
-
}
|
|
51737
|
-
function sourceStatus(doc) {
|
|
51738
|
-
const src = doc?.source;
|
|
51739
|
-
if (!src) return { source_stale: false };
|
|
51740
|
-
const path = src.path;
|
|
51741
|
-
if (path) {
|
|
51742
|
-
let onDisk = null;
|
|
51743
|
-
try {
|
|
51744
|
-
onDisk = readFileSync3(path, "utf8");
|
|
51745
|
-
} catch {
|
|
51746
|
-
return {
|
|
51747
|
-
source_stale: true,
|
|
51748
|
-
source_path: path,
|
|
51749
|
-
reason: `The source file ${path} can no longer be read \u2014 this session is no longer backed by the file it was loaded from.`
|
|
51750
|
-
};
|
|
51751
|
-
}
|
|
51752
|
-
if (sourceHash(onDisk) !== src.hash) {
|
|
51753
|
-
return {
|
|
51754
|
-
source_stale: true,
|
|
51755
|
-
source_path: path,
|
|
51756
|
-
reason: `${path} changed on disk since this session was evaluated from it \u2014 the session's geometry is from the OLD source. Re-load the file to pick up the edits.`
|
|
51757
|
-
};
|
|
51758
|
-
}
|
|
51759
|
-
}
|
|
51760
|
-
if (src.diverged) {
|
|
51761
|
-
const by = src.diverged_by ?? [];
|
|
51762
|
-
return {
|
|
51763
|
-
source_stale: true,
|
|
51764
|
-
...path ? { source_path: path } : {},
|
|
51765
|
-
reason: `This session has been edited directly (${by.join(", ") || "mutation"}), and those edits cannot round-trip back to loon. The stored source describes the document's ORIGIN, not its current state` + (path ? ` \u2014 saving would not reproduce ${path}, and re-evaluating ${path} would discard the edits.` : `.`)
|
|
51766
|
-
};
|
|
51767
|
-
}
|
|
51768
|
-
return { source_stale: false, ...path ? { source_path: path } : {} };
|
|
51769
|
-
}
|
|
51770
|
-
var MAX_DIVERGED_BY;
|
|
51771
|
-
var init_source_provenance = __esm({
|
|
51772
|
-
"src/tools/source-provenance.ts"() {
|
|
51773
|
-
"use strict";
|
|
51774
|
-
init_session_core();
|
|
51775
|
-
MAX_DIVERGED_BY = 8;
|
|
51776
|
-
}
|
|
51777
|
-
});
|
|
51778
|
-
|
|
51779
51802
|
// src/tools/loon.ts
|
|
51780
|
-
import { readFileSync as
|
|
51803
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
51781
51804
|
import { delimiter, isAbsolute as isAbsolute3, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
51782
51805
|
function composeLoonProgram(input) {
|
|
51783
51806
|
const { source, use_loons, loons } = input;
|
|
@@ -51803,7 +51826,7 @@ function readModule(base, name) {
|
|
|
51803
51826
|
const file = resolve2(join2(root, ...name.split(".")) + ext);
|
|
51804
51827
|
if (file !== root && !file.startsWith(root + sep2)) continue;
|
|
51805
51828
|
try {
|
|
51806
|
-
return
|
|
51829
|
+
return readFileSync3(file, "utf8");
|
|
51807
51830
|
} catch {
|
|
51808
51831
|
}
|
|
51809
51832
|
}
|
|
@@ -51870,11 +51893,10 @@ function evalCadLoon(input, engine) {
|
|
|
51870
51893
|
const modules = composeLoonModules(input);
|
|
51871
51894
|
let doc;
|
|
51872
51895
|
try {
|
|
51873
|
-
doc = engine.
|
|
51896
|
+
doc = engine.evalLoonDocument(source, modules, { baseDir: base_dir });
|
|
51874
51897
|
} catch (e) {
|
|
51875
51898
|
throw explainEvalError(e, parsed, missingModules(source, modules));
|
|
51876
51899
|
}
|
|
51877
|
-
if (doc) attachLoonSource(doc, { text: source, modules, base_dir });
|
|
51878
51900
|
if (!doc) {
|
|
51879
51901
|
const text2 = Object.keys(modules).length ? "Error: this kernel build cannot resolve loon modules ([use ...]) \u2014 update the kernel, or inline the modules into `source`" : "Error: Loon evaluation not supported by this engine build";
|
|
51880
51902
|
return { result: { content: [{ type: "text", text: text2 }] }, doc: null };
|
|
@@ -51948,7 +51970,6 @@ var init_loon = __esm({
|
|
|
51948
51970
|
init_session_core();
|
|
51949
51971
|
init_loon_assets();
|
|
51950
51972
|
init_remote();
|
|
51951
|
-
init_source_provenance();
|
|
51952
51973
|
init_tool_def();
|
|
51953
51974
|
createCadLoonSchema = {
|
|
51954
51975
|
type: "object",
|
|
@@ -52604,7 +52625,7 @@ var init_session_store = __esm({
|
|
|
52604
52625
|
});
|
|
52605
52626
|
|
|
52606
52627
|
// src/tools/artifact-store.ts
|
|
52607
|
-
import { createHash
|
|
52628
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
52608
52629
|
function ttlMs() {
|
|
52609
52630
|
const raw = process.env.MCP_ARTIFACT_TTL_MS;
|
|
52610
52631
|
const n = raw ? parseInt(raw, 10) : NaN;
|
|
@@ -52700,7 +52721,7 @@ function storeArtifact(files) {
|
|
|
52700
52721
|
const manifest = stored.map((f) => ({
|
|
52701
52722
|
file: f.name,
|
|
52702
52723
|
bytes: f.buf.length,
|
|
52703
|
-
sha256:
|
|
52724
|
+
sha256: createHash("sha256").update(f.buf).digest("hex")
|
|
52704
52725
|
}));
|
|
52705
52726
|
const bytes = stored.reduce((n, f) => n + f.buf.length, 0);
|
|
52706
52727
|
const expiresAt = now + ttlMs();
|
|
@@ -52835,7 +52856,7 @@ async function loadDurable(id) {
|
|
|
52835
52856
|
manifest: Array.isArray(row.manifest) ? row.manifest : files.map((f) => ({
|
|
52836
52857
|
file: f.name,
|
|
52837
52858
|
bytes: f.buf.length,
|
|
52838
|
-
sha256:
|
|
52859
|
+
sha256: createHash("sha256").update(f.buf).digest("hex")
|
|
52839
52860
|
})),
|
|
52840
52861
|
bytes: typeof row.bytes === "number" ? row.bytes : files.reduce((n, f) => n + f.buf.length, 0),
|
|
52841
52862
|
createdAt: row.created_at ? Date.parse(row.created_at) : Date.now(),
|
|
@@ -52895,6 +52916,64 @@ var init_artifact_store = __esm({
|
|
|
52895
52916
|
}
|
|
52896
52917
|
});
|
|
52897
52918
|
|
|
52919
|
+
// src/tools/source-provenance.ts
|
|
52920
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
52921
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
52922
|
+
function sourceHash(text) {
|
|
52923
|
+
return createHash2("sha256").update(text, "utf8").digest("hex");
|
|
52924
|
+
}
|
|
52925
|
+
function markSourceDiverged(documentId, tool) {
|
|
52926
|
+
const src = documents.get(documentId)?.source;
|
|
52927
|
+
if (!src) return false;
|
|
52928
|
+
const firstTime = !src.diverged;
|
|
52929
|
+
src.diverged = true;
|
|
52930
|
+
const by = src.diverged_by ??= [];
|
|
52931
|
+
if (by[by.length - 1] !== tool) by.push(tool);
|
|
52932
|
+
if (by.length > MAX_DIVERGED_BY) by.splice(0, by.length - MAX_DIVERGED_BY);
|
|
52933
|
+
return firstTime;
|
|
52934
|
+
}
|
|
52935
|
+
function sourceStatus(doc) {
|
|
52936
|
+
const src = doc?.source;
|
|
52937
|
+
if (!src) return { source_stale: false };
|
|
52938
|
+
const path = src.path;
|
|
52939
|
+
if (path) {
|
|
52940
|
+
let onDisk = null;
|
|
52941
|
+
try {
|
|
52942
|
+
onDisk = readFileSync4(path, "utf8");
|
|
52943
|
+
} catch {
|
|
52944
|
+
return {
|
|
52945
|
+
source_stale: true,
|
|
52946
|
+
source_path: path,
|
|
52947
|
+
reason: `The source file ${path} can no longer be read \u2014 this session is no longer backed by the file it was loaded from.`
|
|
52948
|
+
};
|
|
52949
|
+
}
|
|
52950
|
+
if (sourceHash(onDisk) !== src.hash) {
|
|
52951
|
+
return {
|
|
52952
|
+
source_stale: true,
|
|
52953
|
+
source_path: path,
|
|
52954
|
+
reason: `${path} changed on disk since this session was evaluated from it \u2014 the session's geometry is from the OLD source. Re-load the file to pick up the edits.`
|
|
52955
|
+
};
|
|
52956
|
+
}
|
|
52957
|
+
}
|
|
52958
|
+
if (src.diverged) {
|
|
52959
|
+
const by = src.diverged_by ?? [];
|
|
52960
|
+
return {
|
|
52961
|
+
source_stale: true,
|
|
52962
|
+
...path ? { source_path: path } : {},
|
|
52963
|
+
reason: `This session has been edited directly (${by.join(", ") || "mutation"}), and those edits cannot round-trip back to loon. The stored source describes the document's ORIGIN, not its current state` + (path ? ` \u2014 saving would not reproduce ${path}, and re-evaluating ${path} would discard the edits.` : `.`)
|
|
52964
|
+
};
|
|
52965
|
+
}
|
|
52966
|
+
return { source_stale: false, ...path ? { source_path: path } : {} };
|
|
52967
|
+
}
|
|
52968
|
+
var MAX_DIVERGED_BY;
|
|
52969
|
+
var init_source_provenance = __esm({
|
|
52970
|
+
"src/tools/source-provenance.ts"() {
|
|
52971
|
+
"use strict";
|
|
52972
|
+
init_session_core();
|
|
52973
|
+
MAX_DIVERGED_BY = 8;
|
|
52974
|
+
}
|
|
52975
|
+
});
|
|
52976
|
+
|
|
52898
52977
|
// src/tools/session.ts
|
|
52899
52978
|
import { writeFileSync as writeFileSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
52900
52979
|
import { dirname, resolve as resolve3 } from "node:path";
|
|
@@ -53211,18 +53290,12 @@ async function loadDocumentFromPath(path, store, engine) {
|
|
|
53211
53290
|
const modules = composeLoonModules({ source: raw, base_dir: baseDir });
|
|
53212
53291
|
let doc;
|
|
53213
53292
|
try {
|
|
53214
|
-
doc = engine.
|
|
53293
|
+
doc = engine.evalLoonDocument(raw, modules, { baseDir, path: abs });
|
|
53215
53294
|
} catch (e) {
|
|
53216
53295
|
return fail2(`Loon evaluation of ${abs} failed: ${e.message}`);
|
|
53217
53296
|
}
|
|
53218
53297
|
if (!doc) return fail2(`Loon evaluation of ${abs} produced no document.`);
|
|
53219
53298
|
const imports = assetNote(resolveLoonAssets(doc, { base_dir: baseDir }, engine));
|
|
53220
|
-
attachLoonSource(doc, {
|
|
53221
|
-
text: raw,
|
|
53222
|
-
modules,
|
|
53223
|
-
base_dir: baseDir,
|
|
53224
|
-
path: abs
|
|
53225
|
-
});
|
|
53226
53299
|
const id = registerSession(doc);
|
|
53227
53300
|
return {
|
|
53228
53301
|
content: [
|
|
@@ -87053,8 +87126,8 @@ var init_server3 = __esm({
|
|
|
87053
87126
|
init_order_feed();
|
|
87054
87127
|
init_animate();
|
|
87055
87128
|
PKG_VERSION = (() => {
|
|
87056
|
-
if ("0.10.0-main.
|
|
87057
|
-
return "0.10.0-main.
|
|
87129
|
+
if ("0.10.0-main.133") {
|
|
87130
|
+
return "0.10.0-main.133";
|
|
87058
87131
|
}
|
|
87059
87132
|
try {
|
|
87060
87133
|
const req = createRequire2(import.meta.url);
|
|
@@ -87063,8 +87136,8 @@ var init_server3 = __esm({
|
|
|
87063
87136
|
return "0.0.0";
|
|
87064
87137
|
}
|
|
87065
87138
|
})();
|
|
87066
|
-
BUILD_SHA = "
|
|
87067
|
-
BUILD_TIME = "2026-10-
|
|
87139
|
+
BUILD_SHA = "ed9b701622258f961cdbb3fa2c2430c283a8fc5b";
|
|
87140
|
+
BUILD_TIME = "2026-10-21T17:47:36.984Z";
|
|
87068
87141
|
SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
|
|
87069
87142
|
VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
|
|
87070
87143
|
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.
|
|
3
|
+
"version": "0.10.0-main.133",
|
|
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": "
|
|
23
|
-
"builtAt": "2026-10-
|
|
22
|
+
"sha": "ed9b701622258f961cdbb3fa2c2430c283a8fc5b",
|
|
23
|
+
"builtAt": "2026-10-21T17:47:36.984Z"
|
|
24
24
|
}
|
|
25
25
|
}
|