@vcad/mcp 0.10.0-main.112 → 0.10.0-main.113
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 +174 -7
- 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 6fe98c8bcad683e78ce3185512bd51fbfc36aa73 at 2026-10-20T22:54:39.478Z. Source: https://github.com/ecto/vcad
|
package/index.mjs
CHANGED
|
@@ -42019,6 +42019,21 @@ var init_CHANGELOG = __esm({
|
|
|
42019
42019
|
"get_footprint"
|
|
42020
42020
|
]
|
|
42021
42021
|
},
|
|
42022
|
+
{
|
|
42023
|
+
id: "2026-10-20-update-params-apply",
|
|
42024
|
+
version: "0.10.0",
|
|
42025
|
+
date: "2026-10-20",
|
|
42026
|
+
category: "fix",
|
|
42027
|
+
title: "AI updates to part dimensions actually apply",
|
|
42028
|
+
summary: "An update like resizing a cube via size {x,y,z} reported success but changed nothing; nested params now map onto the part's real fields, and unknown params are refused.",
|
|
42029
|
+
features: [
|
|
42030
|
+
"engine",
|
|
42031
|
+
"ai"
|
|
42032
|
+
],
|
|
42033
|
+
mcpTools: [
|
|
42034
|
+
"update"
|
|
42035
|
+
]
|
|
42036
|
+
},
|
|
42022
42037
|
{
|
|
42023
42038
|
id: "2026-10-20-schematic-power-flags",
|
|
42024
42039
|
version: "0.10.0",
|
|
@@ -42152,6 +42167,19 @@ var init_CHANGELOG = __esm({
|
|
|
42152
42167
|
"find_alternatives"
|
|
42153
42168
|
]
|
|
42154
42169
|
},
|
|
42170
|
+
{
|
|
42171
|
+
id: "2026-10-20-import-keeps-materials",
|
|
42172
|
+
version: "0.10.0",
|
|
42173
|
+
date: "2026-10-20",
|
|
42174
|
+
category: "fix",
|
|
42175
|
+
title: "Imported parts keep their material and visibility",
|
|
42176
|
+
summary: "Opening a document through the engine reset every part's material to default and showed hidden parts; both now survive import and every later edit.",
|
|
42177
|
+
features: [
|
|
42178
|
+
"engine",
|
|
42179
|
+
"import",
|
|
42180
|
+
"materials"
|
|
42181
|
+
]
|
|
42182
|
+
},
|
|
42155
42183
|
{
|
|
42156
42184
|
id: "2026-10-20-hierarchical-schematic-sheets",
|
|
42157
42185
|
version: "0.10.0",
|
|
@@ -55719,8 +55747,123 @@ function dispatchRegistryTool(toolName, args, engine) {
|
|
|
55719
55747
|
}
|
|
55720
55748
|
return result;
|
|
55721
55749
|
}
|
|
55722
|
-
function
|
|
55750
|
+
function toStableId(doc, v) {
|
|
55751
|
+
if (typeof v !== "string" && typeof v !== "number") return v;
|
|
55752
|
+
return rootForPartId(doc, v)?.partId ?? String(v);
|
|
55753
|
+
}
|
|
55754
|
+
function owningRootIndex(doc, nodeId) {
|
|
55755
|
+
const exact = doc.roots.findIndex((r) => String(r.root) === nodeId);
|
|
55756
|
+
if (exact >= 0) return exact;
|
|
55757
|
+
return doc.roots.findIndex((r) => {
|
|
55758
|
+
const stack = [r.root];
|
|
55759
|
+
const seen = /* @__PURE__ */ new Set();
|
|
55760
|
+
while (stack.length) {
|
|
55761
|
+
const id = String(stack.pop());
|
|
55762
|
+
if (id === nodeId) return true;
|
|
55763
|
+
if (seen.has(id)) continue;
|
|
55764
|
+
seen.add(id);
|
|
55765
|
+
const op = doc.nodes[id]?.op;
|
|
55766
|
+
if (!op) continue;
|
|
55767
|
+
for (const k of ["child", "left", "right"]) if (op[k] !== void 0) stack.push(op[k]);
|
|
55768
|
+
if (Array.isArray(op.children)) stack.push(...op.children);
|
|
55769
|
+
}
|
|
55770
|
+
return false;
|
|
55771
|
+
});
|
|
55772
|
+
}
|
|
55773
|
+
function nodeRefToStableId(doc, v) {
|
|
55774
|
+
if (typeof v === "number" || typeof v === "string" && /^\d+$/.test(v)) {
|
|
55775
|
+
const idx = owningRootIndex(doc, String(v));
|
|
55776
|
+
if (idx >= 0) return partIdForRoot(doc, idx);
|
|
55777
|
+
}
|
|
55778
|
+
return toStableId(doc, v);
|
|
55779
|
+
}
|
|
55780
|
+
function engineArgs(toolName, args, doc) {
|
|
55781
|
+
const out = toolName === "create" ? applyParamDefaults({ ...args }) : { ...args };
|
|
55782
|
+
if ("part_id" in out) out.part_id = toStableId(doc, out.part_id);
|
|
55783
|
+
if (Array.isArray(out.part_ids)) out.part_ids = out.part_ids.map((v) => toStableId(doc, v));
|
|
55784
|
+
if (out.parent_part_id !== void 0) out.parent_part_id = nodeRefToStableId(doc, out.parent_part_id);
|
|
55785
|
+
if (toolName === "update" && out.node_id !== void 0) {
|
|
55786
|
+
out.node_id = nodeRefToStableId(doc, out.node_id);
|
|
55787
|
+
}
|
|
55788
|
+
if (toolName === "create" && out.params && typeof out.params === "object") {
|
|
55789
|
+
const params = { ...out.params };
|
|
55790
|
+
for (const key3 of ["left", "right", "child"]) {
|
|
55791
|
+
if (key3 in params) params[key3] = nodeRefToStableId(doc, params[key3]);
|
|
55792
|
+
}
|
|
55793
|
+
out.params = params;
|
|
55794
|
+
}
|
|
55795
|
+
return out;
|
|
55796
|
+
}
|
|
55797
|
+
function engineErrorMessage(toolName, args, err9) {
|
|
55798
|
+
switch (err9.kind) {
|
|
55799
|
+
case "unknown_id":
|
|
55800
|
+
return `${toolName}: no part with id "${err9.id ?? "?"}"`;
|
|
55801
|
+
case "invalid":
|
|
55802
|
+
return enrichPlannerError(toolName, args, `${toolName}: ${err9.message ?? "invalid arguments"}`);
|
|
55803
|
+
default:
|
|
55804
|
+
return `${toolName}: ${err9.message ?? err9.kind}`;
|
|
55805
|
+
}
|
|
55806
|
+
}
|
|
55807
|
+
function runMutationViaEngine(toolName, toolArgs, doc, documentId) {
|
|
55808
|
+
if (!ENGINE_LOWERED_TOOLS.has(toolName)) return null;
|
|
55809
|
+
if (process.env.VCAD_MCP_ENGINE_APPLY === "0") return null;
|
|
55810
|
+
const wasm3 = getKernelWasmSync();
|
|
55811
|
+
const factory = wasm3?.WasmDocumentEngine;
|
|
55812
|
+
if (!factory || typeof factory.withReplica !== "function") return null;
|
|
55813
|
+
const engine = factory.withReplica(0);
|
|
55814
|
+
try {
|
|
55815
|
+
if (typeof engine.apply_tool !== "function") return null;
|
|
55816
|
+
const deprecation = typeof toolArgs.part_id === "string" ? partIdDeprecation(toolArgs.part_id, rootForPartId(doc, toolArgs.part_id)) : void 0;
|
|
55817
|
+
const args = engineArgs(toolName, toolArgs, doc);
|
|
55818
|
+
engine.import_ir(JSON.stringify(doc));
|
|
55819
|
+
const envelope = JSON.parse(engine.apply_tool(toolName, JSON.stringify(args)));
|
|
55820
|
+
if (!envelope.ok || !envelope.result) {
|
|
55821
|
+
const err9 = envelope.error ?? { kind: "invalid", message: "engine returned no result" };
|
|
55822
|
+
if (err9.kind === "unsupported") return null;
|
|
55823
|
+
throw new Error(engineErrorMessage(toolName, args, err9));
|
|
55824
|
+
}
|
|
55825
|
+
const next = envelope.result.document;
|
|
55826
|
+
const parts = envelope.result.parts ?? [];
|
|
55827
|
+
for (const p of parts) {
|
|
55828
|
+
if (!p.name) continue;
|
|
55829
|
+
const rootIdx = next.roots.findIndex((_, i) => next.partIds?.[String(next.roots[i].root)] === p.id);
|
|
55830
|
+
const rootNode = rootIdx >= 0 ? next.nodes[String(next.roots[rootIdx].root)] : void 0;
|
|
55831
|
+
if (rootNode && !rootNode.name) rootNode.name = p.name;
|
|
55832
|
+
}
|
|
55833
|
+
for (const k of Object.keys(doc)) delete doc[k];
|
|
55834
|
+
Object.assign(doc, next);
|
|
55835
|
+
const warnings = [...envelope.result.warnings ?? [], ...deprecation ? [deprecation] : []];
|
|
55836
|
+
const payload = { document_id: documentId };
|
|
55837
|
+
if (toolName === "delete") {
|
|
55838
|
+
payload.removed = args.part_id;
|
|
55839
|
+
} else if (toolName === "set_material") {
|
|
55840
|
+
payload.part_id = args.part_id ?? args.part_ids;
|
|
55841
|
+
payload.material = toolArgs.material;
|
|
55842
|
+
} else {
|
|
55843
|
+
const partId = envelope.result.createdFeatureId ?? (typeof args.part_id === "string" ? args.part_id : void 0);
|
|
55844
|
+
if (partId) {
|
|
55845
|
+
payload.part_id = partId;
|
|
55846
|
+
const part = parts.find((p) => p.id === partId);
|
|
55847
|
+
const root = rootForPartId(doc, partId);
|
|
55848
|
+
const nodeId = part?.primitiveNodeId ?? root?.entry.root;
|
|
55849
|
+
if (nodeId !== void 0) payload.node_id = nodeId;
|
|
55850
|
+
}
|
|
55851
|
+
}
|
|
55852
|
+
if (envelope.result.consumedPartIds?.length) {
|
|
55853
|
+
payload.consumed_part_ids = envelope.result.consumedPartIds;
|
|
55854
|
+
}
|
|
55855
|
+
if (warnings.length) payload.warnings = warnings;
|
|
55856
|
+
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
55857
|
+
} finally {
|
|
55858
|
+
engine.free?.();
|
|
55859
|
+
}
|
|
55860
|
+
}
|
|
55861
|
+
function runMutation(toolName, rawArgs, doc, documentId, opts = {}) {
|
|
55723
55862
|
const toolArgs = normalizeNodeRefs(toolName, rawArgs, doc);
|
|
55863
|
+
if (opts.engine !== false) {
|
|
55864
|
+
const viaEngine = runMutationViaEngine(toolName, toolArgs, doc, documentId);
|
|
55865
|
+
if (viaEngine) return viaEngine;
|
|
55866
|
+
}
|
|
55724
55867
|
if (toolName === "delete") {
|
|
55725
55868
|
const partId = String(toolArgs.part_id ?? "");
|
|
55726
55869
|
if (!partId) throw new Error("delete: missing `part_id`");
|
|
@@ -55905,13 +56048,14 @@ function childrenOf(op) {
|
|
|
55905
56048
|
return [];
|
|
55906
56049
|
}
|
|
55907
56050
|
}
|
|
55908
|
-
var BROWSER_ONLY_TOOLS, DEFERRED_TOOLS, READ_ONLY_REGISTRY_TOOLS, MCP_DESCRIPTIONS, CREATE_PARAM_DEFAULTS, CREATE_PARAM_HINTS, NODE_REF_PARAM_KEYS;
|
|
56051
|
+
var BROWSER_ONLY_TOOLS, DEFERRED_TOOLS, READ_ONLY_REGISTRY_TOOLS, MCP_DESCRIPTIONS, CREATE_PARAM_DEFAULTS, CREATE_PARAM_HINTS, NODE_REF_PARAM_KEYS, ENGINE_LOWERED_TOOLS;
|
|
55909
56052
|
var init_registry_dispatch = __esm({
|
|
55910
56053
|
"src/tools/registry-dispatch.ts"() {
|
|
55911
56054
|
"use strict";
|
|
55912
56055
|
init_dist3();
|
|
55913
56056
|
init_session2();
|
|
55914
56057
|
init_part_ids2();
|
|
56058
|
+
init_dist();
|
|
55915
56059
|
init_pose();
|
|
55916
56060
|
init_integrity();
|
|
55917
56061
|
init_measure();
|
|
@@ -55967,6 +56111,26 @@ var init_registry_dispatch = __esm({
|
|
|
55967
56111
|
edge_blend: '{child: nodeId, edges: {type: "All"} | {type: "Near", point: {x,y,z}} | {type: "Direction", axis: {x,y,z}, tol_deg}, profile: {type: "Constant", size, shape} | {type: "Keyed", keys: [{t, size, shape}]}} \u2014 shape 0 = chamfer, 1 = fillet; size in mm'
|
|
55968
56112
|
};
|
|
55969
56113
|
NODE_REF_PARAM_KEYS = ["child", "left", "right", "sketch"];
|
|
56114
|
+
ENGINE_LOWERED_TOOLS = /* @__PURE__ */ new Set([
|
|
56115
|
+
"create",
|
|
56116
|
+
"update",
|
|
56117
|
+
"delete",
|
|
56118
|
+
"set_material",
|
|
56119
|
+
"linear_pattern",
|
|
56120
|
+
"circular_pattern",
|
|
56121
|
+
"mirror",
|
|
56122
|
+
"translate",
|
|
56123
|
+
"rotate",
|
|
56124
|
+
"scale",
|
|
56125
|
+
"union",
|
|
56126
|
+
"difference",
|
|
56127
|
+
"intersection",
|
|
56128
|
+
"fillet",
|
|
56129
|
+
"chamfer",
|
|
56130
|
+
"shell",
|
|
56131
|
+
"tube",
|
|
56132
|
+
"polyline_tube"
|
|
56133
|
+
]);
|
|
55970
56134
|
}
|
|
55971
56135
|
});
|
|
55972
56136
|
|
|
@@ -58041,7 +58205,10 @@ function applyOps(doc, ops, documentId) {
|
|
|
58041
58205
|
name,
|
|
58042
58206
|
resolveSymbolicRefs(args, createdIds, i, doc),
|
|
58043
58207
|
doc,
|
|
58044
|
-
documentId
|
|
58208
|
+
documentId,
|
|
58209
|
+
// Legacy planner: "@N" and raw numeric child refs address the
|
|
58210
|
+
// planner's node numbering (see runMutation).
|
|
58211
|
+
{ engine: false }
|
|
58045
58212
|
);
|
|
58046
58213
|
} catch (err9) {
|
|
58047
58214
|
throw new BatchOpError(i, name, err9);
|
|
@@ -87229,8 +87396,8 @@ var init_server3 = __esm({
|
|
|
87229
87396
|
init_order_feed();
|
|
87230
87397
|
init_animate();
|
|
87231
87398
|
PKG_VERSION = (() => {
|
|
87232
|
-
if ("0.10.0-main.
|
|
87233
|
-
return "0.10.0-main.
|
|
87399
|
+
if ("0.10.0-main.113") {
|
|
87400
|
+
return "0.10.0-main.113";
|
|
87234
87401
|
}
|
|
87235
87402
|
try {
|
|
87236
87403
|
const req = createRequire2(import.meta.url);
|
|
@@ -87239,8 +87406,8 @@ var init_server3 = __esm({
|
|
|
87239
87406
|
return "0.0.0";
|
|
87240
87407
|
}
|
|
87241
87408
|
})();
|
|
87242
|
-
BUILD_SHA = "
|
|
87243
|
-
BUILD_TIME = "2026-10-20T22:
|
|
87409
|
+
BUILD_SHA = "6fe98c8bcad683e78ce3185512bd51fbfc36aa73";
|
|
87410
|
+
BUILD_TIME = "2026-10-20T22:54:39.478Z";
|
|
87244
87411
|
SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
|
|
87245
87412
|
VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
|
|
87246
87413
|
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.113",
|
|
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-20T22:
|
|
22
|
+
"sha": "6fe98c8bcad683e78ce3185512bd51fbfc36aa73",
|
|
23
|
+
"builtAt": "2026-10-20T22:54:39.478Z"
|
|
24
24
|
}
|
|
25
25
|
}
|