@vcad/mcp 0.9.4-main.47 → 0.9.4-main.49
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 +848 -56
- package/package.json +3 -3
- package/vcad_kernel_wasm_bg.wasm +0 -0
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 40ccc073edea8494ce6e1a94ea360bf79cfc630d at 2026-07-29T16:38:39.110Z. Source: https://github.com/ecto/vcad
|
package/index.mjs
CHANGED
|
@@ -6180,22 +6180,6 @@ var init_vcad_kernel_wasm = __esm({
|
|
|
6180
6180
|
resetAccumulation() {
|
|
6181
6181
|
wasm.raytracer_resetAccumulation(this.__wbg_ptr);
|
|
6182
6182
|
}
|
|
6183
|
-
/**
|
|
6184
|
-
* Set SSAO (screen-space ambient occlusion) parameters.
|
|
6185
|
-
*
|
|
6186
|
-
* # Arguments
|
|
6187
|
-
* * `radius` - World-space hemisphere sample radius (default 0.3)
|
|
6188
|
-
* * `intensity` - Occlusion strength: 0 = disabled, 1 = default (>1 stylized)
|
|
6189
|
-
* * `bias` - Depth bias to prevent self-occlusion (default 0.001)
|
|
6190
|
-
* * `sample_count` - Hemisphere samples per frame: 8, 16, or 32 (default 16)
|
|
6191
|
-
* @param {number} radius
|
|
6192
|
-
* @param {number} intensity
|
|
6193
|
-
* @param {number} bias
|
|
6194
|
-
* @param {number} sample_count
|
|
6195
|
-
*/
|
|
6196
|
-
setAO(radius, intensity, bias, sample_count) {
|
|
6197
|
-
wasm.raytracer_setAO(this.__wbg_ptr, radius, intensity, bias, sample_count);
|
|
6198
|
-
}
|
|
6199
6183
|
/**
|
|
6200
6184
|
* Set the debug render mode.
|
|
6201
6185
|
*
|
|
@@ -6251,12 +6235,6 @@ var init_vcad_kernel_wasm = __esm({
|
|
|
6251
6235
|
wasm.raytracer_setEdgeStyle(this.__wbg_ptr, enable_silhouette, enable_crease, enable_boundary, silhouette_r, silhouette_g, silhouette_b, silhouette_a, crease_r, crease_g, crease_b, crease_a, boundary_r, boundary_g, boundary_b, boundary_a, silhouette_width, crease_width, boundary_width, edge_softness);
|
|
6252
6236
|
}
|
|
6253
6237
|
/**
|
|
6254
|
-
* Set the material for all faces in the scene.
|
|
6255
|
-
*
|
|
6256
|
-
* # Arguments
|
|
6257
|
-
* * `r`, `g`, `b` - RGB color components (0-1 range, linear)
|
|
6258
|
-
* * `metallic` - Metallic factor (0 = dielectric, 1 = metal)
|
|
6259
|
-
* * `roughness` - Roughness factor (0 = smooth/mirror, 1 = rough/diffuse)
|
|
6260
6238
|
* @param {number} r
|
|
6261
6239
|
* @param {number} g
|
|
6262
6240
|
* @param {number} b
|
|
@@ -6269,6 +6247,57 @@ var init_vcad_kernel_wasm = __esm({
|
|
|
6269
6247
|
throw takeFromExternrefTable0(ret[0]);
|
|
6270
6248
|
}
|
|
6271
6249
|
}
|
|
6250
|
+
/**
|
|
6251
|
+
* Set the material for all faces in the scene.
|
|
6252
|
+
*
|
|
6253
|
+
* # Arguments
|
|
6254
|
+
* * `r`, `g`, `b` - RGB color components (0-1 range, linear)
|
|
6255
|
+
* * `metallic` - Metallic factor (0 = dielectric, 1 = metal)
|
|
6256
|
+
* * `roughness` - Roughness factor (0 = smooth/mirror, 1 = rough/diffuse)
|
|
6257
|
+
* Set the material from a serialized IR `MaterialDef`.
|
|
6258
|
+
*
|
|
6259
|
+
* Preferred over `setMaterial`: that one only carries colour, metallic and
|
|
6260
|
+
* roughness, so clearcoat, IOR and anisotropy never reached the viewport
|
|
6261
|
+
* and a brushed or lacquered part shaded differently here than under
|
|
6262
|
+
* `vcad-render --photoreal`. This runs the SAME derivation the CPU
|
|
6263
|
+
* renderer uses (`Pbr::from_material_def`), so both agree by construction.
|
|
6264
|
+
*
|
|
6265
|
+
* `json` is a `MaterialDef` object; pass `null`/empty to fall back to the
|
|
6266
|
+
* optional `tint` (linear RGB) or the neutral default.
|
|
6267
|
+
* @param {string | null} [json]
|
|
6268
|
+
* @param {Float64Array | null} [tint]
|
|
6269
|
+
*/
|
|
6270
|
+
setMaterialFromDef(json, tint) {
|
|
6271
|
+
var ptr0 = isLikeNone(json) ? 0 : passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
6272
|
+
var len0 = WASM_VECTOR_LEN;
|
|
6273
|
+
var ptr1 = isLikeNone(tint) ? 0 : passArrayF64ToWasm0(tint, wasm.__wbindgen_malloc);
|
|
6274
|
+
var len1 = WASM_VECTOR_LEN;
|
|
6275
|
+
const ret = wasm.raytracer_setMaterialFromDef(this.__wbg_ptr, ptr0, len0, ptr1, len1);
|
|
6276
|
+
if (ret[1]) {
|
|
6277
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
6278
|
+
}
|
|
6279
|
+
}
|
|
6280
|
+
/**
|
|
6281
|
+
* Set the path tracer's quality ceiling and stylisation mode.
|
|
6282
|
+
*
|
|
6283
|
+
* Replaces the old `setAO`. The renderer is a real path tracer now, so
|
|
6284
|
+
* screen-space ambient occlusion is gone — multi-bounce GI computes
|
|
6285
|
+
* contact occlusion correctly, and stacking a proxy on top of it would
|
|
6286
|
+
* double-darken every concave corner.
|
|
6287
|
+
*
|
|
6288
|
+
* # Arguments
|
|
6289
|
+
* * `max_depth` - Ceiling on path length (1 = direct lighting only,
|
|
6290
|
+
* default 6, which matches `vcad-render --photoreal`). Actual depth
|
|
6291
|
+
* escalates with accumulation, so the draft frame stays interactive
|
|
6292
|
+
* regardless of this value.
|
|
6293
|
+
* * `stylize` - Draw the Sobel edge overlay. Turn this OFF for a
|
|
6294
|
+
* photoreal viewport: edge lines fight photorealism.
|
|
6295
|
+
* @param {number} max_depth
|
|
6296
|
+
* @param {boolean} stylize
|
|
6297
|
+
*/
|
|
6298
|
+
setPathTrace(max_depth, stylize) {
|
|
6299
|
+
wasm.raytracer_setPathTrace(this.__wbg_ptr, max_depth, stylize);
|
|
6300
|
+
}
|
|
6272
6301
|
/**
|
|
6273
6302
|
* Set the adaptive refinement sample count.
|
|
6274
6303
|
*
|
|
@@ -13733,10 +13762,10 @@ function isValidJWT(token, algorithm = null) {
|
|
|
13733
13762
|
const tokensParts = token.split(".");
|
|
13734
13763
|
if (tokensParts.length !== 3)
|
|
13735
13764
|
return false;
|
|
13736
|
-
const [
|
|
13737
|
-
if (!
|
|
13765
|
+
const [header2] = tokensParts;
|
|
13766
|
+
if (!header2)
|
|
13738
13767
|
return false;
|
|
13739
|
-
const parsedHeader = JSON.parse(atob(
|
|
13768
|
+
const parsedHeader = JSON.parse(atob(header2));
|
|
13740
13769
|
if ("typ" in parsedHeader && parsedHeader?.typ !== "JWT")
|
|
13741
13770
|
return false;
|
|
13742
13771
|
if (!parsedHeader.alg)
|
|
@@ -18655,9 +18684,9 @@ var init_protocol = __esm({
|
|
|
18655
18684
|
});
|
|
18656
18685
|
this.setRequestHandler(ListTasksRequestSchema, async (request, extra) => {
|
|
18657
18686
|
try {
|
|
18658
|
-
const { tasks, nextCursor } = await this._taskStore.listTasks(request.params?.cursor, extra.sessionId);
|
|
18687
|
+
const { tasks: tasks2, nextCursor } = await this._taskStore.listTasks(request.params?.cursor, extra.sessionId);
|
|
18659
18688
|
return {
|
|
18660
|
-
tasks,
|
|
18689
|
+
tasks: tasks2,
|
|
18661
18690
|
nextCursor,
|
|
18662
18691
|
_meta: {}
|
|
18663
18692
|
};
|
|
@@ -18804,7 +18833,7 @@ var init_protocol = __esm({
|
|
|
18804
18833
|
const capturedTransport = this._transport;
|
|
18805
18834
|
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
18806
18835
|
if (handler === void 0) {
|
|
18807
|
-
const
|
|
18836
|
+
const errorResponse2 = {
|
|
18808
18837
|
jsonrpc: "2.0",
|
|
18809
18838
|
id: request.id,
|
|
18810
18839
|
error: {
|
|
@@ -18815,11 +18844,11 @@ var init_protocol = __esm({
|
|
|
18815
18844
|
if (relatedTaskId && this._taskMessageQueue) {
|
|
18816
18845
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
18817
18846
|
type: "error",
|
|
18818
|
-
message:
|
|
18847
|
+
message: errorResponse2,
|
|
18819
18848
|
timestamp: Date.now()
|
|
18820
18849
|
}, capturedTransport?.sessionId).catch((error2) => this._onerror(new Error(`Failed to enqueue error response: ${error2}`)));
|
|
18821
18850
|
} else {
|
|
18822
|
-
capturedTransport?.send(
|
|
18851
|
+
capturedTransport?.send(errorResponse2).catch((error2) => this._onerror(new Error(`Failed to send an error response: ${error2}`)));
|
|
18823
18852
|
}
|
|
18824
18853
|
return;
|
|
18825
18854
|
}
|
|
@@ -18889,7 +18918,7 @@ var init_protocol = __esm({
|
|
|
18889
18918
|
if (abortController.signal.aborted) {
|
|
18890
18919
|
return;
|
|
18891
18920
|
}
|
|
18892
|
-
const
|
|
18921
|
+
const errorResponse2 = {
|
|
18893
18922
|
jsonrpc: "2.0",
|
|
18894
18923
|
id: request.id,
|
|
18895
18924
|
error: {
|
|
@@ -18901,11 +18930,11 @@ var init_protocol = __esm({
|
|
|
18901
18930
|
if (relatedTaskId && this._taskMessageQueue) {
|
|
18902
18931
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
18903
18932
|
type: "error",
|
|
18904
|
-
message:
|
|
18933
|
+
message: errorResponse2,
|
|
18905
18934
|
timestamp: Date.now()
|
|
18906
18935
|
}, capturedTransport?.sessionId);
|
|
18907
18936
|
} else {
|
|
18908
|
-
await capturedTransport?.send(
|
|
18937
|
+
await capturedTransport?.send(errorResponse2);
|
|
18909
18938
|
}
|
|
18910
18939
|
}).catch((error2) => this._onerror(new Error(`Failed to send response: ${error2}`))).finally(() => {
|
|
18911
18940
|
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
@@ -41040,6 +41069,18 @@ var init_CHANGELOG = __esm({
|
|
|
41040
41069
|
CHANGELOG_default = {
|
|
41041
41070
|
$schema: "./changelog.schema.json",
|
|
41042
41071
|
entries: [
|
|
41072
|
+
{
|
|
41073
|
+
id: "2026-07-28-mcp-2026-07-28-protocol",
|
|
41074
|
+
version: "0.9.4",
|
|
41075
|
+
date: "2026-07-28",
|
|
41076
|
+
category: "feat",
|
|
41077
|
+
title: "MCP 2026-07-28 protocol support",
|
|
41078
|
+
summary: "The vcad MCP server now fully speaks the stateless 2026-07-28 revision \u2014 server/discover, MRTR, the Tasks extension, subscriptions/listen, and streamed progress \u2014 alongside every earlier revision.",
|
|
41079
|
+
features: [
|
|
41080
|
+
"mcp"
|
|
41081
|
+
],
|
|
41082
|
+
mcpTools: []
|
|
41083
|
+
},
|
|
41043
41084
|
{
|
|
41044
41085
|
id: "2026-07-26-viewport-path-tracer",
|
|
41045
41086
|
version: "0.9.4",
|
|
@@ -41073,6 +41114,21 @@ var init_CHANGELOG = __esm({
|
|
|
41073
41114
|
"verify_receipt"
|
|
41074
41115
|
]
|
|
41075
41116
|
},
|
|
41117
|
+
{
|
|
41118
|
+
id: "2026-07-26-step-export-product-anchor",
|
|
41119
|
+
version: "0.9.4",
|
|
41120
|
+
date: "2026-07-26",
|
|
41121
|
+
category: "fix",
|
|
41122
|
+
title: "STEP exports now open in external CAD",
|
|
41123
|
+
summary: "Exported STEP files carry the AP214 product/representation anchor and mm units, so Shapr3D, SolidWorks, and Fusion no longer reject them as containing no 3D geometry.",
|
|
41124
|
+
features: [
|
|
41125
|
+
"step-export",
|
|
41126
|
+
"interop"
|
|
41127
|
+
],
|
|
41128
|
+
mcpTools: [
|
|
41129
|
+
"export_cad"
|
|
41130
|
+
]
|
|
41131
|
+
},
|
|
41076
41132
|
{
|
|
41077
41133
|
id: "2026-07-26-step-export-booleans",
|
|
41078
41134
|
version: "0.9.4",
|
|
@@ -41090,6 +41146,19 @@ var init_CHANGELOG = __esm({
|
|
|
41090
41146
|
"export_cad"
|
|
41091
41147
|
]
|
|
41092
41148
|
},
|
|
41149
|
+
{
|
|
41150
|
+
id: "2026-07-26-step-analytic-circle-edges",
|
|
41151
|
+
version: "0.9.4",
|
|
41152
|
+
date: "2026-07-26",
|
|
41153
|
+
category: "fix",
|
|
41154
|
+
title: "STEP export: curved faces survive third-party import",
|
|
41155
|
+
summary: "Circular edges now export as analytic CIRCLEs instead of chord polylines, so importers like Shapr3D keep cylinder walls and annular faces at the spec 1e-6 accuracy.",
|
|
41156
|
+
features: [
|
|
41157
|
+
"step",
|
|
41158
|
+
"export",
|
|
41159
|
+
"kernel"
|
|
41160
|
+
]
|
|
41161
|
+
},
|
|
41093
41162
|
{
|
|
41094
41163
|
id: "2026-07-26-render-loon-directly",
|
|
41095
41164
|
version: "0.9.4",
|
|
@@ -53175,6 +53244,693 @@ var init_artifact_route = __esm({
|
|
|
53175
53244
|
}
|
|
53176
53245
|
});
|
|
53177
53246
|
|
|
53247
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/inMemory.js
|
|
53248
|
+
var InMemoryTransport;
|
|
53249
|
+
var init_inMemory = __esm({
|
|
53250
|
+
"node_modules/@modelcontextprotocol/sdk/dist/esm/inMemory.js"() {
|
|
53251
|
+
InMemoryTransport = class _InMemoryTransport {
|
|
53252
|
+
constructor() {
|
|
53253
|
+
this._messageQueue = [];
|
|
53254
|
+
}
|
|
53255
|
+
/**
|
|
53256
|
+
* Creates a pair of linked in-memory transports that can communicate with each other. One should be passed to a Client and one to a Server.
|
|
53257
|
+
*/
|
|
53258
|
+
static createLinkedPair() {
|
|
53259
|
+
const clientTransport = new _InMemoryTransport();
|
|
53260
|
+
const serverTransport = new _InMemoryTransport();
|
|
53261
|
+
clientTransport._otherTransport = serverTransport;
|
|
53262
|
+
serverTransport._otherTransport = clientTransport;
|
|
53263
|
+
return [clientTransport, serverTransport];
|
|
53264
|
+
}
|
|
53265
|
+
async start() {
|
|
53266
|
+
while (this._messageQueue.length > 0) {
|
|
53267
|
+
const queuedMessage = this._messageQueue.shift();
|
|
53268
|
+
this.onmessage?.(queuedMessage.message, queuedMessage.extra);
|
|
53269
|
+
}
|
|
53270
|
+
}
|
|
53271
|
+
async close() {
|
|
53272
|
+
const other = this._otherTransport;
|
|
53273
|
+
this._otherTransport = void 0;
|
|
53274
|
+
await other?.close();
|
|
53275
|
+
this.onclose?.();
|
|
53276
|
+
}
|
|
53277
|
+
/**
|
|
53278
|
+
* Sends a message with optional auth info.
|
|
53279
|
+
* This is useful for testing authentication scenarios.
|
|
53280
|
+
*/
|
|
53281
|
+
async send(message, options) {
|
|
53282
|
+
if (!this._otherTransport) {
|
|
53283
|
+
throw new Error("Not connected");
|
|
53284
|
+
}
|
|
53285
|
+
if (this._otherTransport.onmessage) {
|
|
53286
|
+
this._otherTransport.onmessage(message, { authInfo: options?.authInfo });
|
|
53287
|
+
} else {
|
|
53288
|
+
this._otherTransport._messageQueue.push({ message, extra: { authInfo: options?.authInfo } });
|
|
53289
|
+
}
|
|
53290
|
+
}
|
|
53291
|
+
};
|
|
53292
|
+
}
|
|
53293
|
+
});
|
|
53294
|
+
|
|
53295
|
+
// src/protocol-2026.ts
|
|
53296
|
+
import { EventEmitter } from "node:events";
|
|
53297
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
53298
|
+
function header(headers, name) {
|
|
53299
|
+
if (!headers) return void 0;
|
|
53300
|
+
const lower = name.toLowerCase();
|
|
53301
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
53302
|
+
if (k.toLowerCase() !== lower) continue;
|
|
53303
|
+
return Array.isArray(v) ? v[0] : v;
|
|
53304
|
+
}
|
|
53305
|
+
return void 0;
|
|
53306
|
+
}
|
|
53307
|
+
function metaOf(msg) {
|
|
53308
|
+
const params = msg?.params;
|
|
53309
|
+
const meta = params?._meta;
|
|
53310
|
+
return meta && typeof meta === "object" ? meta : void 0;
|
|
53311
|
+
}
|
|
53312
|
+
function isModernMessage(msg, headers) {
|
|
53313
|
+
const first = Array.isArray(msg) ? msg[0] : msg;
|
|
53314
|
+
if (!first || typeof first !== "object") return false;
|
|
53315
|
+
const method = first.method;
|
|
53316
|
+
if (typeof method === "string" && MODERN_ONLY_METHODS.has(method)) return true;
|
|
53317
|
+
const declared = metaOf(first)?.[META_PROTOCOL_VERSION];
|
|
53318
|
+
if (typeof declared === "string") return true;
|
|
53319
|
+
return header(headers, "mcp-method") !== void 0;
|
|
53320
|
+
}
|
|
53321
|
+
function decodeHeaderValue(value) {
|
|
53322
|
+
if (!value.startsWith(BASE64_SENTINEL_PREFIX) || !value.endsWith(BASE64_SENTINEL_SUFFIX) || value.length < BASE64_SENTINEL_PREFIX.length + BASE64_SENTINEL_SUFFIX.length) {
|
|
53323
|
+
return value;
|
|
53324
|
+
}
|
|
53325
|
+
const encoded = value.slice(
|
|
53326
|
+
BASE64_SENTINEL_PREFIX.length,
|
|
53327
|
+
value.length - BASE64_SENTINEL_SUFFIX.length
|
|
53328
|
+
);
|
|
53329
|
+
try {
|
|
53330
|
+
return Buffer.from(encoded, "base64").toString("utf-8");
|
|
53331
|
+
} catch {
|
|
53332
|
+
return value;
|
|
53333
|
+
}
|
|
53334
|
+
}
|
|
53335
|
+
function errorResponse(id, code, message, data) {
|
|
53336
|
+
return {
|
|
53337
|
+
jsonrpc: "2.0",
|
|
53338
|
+
id: id ?? null,
|
|
53339
|
+
error: data === void 0 ? { code, message } : { code, message, data }
|
|
53340
|
+
};
|
|
53341
|
+
}
|
|
53342
|
+
function unsupportedVersion(id, requested) {
|
|
53343
|
+
return {
|
|
53344
|
+
status: 400,
|
|
53345
|
+
body: errorResponse(
|
|
53346
|
+
id,
|
|
53347
|
+
ERR_UNSUPPORTED_PROTOCOL_VERSION,
|
|
53348
|
+
"Unsupported protocol version",
|
|
53349
|
+
{ supported: SUPPORTED_PROTOCOL_VERSIONS2, requested }
|
|
53350
|
+
)
|
|
53351
|
+
};
|
|
53352
|
+
}
|
|
53353
|
+
function headerMismatch(id, message) {
|
|
53354
|
+
return {
|
|
53355
|
+
status: 400,
|
|
53356
|
+
body: errorResponse(id, ERR_HEADER_MISMATCH, `Header mismatch: ${message}`)
|
|
53357
|
+
};
|
|
53358
|
+
}
|
|
53359
|
+
function pruneTasks() {
|
|
53360
|
+
const now = Date.now();
|
|
53361
|
+
for (const [id, t2] of tasks) {
|
|
53362
|
+
if (t2.expiresAt <= now) {
|
|
53363
|
+
t2.dispose?.();
|
|
53364
|
+
tasks.delete(id);
|
|
53365
|
+
}
|
|
53366
|
+
}
|
|
53367
|
+
}
|
|
53368
|
+
function touchTask(t2, status, message) {
|
|
53369
|
+
if (status) t2.status = status;
|
|
53370
|
+
if (message !== void 0) t2.statusMessage = message;
|
|
53371
|
+
t2.lastUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
53372
|
+
bus.emit(EVT_TASK, detailedTask(t2));
|
|
53373
|
+
}
|
|
53374
|
+
function detailedTask(t2) {
|
|
53375
|
+
const base = {
|
|
53376
|
+
taskId: t2.taskId,
|
|
53377
|
+
status: t2.status,
|
|
53378
|
+
createdAt: t2.createdAt,
|
|
53379
|
+
lastUpdatedAt: t2.lastUpdatedAt,
|
|
53380
|
+
ttlMs: TASK_TTL_MS,
|
|
53381
|
+
pollIntervalMs: TASK_POLL_INTERVAL_MS
|
|
53382
|
+
};
|
|
53383
|
+
if (t2.statusMessage !== void 0) base.statusMessage = t2.statusMessage;
|
|
53384
|
+
if (t2.status === "input_required") base.inputRequests = t2.inputRequests;
|
|
53385
|
+
if (t2.status === "completed") base.result = t2.result ?? {};
|
|
53386
|
+
if (t2.status === "failed") base.error = t2.error ?? { code: ERR_INTERNAL, message: "unknown" };
|
|
53387
|
+
return base;
|
|
53388
|
+
}
|
|
53389
|
+
async function openBridge(createServer2, clientInfo, clientCapabilities, hooks) {
|
|
53390
|
+
const [clientSide, serverSide] = InMemoryTransport.createLinkedPair();
|
|
53391
|
+
let nextId3 = 1;
|
|
53392
|
+
const pending2 = /* @__PURE__ */ new Map();
|
|
53393
|
+
clientSide.onmessage = (msg) => {
|
|
53394
|
+
const m = msg;
|
|
53395
|
+
const id = m.id;
|
|
53396
|
+
if (id !== void 0 && ("result" in m || "error" in m)) {
|
|
53397
|
+
pending2.get(id)?.(m);
|
|
53398
|
+
pending2.delete(id);
|
|
53399
|
+
return;
|
|
53400
|
+
}
|
|
53401
|
+
if (id !== void 0 && typeof m.method === "string") {
|
|
53402
|
+
void hooks.onServerRequest(
|
|
53403
|
+
m.method,
|
|
53404
|
+
m.params ?? {}
|
|
53405
|
+
).then(
|
|
53406
|
+
(result) => clientSide.send({ jsonrpc: "2.0", id, result })
|
|
53407
|
+
).catch(
|
|
53408
|
+
() => clientSide.send({
|
|
53409
|
+
jsonrpc: "2.0",
|
|
53410
|
+
id,
|
|
53411
|
+
error: { code: ERR_INTERNAL, message: "input bridge failed" }
|
|
53412
|
+
})
|
|
53413
|
+
);
|
|
53414
|
+
return;
|
|
53415
|
+
}
|
|
53416
|
+
if (typeof m.method === "string" && id === void 0) {
|
|
53417
|
+
hooks.onNotification?.(m);
|
|
53418
|
+
}
|
|
53419
|
+
};
|
|
53420
|
+
await clientSide.start();
|
|
53421
|
+
const server = await createServer2();
|
|
53422
|
+
await server.connect(serverSide);
|
|
53423
|
+
const rpc = (method, params) => {
|
|
53424
|
+
const id = nextId3++;
|
|
53425
|
+
return new Promise((resolve5) => {
|
|
53426
|
+
pending2.set(id, (m) => resolve5(m));
|
|
53427
|
+
void clientSide.send({
|
|
53428
|
+
jsonrpc: "2.0",
|
|
53429
|
+
id,
|
|
53430
|
+
method,
|
|
53431
|
+
params: params ?? {}
|
|
53432
|
+
});
|
|
53433
|
+
});
|
|
53434
|
+
};
|
|
53435
|
+
const init2 = await rpc("initialize", {
|
|
53436
|
+
protocolVersion: BRIDGE_VERSION,
|
|
53437
|
+
capabilities: clientCapabilities,
|
|
53438
|
+
clientInfo
|
|
53439
|
+
});
|
|
53440
|
+
await clientSide.send({
|
|
53441
|
+
jsonrpc: "2.0",
|
|
53442
|
+
method: "notifications/initialized"
|
|
53443
|
+
});
|
|
53444
|
+
return {
|
|
53445
|
+
rpc,
|
|
53446
|
+
handshake: init2.result ?? {},
|
|
53447
|
+
close: async () => {
|
|
53448
|
+
pending2.clear();
|
|
53449
|
+
await server.close().catch(() => {
|
|
53450
|
+
});
|
|
53451
|
+
await clientSide.close().catch(() => {
|
|
53452
|
+
});
|
|
53453
|
+
}
|
|
53454
|
+
};
|
|
53455
|
+
}
|
|
53456
|
+
async function handleModernRequest(msg, opts) {
|
|
53457
|
+
if (Array.isArray(msg)) {
|
|
53458
|
+
return {
|
|
53459
|
+
status: 400,
|
|
53460
|
+
body: errorResponse(
|
|
53461
|
+
null,
|
|
53462
|
+
ERR_INVALID_PARAMS,
|
|
53463
|
+
"Batched requests are not supported; send one JSON-RPC message per POST"
|
|
53464
|
+
)
|
|
53465
|
+
};
|
|
53466
|
+
}
|
|
53467
|
+
if (!msg || typeof msg !== "object") {
|
|
53468
|
+
return {
|
|
53469
|
+
status: 400,
|
|
53470
|
+
body: errorResponse(null, ERR_INVALID_PARAMS, "Malformed JSON-RPC message")
|
|
53471
|
+
};
|
|
53472
|
+
}
|
|
53473
|
+
const req = msg;
|
|
53474
|
+
const id = req.id;
|
|
53475
|
+
const method = req.method;
|
|
53476
|
+
const params = req.params ?? {};
|
|
53477
|
+
const meta = metaOf(req) ?? {};
|
|
53478
|
+
if (id === void 0 || id === null) return { status: 202, body: null };
|
|
53479
|
+
if (typeof method !== "string") {
|
|
53480
|
+
return {
|
|
53481
|
+
status: 400,
|
|
53482
|
+
body: errorResponse(id, ERR_INVALID_PARAMS, "Missing JSON-RPC method")
|
|
53483
|
+
};
|
|
53484
|
+
}
|
|
53485
|
+
const bodyVersion = meta[META_PROTOCOL_VERSION];
|
|
53486
|
+
const headerVersion = header(opts.headers, "mcp-protocol-version");
|
|
53487
|
+
if (typeof bodyVersion === "string" && headerVersion !== void 0 && headerVersion !== bodyVersion) {
|
|
53488
|
+
return headerMismatch(
|
|
53489
|
+
id,
|
|
53490
|
+
`MCP-Protocol-Version header value '${headerVersion}' does not match body value '${bodyVersion}'`
|
|
53491
|
+
);
|
|
53492
|
+
}
|
|
53493
|
+
const version2 = typeof bodyVersion === "string" ? bodyVersion : headerVersion;
|
|
53494
|
+
if (version2 === void 0) {
|
|
53495
|
+
if (method !== "server/discover") {
|
|
53496
|
+
return unsupportedVersion(id, "(unspecified)");
|
|
53497
|
+
}
|
|
53498
|
+
} else if (version2 !== PROTOCOL_2026) {
|
|
53499
|
+
return unsupportedVersion(id, version2);
|
|
53500
|
+
}
|
|
53501
|
+
if (opts.headers) {
|
|
53502
|
+
const methodHeader = header(opts.headers, "mcp-method");
|
|
53503
|
+
if (methodHeader === void 0) {
|
|
53504
|
+
return headerMismatch(id, "required header Mcp-Method is missing");
|
|
53505
|
+
}
|
|
53506
|
+
if (methodHeader !== method) {
|
|
53507
|
+
return headerMismatch(
|
|
53508
|
+
id,
|
|
53509
|
+
`Mcp-Method header value '${methodHeader}' does not match body value '${method}'`
|
|
53510
|
+
);
|
|
53511
|
+
}
|
|
53512
|
+
const expectedName = NAME_HEADER_METHODS.has(method) ? params.name : method === "resources/read" ? params.uri : void 0;
|
|
53513
|
+
if (typeof expectedName === "string") {
|
|
53514
|
+
const nameHeader = header(opts.headers, "mcp-name");
|
|
53515
|
+
if (nameHeader === void 0) {
|
|
53516
|
+
return headerMismatch(id, "required header Mcp-Name is missing");
|
|
53517
|
+
}
|
|
53518
|
+
if (decodeHeaderValue(nameHeader) !== expectedName) {
|
|
53519
|
+
return headerMismatch(
|
|
53520
|
+
id,
|
|
53521
|
+
`Mcp-Name header value does not match body value '${expectedName}'`
|
|
53522
|
+
);
|
|
53523
|
+
}
|
|
53524
|
+
}
|
|
53525
|
+
}
|
|
53526
|
+
if (method === "tasks/get" || method === "tasks/update" || method === "tasks/cancel") {
|
|
53527
|
+
return handleTaskMethod(id, method, params);
|
|
53528
|
+
}
|
|
53529
|
+
if (method === "initialize") {
|
|
53530
|
+
return {
|
|
53531
|
+
status: 404,
|
|
53532
|
+
body: errorResponse(
|
|
53533
|
+
id,
|
|
53534
|
+
ERR_METHOD_NOT_FOUND,
|
|
53535
|
+
`'initialize' was removed in protocol ${PROTOCOL_2026}; use 'server/discover'. This server supports: ${SUPPORTED_PROTOCOL_VERSIONS2.join(", ")}`
|
|
53536
|
+
)
|
|
53537
|
+
};
|
|
53538
|
+
}
|
|
53539
|
+
if (method !== "server/discover" && !FORWARDED_METHODS.has(method)) {
|
|
53540
|
+
return {
|
|
53541
|
+
status: 404,
|
|
53542
|
+
body: errorResponse(id, ERR_METHOD_NOT_FOUND, `Unknown method '${method}'`)
|
|
53543
|
+
};
|
|
53544
|
+
}
|
|
53545
|
+
const rawClientInfo = meta[META_CLIENT_INFO];
|
|
53546
|
+
const infoObj = rawClientInfo && typeof rawClientInfo === "object" ? rawClientInfo : {};
|
|
53547
|
+
const clientInfo = {
|
|
53548
|
+
name: typeof infoObj.name === "string" ? infoObj.name : "unknown",
|
|
53549
|
+
version: typeof infoObj.version === "string" ? infoObj.version : "0.0.0"
|
|
53550
|
+
};
|
|
53551
|
+
const rawCaps = meta[META_CLIENT_CAPABILITIES];
|
|
53552
|
+
const clientCapabilities = rawCaps && typeof rawCaps === "object" ? rawCaps : {};
|
|
53553
|
+
const wantsLogs = typeof meta[META_LOG_LEVEL] === "string";
|
|
53554
|
+
const inputResponses = params.inputResponses && typeof params.inputResponses === "object" ? params.inputResponses : {};
|
|
53555
|
+
const extCaps = clientCapabilities.extensions ?? {};
|
|
53556
|
+
const asTask = method === "tools/call" && TASKS_EXTENSION in extCaps && typeof params.name === "string" && LONG_RUNNING_TOOLS.has(params.name);
|
|
53557
|
+
let inputSeq = 0;
|
|
53558
|
+
const capturedInputRequests = {};
|
|
53559
|
+
const onServerRequest = async (reqMethod, reqParams) => {
|
|
53560
|
+
if (reqMethod !== "elicitation/create") {
|
|
53561
|
+
throw new Error(`unsupported server-initiated request ${reqMethod}`);
|
|
53562
|
+
}
|
|
53563
|
+
if (bridgeRef) {
|
|
53564
|
+
const parked = taskElicitation(bridgeRef, reqParams);
|
|
53565
|
+
if (parked) return parked;
|
|
53566
|
+
}
|
|
53567
|
+
const key = `input_${++inputSeq}`;
|
|
53568
|
+
const provided = inputResponses[key];
|
|
53569
|
+
if (provided) return provided;
|
|
53570
|
+
if (!MRTR_METHODS.has(method)) return { action: "cancel" };
|
|
53571
|
+
const { elicitationId: _drop, ...cleanParams } = reqParams;
|
|
53572
|
+
capturedInputRequests[key] = {
|
|
53573
|
+
method: "elicitation/create",
|
|
53574
|
+
params: cleanParams
|
|
53575
|
+
};
|
|
53576
|
+
return { action: "cancel" };
|
|
53577
|
+
};
|
|
53578
|
+
let bridge;
|
|
53579
|
+
let bridgeRef;
|
|
53580
|
+
try {
|
|
53581
|
+
bridge = bridgeRef = await openBridge(opts.createServer, clientInfo, clientCapabilities, {
|
|
53582
|
+
onNotification: (n) => {
|
|
53583
|
+
const nm = n.method;
|
|
53584
|
+
if (nm === "notifications/message" && !wantsLogs) return;
|
|
53585
|
+
opts.onNotification?.(n);
|
|
53586
|
+
},
|
|
53587
|
+
onServerRequest
|
|
53588
|
+
});
|
|
53589
|
+
if (method === "server/discover") {
|
|
53590
|
+
const info = bridge.handshake;
|
|
53591
|
+
const capabilities = { ...info.capabilities ?? {} };
|
|
53592
|
+
capabilities.extensions = {
|
|
53593
|
+
...capabilities.extensions ?? {},
|
|
53594
|
+
[TASKS_EXTENSION]: {}
|
|
53595
|
+
};
|
|
53596
|
+
const result2 = {
|
|
53597
|
+
resultType: "complete",
|
|
53598
|
+
supportedVersions: SUPPORTED_PROTOCOL_VERSIONS2,
|
|
53599
|
+
capabilities,
|
|
53600
|
+
_meta: { [META_SERVER_INFO]: info.serverInfo ?? {} }
|
|
53601
|
+
};
|
|
53602
|
+
if (info.instructions) result2.instructions = info.instructions;
|
|
53603
|
+
decorateCache(result2, "server/discover");
|
|
53604
|
+
return { status: 200, body: { jsonrpc: "2.0", id, result: result2 } };
|
|
53605
|
+
}
|
|
53606
|
+
const serverInfo = bridge.handshake.serverInfo ?? {
|
|
53607
|
+
name: "vcad",
|
|
53608
|
+
version: "0.0.0"
|
|
53609
|
+
};
|
|
53610
|
+
const forwarded = stripModernFields(params);
|
|
53611
|
+
if (asTask) {
|
|
53612
|
+
pruneTasks();
|
|
53613
|
+
const record2 = createTaskRecord(params.name);
|
|
53614
|
+
const owned = bridge;
|
|
53615
|
+
bridge = void 0;
|
|
53616
|
+
runTaskInBackground(record2, owned, method, forwarded, inputResponses);
|
|
53617
|
+
const result2 = {
|
|
53618
|
+
resultType: "task",
|
|
53619
|
+
...detailedTask(record2),
|
|
53620
|
+
_meta: { [META_SERVER_INFO]: serverInfo }
|
|
53621
|
+
};
|
|
53622
|
+
return { status: 200, body: { jsonrpc: "2.0", id, result: result2 } };
|
|
53623
|
+
}
|
|
53624
|
+
const reply = await bridge.rpc(method, forwarded);
|
|
53625
|
+
if (Object.keys(capturedInputRequests).length > 0) {
|
|
53626
|
+
const result2 = {
|
|
53627
|
+
resultType: "input_required",
|
|
53628
|
+
inputRequests: capturedInputRequests,
|
|
53629
|
+
_meta: { [META_SERVER_INFO]: serverInfo }
|
|
53630
|
+
};
|
|
53631
|
+
return { status: 200, body: { jsonrpc: "2.0", id, result: result2 } };
|
|
53632
|
+
}
|
|
53633
|
+
if (reply.error) {
|
|
53634
|
+
const code = reply.error.code === LEGACY_RESOURCE_NOT_FOUND ? ERR_INVALID_PARAMS : reply.error.code;
|
|
53635
|
+
return {
|
|
53636
|
+
status: code === ERR_METHOD_NOT_FOUND ? 404 : 200,
|
|
53637
|
+
body: errorResponse(id, code, reply.error.message, reply.error.data)
|
|
53638
|
+
};
|
|
53639
|
+
}
|
|
53640
|
+
const result = { ...reply.result ?? {} };
|
|
53641
|
+
result.resultType = "complete";
|
|
53642
|
+
const resultMeta = result._meta && typeof result._meta === "object" ? { ...result._meta } : {};
|
|
53643
|
+
resultMeta[META_SERVER_INFO] = serverInfo;
|
|
53644
|
+
result._meta = resultMeta;
|
|
53645
|
+
decorateCache(result, method);
|
|
53646
|
+
if (method === "tools/call" && params.name === "set_tool_packs") {
|
|
53647
|
+
bus.emit(EVT_TOOLS_CHANGED);
|
|
53648
|
+
}
|
|
53649
|
+
return { status: 200, body: { jsonrpc: "2.0", id, result } };
|
|
53650
|
+
} catch (err7) {
|
|
53651
|
+
return {
|
|
53652
|
+
status: 500,
|
|
53653
|
+
body: errorResponse(
|
|
53654
|
+
id,
|
|
53655
|
+
ERR_INTERNAL,
|
|
53656
|
+
err7 instanceof Error ? err7.message : String(err7)
|
|
53657
|
+
)
|
|
53658
|
+
};
|
|
53659
|
+
} finally {
|
|
53660
|
+
await bridge?.close();
|
|
53661
|
+
}
|
|
53662
|
+
}
|
|
53663
|
+
function decorateCache(result, method) {
|
|
53664
|
+
const ttl = CACHEABLE_METHODS.get(method);
|
|
53665
|
+
if (ttl === void 0) return;
|
|
53666
|
+
result.ttlMs = ttl;
|
|
53667
|
+
result.cacheScope = CACHE_SCOPE;
|
|
53668
|
+
}
|
|
53669
|
+
function stripModernFields(params) {
|
|
53670
|
+
const out = { ...params };
|
|
53671
|
+
delete out.inputResponses;
|
|
53672
|
+
delete out.requestState;
|
|
53673
|
+
const meta = out._meta;
|
|
53674
|
+
if (meta && typeof meta === "object") {
|
|
53675
|
+
const rest = { ...meta };
|
|
53676
|
+
delete rest[META_PROTOCOL_VERSION];
|
|
53677
|
+
delete rest[META_CLIENT_CAPABILITIES];
|
|
53678
|
+
delete rest[META_CLIENT_INFO];
|
|
53679
|
+
delete rest[META_LOG_LEVEL];
|
|
53680
|
+
if (Object.keys(rest).length === 0) delete out._meta;
|
|
53681
|
+
else out._meta = rest;
|
|
53682
|
+
}
|
|
53683
|
+
return out;
|
|
53684
|
+
}
|
|
53685
|
+
function createTaskRecord(toolName) {
|
|
53686
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
53687
|
+
const record2 = {
|
|
53688
|
+
taskId: `task_${randomUUID2().slice(0, 13)}`,
|
|
53689
|
+
status: "working",
|
|
53690
|
+
statusMessage: `running ${toolName}`,
|
|
53691
|
+
createdAt: now,
|
|
53692
|
+
lastUpdatedAt: now,
|
|
53693
|
+
expiresAt: Date.now() + TASK_TTL_MS,
|
|
53694
|
+
toolName,
|
|
53695
|
+
inputRequests: {},
|
|
53696
|
+
pendingInputs: /* @__PURE__ */ new Map(),
|
|
53697
|
+
cancelRequested: false
|
|
53698
|
+
};
|
|
53699
|
+
tasks.set(record2.taskId, record2);
|
|
53700
|
+
return record2;
|
|
53701
|
+
}
|
|
53702
|
+
function runTaskInBackground(record2, bridge, method, forwarded, presetResponses) {
|
|
53703
|
+
record2.dispose = () => {
|
|
53704
|
+
void bridge.close();
|
|
53705
|
+
};
|
|
53706
|
+
taskInputHooks.set(bridge, { record: record2, presetResponses, seq: 0 });
|
|
53707
|
+
void bridge.rpc(method, forwarded).then((reply) => {
|
|
53708
|
+
if (record2.status === "cancelled") return;
|
|
53709
|
+
if (reply.error) {
|
|
53710
|
+
record2.error = reply.error;
|
|
53711
|
+
touchTask(record2, "failed", reply.error.message);
|
|
53712
|
+
} else {
|
|
53713
|
+
const result = { ...reply.result ?? {} };
|
|
53714
|
+
result.resultType = "complete";
|
|
53715
|
+
record2.result = result;
|
|
53716
|
+
touchTask(record2, "completed", `${record2.toolName} finished`);
|
|
53717
|
+
}
|
|
53718
|
+
}).catch((err7) => {
|
|
53719
|
+
record2.error = {
|
|
53720
|
+
code: ERR_INTERNAL,
|
|
53721
|
+
message: err7 instanceof Error ? err7.message : String(err7)
|
|
53722
|
+
};
|
|
53723
|
+
touchTask(record2, "failed");
|
|
53724
|
+
}).finally(() => {
|
|
53725
|
+
taskInputHooks.delete(bridge);
|
|
53726
|
+
void bridge.close();
|
|
53727
|
+
record2.dispose = void 0;
|
|
53728
|
+
});
|
|
53729
|
+
}
|
|
53730
|
+
function taskElicitation(bridge, reqParams) {
|
|
53731
|
+
const ctx = taskInputHooks.get(bridge);
|
|
53732
|
+
if (!ctx) return void 0;
|
|
53733
|
+
const { record: record2, presetResponses } = ctx;
|
|
53734
|
+
const key = `input_${++ctx.seq}`;
|
|
53735
|
+
const preset = presetResponses[key];
|
|
53736
|
+
if (preset) return Promise.resolve(preset);
|
|
53737
|
+
if (record2.cancelRequested) return Promise.resolve({ action: "cancel" });
|
|
53738
|
+
const { elicitationId: _drop, ...cleanParams } = reqParams;
|
|
53739
|
+
record2.inputRequests[key] = {
|
|
53740
|
+
method: "elicitation/create",
|
|
53741
|
+
params: cleanParams
|
|
53742
|
+
};
|
|
53743
|
+
return new Promise((resolve5) => {
|
|
53744
|
+
record2.pendingInputs.set(key, resolve5);
|
|
53745
|
+
touchTask(record2, "input_required", "waiting for client input");
|
|
53746
|
+
});
|
|
53747
|
+
}
|
|
53748
|
+
function handleTaskMethod(id, method, params) {
|
|
53749
|
+
pruneTasks();
|
|
53750
|
+
const taskId = typeof params.taskId === "string" ? params.taskId : "";
|
|
53751
|
+
const record2 = tasks.get(taskId);
|
|
53752
|
+
if (!record2) {
|
|
53753
|
+
return {
|
|
53754
|
+
status: 200,
|
|
53755
|
+
body: errorResponse(
|
|
53756
|
+
id,
|
|
53757
|
+
ERR_INVALID_PARAMS,
|
|
53758
|
+
`Unknown taskId '${taskId}' \u2014 expired, cancelled long ago, or from a previous server instance`
|
|
53759
|
+
)
|
|
53760
|
+
};
|
|
53761
|
+
}
|
|
53762
|
+
if (method === "tasks/get") {
|
|
53763
|
+
const result = { resultType: "complete", ...detailedTask(record2) };
|
|
53764
|
+
return { status: 200, body: { jsonrpc: "2.0", id, result } };
|
|
53765
|
+
}
|
|
53766
|
+
if (method === "tasks/update") {
|
|
53767
|
+
const responses = params.inputResponses && typeof params.inputResponses === "object" ? params.inputResponses : {};
|
|
53768
|
+
for (const [key, response] of Object.entries(responses)) {
|
|
53769
|
+
const resolve5 = record2.pendingInputs.get(key);
|
|
53770
|
+
if (!resolve5) continue;
|
|
53771
|
+
record2.pendingInputs.delete(key);
|
|
53772
|
+
delete record2.inputRequests[key];
|
|
53773
|
+
resolve5(response);
|
|
53774
|
+
}
|
|
53775
|
+
if (record2.status === "input_required" && Object.keys(record2.inputRequests).length === 0) {
|
|
53776
|
+
touchTask(record2, "working", `running ${record2.toolName}`);
|
|
53777
|
+
}
|
|
53778
|
+
return {
|
|
53779
|
+
status: 200,
|
|
53780
|
+
body: { jsonrpc: "2.0", id, result: { resultType: "complete" } }
|
|
53781
|
+
};
|
|
53782
|
+
}
|
|
53783
|
+
record2.cancelRequested = true;
|
|
53784
|
+
if (record2.status === "working" || record2.status === "input_required") {
|
|
53785
|
+
for (const [key, resolve5] of record2.pendingInputs) {
|
|
53786
|
+
record2.pendingInputs.delete(key);
|
|
53787
|
+
delete record2.inputRequests[key];
|
|
53788
|
+
resolve5({ action: "cancel" });
|
|
53789
|
+
}
|
|
53790
|
+
touchTask(record2, "cancelled", "cancelled by client");
|
|
53791
|
+
}
|
|
53792
|
+
return {
|
|
53793
|
+
status: 200,
|
|
53794
|
+
body: { jsonrpc: "2.0", id, result: { resultType: "complete" } }
|
|
53795
|
+
};
|
|
53796
|
+
}
|
|
53797
|
+
function handleModernListen(msg, sink) {
|
|
53798
|
+
const req = msg;
|
|
53799
|
+
const subscriptionId = req.id ?? null;
|
|
53800
|
+
const filter = req.params?.notifications && typeof req.params.notifications === "object" ? req.params.notifications : {};
|
|
53801
|
+
const honored = {};
|
|
53802
|
+
const listeners = [];
|
|
53803
|
+
if (filter.toolsListChanged === true) {
|
|
53804
|
+
honored.toolsListChanged = true;
|
|
53805
|
+
const onChange = () => sink.send({
|
|
53806
|
+
jsonrpc: "2.0",
|
|
53807
|
+
method: "notifications/tools/list_changed",
|
|
53808
|
+
params: { _meta: { [META_SUBSCRIPTION_ID]: subscriptionId } }
|
|
53809
|
+
});
|
|
53810
|
+
bus.on(EVT_TOOLS_CHANGED, onChange);
|
|
53811
|
+
listeners.push(() => bus.off(EVT_TOOLS_CHANGED, onChange));
|
|
53812
|
+
}
|
|
53813
|
+
const taskIds = Array.isArray(filter.taskIds) ? filter.taskIds.filter((t2) => typeof t2 === "string") : [];
|
|
53814
|
+
if (taskIds.length > 0) {
|
|
53815
|
+
honored.taskIds = taskIds;
|
|
53816
|
+
const wanted = new Set(taskIds);
|
|
53817
|
+
const onTask = (task) => {
|
|
53818
|
+
if (!wanted.has(task.taskId)) return;
|
|
53819
|
+
sink.send({
|
|
53820
|
+
jsonrpc: "2.0",
|
|
53821
|
+
method: "notifications/tasks",
|
|
53822
|
+
params: { _meta: { [META_SUBSCRIPTION_ID]: subscriptionId }, ...task }
|
|
53823
|
+
});
|
|
53824
|
+
};
|
|
53825
|
+
bus.on(EVT_TASK, onTask);
|
|
53826
|
+
listeners.push(() => bus.off(EVT_TASK, onTask));
|
|
53827
|
+
}
|
|
53828
|
+
sink.send({
|
|
53829
|
+
jsonrpc: "2.0",
|
|
53830
|
+
method: "notifications/subscriptions/acknowledged",
|
|
53831
|
+
params: {
|
|
53832
|
+
_meta: { [META_SUBSCRIPTION_ID]: subscriptionId },
|
|
53833
|
+
notifications: honored
|
|
53834
|
+
}
|
|
53835
|
+
});
|
|
53836
|
+
return {
|
|
53837
|
+
close: () => {
|
|
53838
|
+
for (const off of listeners) off();
|
|
53839
|
+
listeners.length = 0;
|
|
53840
|
+
}
|
|
53841
|
+
};
|
|
53842
|
+
}
|
|
53843
|
+
var PROTOCOL_2026, BRIDGE_VERSION, SUPPORTED_PROTOCOL_VERSIONS2, META_PROTOCOL_VERSION, META_CLIENT_CAPABILITIES, META_CLIENT_INFO, META_SERVER_INFO, META_LOG_LEVEL, META_SUBSCRIPTION_ID, TASKS_EXTENSION, ERR_HEADER_MISMATCH, ERR_UNSUPPORTED_PROTOCOL_VERSION, ERR_METHOD_NOT_FOUND, ERR_INVALID_PARAMS, ERR_INTERNAL, LEGACY_RESOURCE_NOT_FOUND, LIST_TTL_MS, DISCOVER_TTL_MS, CACHE_SCOPE, CACHEABLE_METHODS, FORWARDED_METHODS, NAME_HEADER_METHODS, MRTR_METHODS, LONG_RUNNING_TOOLS, TASK_TTL_MS, TASK_POLL_INTERVAL_MS, MODERN_ONLY_METHODS, BASE64_SENTINEL_PREFIX, BASE64_SENTINEL_SUFFIX, bus, EVT_TOOLS_CHANGED, EVT_TASK, tasks, taskInputHooks;
|
|
53844
|
+
var init_protocol_2026 = __esm({
|
|
53845
|
+
"src/protocol-2026.ts"() {
|
|
53846
|
+
"use strict";
|
|
53847
|
+
init_inMemory();
|
|
53848
|
+
PROTOCOL_2026 = "2026-07-28";
|
|
53849
|
+
BRIDGE_VERSION = "2025-11-25";
|
|
53850
|
+
SUPPORTED_PROTOCOL_VERSIONS2 = [
|
|
53851
|
+
PROTOCOL_2026,
|
|
53852
|
+
"2025-11-25",
|
|
53853
|
+
"2025-06-18",
|
|
53854
|
+
"2025-03-26",
|
|
53855
|
+
"2024-11-05"
|
|
53856
|
+
];
|
|
53857
|
+
META_PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
|
|
53858
|
+
META_CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
53859
|
+
META_CLIENT_INFO = "io.modelcontextprotocol/clientInfo";
|
|
53860
|
+
META_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
|
|
53861
|
+
META_LOG_LEVEL = "io.modelcontextprotocol/logLevel";
|
|
53862
|
+
META_SUBSCRIPTION_ID = "io.modelcontextprotocol/subscriptionId";
|
|
53863
|
+
TASKS_EXTENSION = "io.modelcontextprotocol/tasks";
|
|
53864
|
+
ERR_HEADER_MISMATCH = -32020;
|
|
53865
|
+
ERR_UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
53866
|
+
ERR_METHOD_NOT_FOUND = -32601;
|
|
53867
|
+
ERR_INVALID_PARAMS = -32602;
|
|
53868
|
+
ERR_INTERNAL = -32603;
|
|
53869
|
+
LEGACY_RESOURCE_NOT_FOUND = -32002;
|
|
53870
|
+
LIST_TTL_MS = 6e4;
|
|
53871
|
+
DISCOVER_TTL_MS = 3e5;
|
|
53872
|
+
CACHE_SCOPE = "private";
|
|
53873
|
+
CACHEABLE_METHODS = /* @__PURE__ */ new Map([
|
|
53874
|
+
["server/discover", DISCOVER_TTL_MS],
|
|
53875
|
+
["tools/list", LIST_TTL_MS],
|
|
53876
|
+
["prompts/list", LIST_TTL_MS],
|
|
53877
|
+
["resources/list", LIST_TTL_MS],
|
|
53878
|
+
["resources/templates/list", LIST_TTL_MS],
|
|
53879
|
+
["resources/read", LIST_TTL_MS]
|
|
53880
|
+
]);
|
|
53881
|
+
FORWARDED_METHODS = /* @__PURE__ */ new Set([
|
|
53882
|
+
"tools/list",
|
|
53883
|
+
"tools/call",
|
|
53884
|
+
"resources/list",
|
|
53885
|
+
"resources/templates/list",
|
|
53886
|
+
"resources/read",
|
|
53887
|
+
"prompts/list",
|
|
53888
|
+
"prompts/get",
|
|
53889
|
+
"completion/complete"
|
|
53890
|
+
]);
|
|
53891
|
+
NAME_HEADER_METHODS = /* @__PURE__ */ new Set(["tools/call", "prompts/get"]);
|
|
53892
|
+
MRTR_METHODS = /* @__PURE__ */ new Set(["tools/call", "prompts/get", "resources/read"]);
|
|
53893
|
+
LONG_RUNNING_TOOLS = /* @__PURE__ */ new Set([
|
|
53894
|
+
"route_nets",
|
|
53895
|
+
"route_diff_pair",
|
|
53896
|
+
"length_match_traces",
|
|
53897
|
+
"fab_prep",
|
|
53898
|
+
"fix_drc",
|
|
53899
|
+
"topology_optimize",
|
|
53900
|
+
"optimize_electrodes",
|
|
53901
|
+
"export_video",
|
|
53902
|
+
"render_sequence",
|
|
53903
|
+
"simulate_flow",
|
|
53904
|
+
"simulate_em",
|
|
53905
|
+
"simulate_photonics",
|
|
53906
|
+
"simulate_charged_particles",
|
|
53907
|
+
"simulate_neutron_shield",
|
|
53908
|
+
"simulate_lattice_gauge",
|
|
53909
|
+
"md_run",
|
|
53910
|
+
"minimize_energy",
|
|
53911
|
+
"homogenize_material",
|
|
53912
|
+
"design_material"
|
|
53913
|
+
]);
|
|
53914
|
+
TASK_TTL_MS = 30 * 6e4;
|
|
53915
|
+
TASK_POLL_INTERVAL_MS = 1e3;
|
|
53916
|
+
MODERN_ONLY_METHODS = /* @__PURE__ */ new Set([
|
|
53917
|
+
"server/discover",
|
|
53918
|
+
"subscriptions/listen",
|
|
53919
|
+
"tasks/get",
|
|
53920
|
+
"tasks/update",
|
|
53921
|
+
"tasks/cancel"
|
|
53922
|
+
]);
|
|
53923
|
+
BASE64_SENTINEL_PREFIX = "=?base64?";
|
|
53924
|
+
BASE64_SENTINEL_SUFFIX = "?=";
|
|
53925
|
+
bus = new EventEmitter();
|
|
53926
|
+
bus.setMaxListeners(100);
|
|
53927
|
+
EVT_TOOLS_CHANGED = "tools_list_changed";
|
|
53928
|
+
EVT_TASK = "task";
|
|
53929
|
+
tasks = /* @__PURE__ */ new Map();
|
|
53930
|
+
taskInputHooks = /* @__PURE__ */ new WeakMap();
|
|
53931
|
+
}
|
|
53932
|
+
});
|
|
53933
|
+
|
|
53178
53934
|
// src/viewer-html.generated.ts
|
|
53179
53935
|
var VIEWER_HTML;
|
|
53180
53936
|
var init_viewer_html_generated = __esm({
|
|
@@ -54791,7 +55547,7 @@ var init_client = __esm({
|
|
|
54791
55547
|
});
|
|
54792
55548
|
|
|
54793
55549
|
// src/fabricate/adapters/kerf.ts
|
|
54794
|
-
import { randomUUID as
|
|
55550
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
54795
55551
|
function kerfQuoteMode() {
|
|
54796
55552
|
return process.env.KERF_QUOTE_MODE === "live" ? "live" : "scripted";
|
|
54797
55553
|
}
|
|
@@ -54821,7 +55577,7 @@ function buildKerfSheetMetalIntent(p) {
|
|
|
54821
55577
|
files: p.files,
|
|
54822
55578
|
config: p.config,
|
|
54823
55579
|
quantity: p.quantity,
|
|
54824
|
-
idempotency_key: `vq_${
|
|
55580
|
+
idempotency_key: `vq_${randomUUID3()}`,
|
|
54825
55581
|
ship_to: quoteShipTo(),
|
|
54826
55582
|
budget_cap: { currency: "USD", amount_minor: 0 }
|
|
54827
55583
|
};
|
|
@@ -55185,7 +55941,7 @@ var init_types4 = __esm({
|
|
|
55185
55941
|
});
|
|
55186
55942
|
|
|
55187
55943
|
// src/tools/order.ts
|
|
55188
|
-
import { randomUUID as
|
|
55944
|
+
import { randomUUID as randomUUID4, createHash as createHash4 } from "node:crypto";
|
|
55189
55945
|
function quoteDfm(process3, metrics) {
|
|
55190
55946
|
const violations = [];
|
|
55191
55947
|
if (process3 !== "pcb" && !metrics.ok) {
|
|
@@ -55371,8 +56127,8 @@ async function quoteManufacturing(input, engine, store, user) {
|
|
|
55371
56127
|
}
|
|
55372
56128
|
const now = /* @__PURE__ */ new Date();
|
|
55373
56129
|
const expiresAt = new Date(now.getTime() + QUOTE_TTL_MS).toISOString();
|
|
55374
|
-
const quoteId =
|
|
55375
|
-
const orderId =
|
|
56130
|
+
const quoteId = randomUUID4();
|
|
56131
|
+
const orderId = randomUUID4();
|
|
55376
56132
|
const owner = ownerId(user);
|
|
55377
56133
|
const quote = {
|
|
55378
56134
|
quote_id: quoteId,
|
|
@@ -56734,7 +57490,7 @@ var init_clearance = __esm({
|
|
|
56734
57490
|
});
|
|
56735
57491
|
|
|
56736
57492
|
// src/tools/ordering.ts
|
|
56737
|
-
import { randomUUID as
|
|
57493
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
56738
57494
|
function orderingEnabled() {
|
|
56739
57495
|
return process.env.VCAD_FABRICATE_ORDERING === "1";
|
|
56740
57496
|
}
|
|
@@ -56768,7 +57524,7 @@ async function authorizeSpend(input, store, eventStore, user, elicit) {
|
|
|
56768
57524
|
}
|
|
56769
57525
|
const now = /* @__PURE__ */ new Date();
|
|
56770
57526
|
const authz = {
|
|
56771
|
-
id:
|
|
57527
|
+
id: randomUUID5(),
|
|
56772
57528
|
user_id: owner,
|
|
56773
57529
|
quote_id: order.quote_id,
|
|
56774
57530
|
kind: "one_time",
|
|
@@ -57308,7 +58064,7 @@ var init_mech_parts = __esm({
|
|
|
57308
58064
|
});
|
|
57309
58065
|
|
|
57310
58066
|
// src/tools/bom.ts
|
|
57311
|
-
import { randomUUID as
|
|
58067
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
57312
58068
|
function ok3(payload) {
|
|
57313
58069
|
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
|
|
57314
58070
|
}
|
|
@@ -57379,7 +58135,7 @@ async function buildLine(args, store, owner) {
|
|
|
57379
58135
|
if (kind !== "manufactured" && kind !== "cots") {
|
|
57380
58136
|
return { error: `Line kind must be 'manufactured' or 'cots', got "${kind}".` };
|
|
57381
58137
|
}
|
|
57382
|
-
const lineId =
|
|
58138
|
+
const lineId = randomUUID6().slice(0, 8);
|
|
57383
58139
|
const explicitUnitUsd = typeof args.unit_price_usd === "number" && Number.isFinite(args.unit_price_usd) ? args.unit_price_usd : null;
|
|
57384
58140
|
if (kind === "manufactured") {
|
|
57385
58141
|
const name2 = str(args.name);
|
|
@@ -57540,7 +58296,7 @@ async function bomCreate(input, store, user) {
|
|
|
57540
58296
|
const owner = ownerId(user);
|
|
57541
58297
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
57542
58298
|
const bom = {
|
|
57543
|
-
bom_id:
|
|
58299
|
+
bom_id: randomUUID6(),
|
|
57544
58300
|
title: str(args.title) ?? "Bill of Materials",
|
|
57545
58301
|
document_id: str(args.document_id),
|
|
57546
58302
|
assembly_notes: Array.isArray(args.assembly_notes) ? args.assembly_notes.map(String).filter((s) => s.trim()) : [],
|
|
@@ -71089,7 +71845,7 @@ function listEvalTasks(args) {
|
|
|
71089
71845
|
}
|
|
71090
71846
|
const tasksDir = join3(mechevalRoot, "tasks");
|
|
71091
71847
|
const suiteFilter = args.suite ? String(args.suite).toUpperCase() : null;
|
|
71092
|
-
const
|
|
71848
|
+
const tasks2 = [];
|
|
71093
71849
|
for (const file of readdirSync2(tasksDir).sort()) {
|
|
71094
71850
|
if (!file.endsWith(".json")) continue;
|
|
71095
71851
|
try {
|
|
@@ -71097,7 +71853,7 @@ function listEvalTasks(args) {
|
|
|
71097
71853
|
if (suiteFilter && String(raw.suite).toUpperCase() !== suiteFilter) {
|
|
71098
71854
|
continue;
|
|
71099
71855
|
}
|
|
71100
|
-
|
|
71856
|
+
tasks2.push({
|
|
71101
71857
|
id: raw.id,
|
|
71102
71858
|
suite: raw.suite,
|
|
71103
71859
|
tier: raw.tier,
|
|
@@ -71109,7 +71865,7 @@ function listEvalTasks(args) {
|
|
|
71109
71865
|
} catch {
|
|
71110
71866
|
}
|
|
71111
71867
|
}
|
|
71112
|
-
return textResult({ count:
|
|
71868
|
+
return textResult({ count: tasks2.length, tasks: tasks2 });
|
|
71113
71869
|
}
|
|
71114
71870
|
async function verifyPart(args) {
|
|
71115
71871
|
const documentId = String(args.document_id ?? "");
|
|
@@ -79895,7 +80651,7 @@ var init_animate = __esm({
|
|
|
79895
80651
|
|
|
79896
80652
|
// src/server.ts
|
|
79897
80653
|
import { createRequire as createRequire2 } from "node:module";
|
|
79898
|
-
import { randomUUID as
|
|
80654
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
79899
80655
|
function getBuildInfo() {
|
|
79900
80656
|
return {
|
|
79901
80657
|
name: "vcad",
|
|
@@ -79908,7 +80664,7 @@ function getBuildInfo() {
|
|
|
79908
80664
|
};
|
|
79909
80665
|
}
|
|
79910
80666
|
function buildInstructions(kernelPrompt) {
|
|
79911
|
-
const
|
|
80667
|
+
const header2 = [
|
|
79912
80668
|
"vcad \u2014 parametric CAD with a real BRep kernel. Coordinate system: Z-up (X right, Y forward, Z up). Units: millimeters.",
|
|
79913
80669
|
"",
|
|
79914
80670
|
"Workflow: `open_document` \u2192 author \u2192 see \u2192 measure \u2192 ship.",
|
|
@@ -79926,7 +80682,7 @@ function buildInstructions(kernelPrompt) {
|
|
|
79926
80682
|
"",
|
|
79927
80683
|
"PCB workflow: `create_schematic` (declare connectivity as data via `nets`) \u2192 `place_components` \u2192 `route_nets` / `add_coil` / `add_coil_array` \u2192 `run_drc` \u2192 `validate_for_fab` \u2192 `export_gerber`. All take the `document_id` from create_schematic and mutate that session \u2014 never re-send the document. `validate_for_fab` is the single 'is this board ready?' gate (DRC + renderability + Gerber serialization + blockers, all fail-closed); `export_gerber` enforces a clean DRC by default and blocks a dirty board. `board_from_solid` turns a solid part (e.g. an enclosure or stator disc in a CAD session) into an outline polygon for `place_components`. For motors, plan the winding first with `winding_layout` (slots + poles \u2192 per-coil phase/polarity/winding-factor, as data \u2014 it touches no board), then realize it with `add_coil_array`. `run_drc` returns a summary by default (counts by rule + net-pair, worst clearance, a capped sample); pass `detail:'full'` for every violation. Surgical copper edits: `get_copper` lists existing traces/vias/zones (filtered by layer/net/bbox/kind) with the same indices `delete_trace`/`delete_via`/`delete_zone` accept \u2014 discover, then delete, without exporting the document. Where two nets must touch on purpose (wye neutral, split ground, shunt tap), declare it with `add_net_tie` \u2014 prefer a region-scoped tie (position+radius) so DRC stays honest away from the junction; `delete_net_tie` takes it back."
|
|
79928
80684
|
].join("\n");
|
|
79929
|
-
if (!kernelPrompt) return
|
|
80685
|
+
if (!kernelPrompt) return header2;
|
|
79930
80686
|
const sections = /* @__PURE__ */ new Map();
|
|
79931
80687
|
for (const part of kernelPrompt.split(/^## /m).slice(1)) {
|
|
79932
80688
|
const nl = part.indexOf("\n");
|
|
@@ -79937,7 +80693,7 @@ function buildInstructions(kernelPrompt) {
|
|
|
79937
80693
|
(t2) => `## ${t2}
|
|
79938
80694
|
${sections.get(t2)}`
|
|
79939
80695
|
);
|
|
79940
|
-
return [
|
|
80696
|
+
return [header2, ...picked].join("\n\n");
|
|
79941
80697
|
}
|
|
79942
80698
|
function parseEnvPacks() {
|
|
79943
80699
|
const env = process.env.VCAD_MCP_PACKS?.trim();
|
|
@@ -80373,7 +81129,7 @@ async function createServer(existingEngine, context = { user: null }) {
|
|
|
80373
81129
|
]
|
|
80374
81130
|
};
|
|
80375
81131
|
}
|
|
80376
|
-
throw new
|
|
81132
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown resource: ${uri}`);
|
|
80377
81133
|
});
|
|
80378
81134
|
const clientHasInlineUi = () => {
|
|
80379
81135
|
const caps = server.getClientCapabilities();
|
|
@@ -80724,6 +81480,7 @@ var init_server3 = __esm({
|
|
|
80724
81480
|
init_edge_config();
|
|
80725
81481
|
init_live_route();
|
|
80726
81482
|
init_artifact_route();
|
|
81483
|
+
init_protocol_2026();
|
|
80727
81484
|
init_artifact_store();
|
|
80728
81485
|
init_viewer();
|
|
80729
81486
|
init_notify();
|
|
@@ -80787,8 +81544,8 @@ var init_server3 = __esm({
|
|
|
80787
81544
|
init_order_feed();
|
|
80788
81545
|
init_animate();
|
|
80789
81546
|
PKG_VERSION = (() => {
|
|
80790
|
-
if ("0.9.4-main.
|
|
80791
|
-
return "0.9.4-main.
|
|
81547
|
+
if ("0.9.4-main.49") {
|
|
81548
|
+
return "0.9.4-main.49";
|
|
80792
81549
|
}
|
|
80793
81550
|
try {
|
|
80794
81551
|
const req = createRequire2(import.meta.url);
|
|
@@ -80797,11 +81554,11 @@ var init_server3 = __esm({
|
|
|
80797
81554
|
return "0.0.0";
|
|
80798
81555
|
}
|
|
80799
81556
|
})();
|
|
80800
|
-
BUILD_SHA = "
|
|
80801
|
-
BUILD_TIME = "2026-07-
|
|
81557
|
+
BUILD_SHA = "40ccc073edea8494ce6e1a94ea360bf79cfc630d";
|
|
81558
|
+
BUILD_TIME = "2026-07-29T16:38:39.110Z";
|
|
80802
81559
|
SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
|
|
80803
81560
|
VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
|
|
80804
|
-
INSTANCE_ID =
|
|
81561
|
+
INSTANCE_ID = randomUUID7().slice(0, 8);
|
|
80805
81562
|
PROCESS_STARTED_AT = Date.now();
|
|
80806
81563
|
configureTelemetry(getBuildInfo());
|
|
80807
81564
|
warnIfSessionStoreNotDurable();
|
|
@@ -81103,12 +81860,47 @@ async function main() {
|
|
|
81103
81860
|
const server = await createServer(void 0, { user: null });
|
|
81104
81861
|
const transport = new StdioServerTransport();
|
|
81105
81862
|
await server.connect(transport);
|
|
81863
|
+
const legacyOnMessage = transport.onmessage?.bind(transport);
|
|
81864
|
+
const listens = /* @__PURE__ */ new Map();
|
|
81865
|
+
transport.onmessage = (msg) => {
|
|
81866
|
+
if (!isModernMessage(msg)) {
|
|
81867
|
+
const m = msg;
|
|
81868
|
+
const cancelId = m.params?.requestId;
|
|
81869
|
+
if (m.method === "notifications/cancelled" && cancelId !== void 0 && listens.has(cancelId)) {
|
|
81870
|
+
listens.get(cancelId).close();
|
|
81871
|
+
listens.delete(cancelId);
|
|
81872
|
+
return;
|
|
81873
|
+
}
|
|
81874
|
+
legacyOnMessage?.(msg);
|
|
81875
|
+
return;
|
|
81876
|
+
}
|
|
81877
|
+
const method = msg.method;
|
|
81878
|
+
if (method === "subscriptions/listen") {
|
|
81879
|
+
const id = msg.id;
|
|
81880
|
+
const handle = handleModernListen(msg, {
|
|
81881
|
+
send: (m) => void transport.send(m)
|
|
81882
|
+
});
|
|
81883
|
+
if (id !== void 0) listens.set(id, handle);
|
|
81884
|
+
return;
|
|
81885
|
+
}
|
|
81886
|
+
void handleModernRequest(msg, {
|
|
81887
|
+
createServer: () => createServer(void 0, { user: null }),
|
|
81888
|
+
// Request-scoped notifications share the stdio channel; the SDK
|
|
81889
|
+
// client correlates progress via its progressToken.
|
|
81890
|
+
onNotification: (n) => void transport.send(n)
|
|
81891
|
+
}).then(({ body }) => {
|
|
81892
|
+
if (body !== null) {
|
|
81893
|
+
void transport.send(body);
|
|
81894
|
+
}
|
|
81895
|
+
});
|
|
81896
|
+
};
|
|
81106
81897
|
}
|
|
81107
81898
|
var init_index = __esm({
|
|
81108
81899
|
"src/index.ts"() {
|
|
81109
81900
|
"use strict";
|
|
81110
81901
|
init_stdio2();
|
|
81111
81902
|
init_server3();
|
|
81903
|
+
init_protocol_2026();
|
|
81112
81904
|
console.log = (...args) => console.error(...args);
|
|
81113
81905
|
main().catch((err7) => {
|
|
81114
81906
|
console.error("Fatal error:", err7);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vcad/mcp",
|
|
3
|
-
"version": "0.9.4-main.
|
|
3
|
+
"version": "0.9.4-main.49",
|
|
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-07-
|
|
22
|
+
"sha": "40ccc073edea8494ce6e1a94ea360bf79cfc630d",
|
|
23
|
+
"builtAt": "2026-07-29T16:38:39.110Z"
|
|
24
24
|
}
|
|
25
25
|
}
|
package/vcad_kernel_wasm_bg.wasm
CHANGED
|
Binary file
|