@classcad/mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +361 -0
- package/dist/auth.d.ts +32 -0
- package/dist/auth.js +272 -0
- package/dist/auth.js.map +1 -0
- package/dist/bridge/protocol.d.ts +87 -0
- package/dist/bridge/protocol.js +14 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/server.d.ts +35 -0
- package/dist/bridge/server.js +236 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/client.d.ts +98 -0
- package/dist/client.js +879 -0
- package/dist/client.js.map +1 -0
- package/dist/daemon.d.ts +38 -0
- package/dist/daemon.js +390 -0
- package/dist/daemon.js.map +1 -0
- package/dist/engine/wasm-worker.d.ts +1 -0
- package/dist/engine/wasm-worker.js +176 -0
- package/dist/engine/wasm-worker.js.map +1 -0
- package/dist/engine/wasm.d.ts +60 -0
- package/dist/engine/wasm.js +212 -0
- package/dist/engine/wasm.js.map +1 -0
- package/dist/mcp-server.d.ts +23 -0
- package/dist/mcp-server.js +141 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/ports.d.ts +2 -0
- package/dist/ports.js +5 -0
- package/dist/ports.js.map +1 -0
- package/dist/queue.d.ts +9 -0
- package/dist/queue.js +50 -0
- package/dist/queue.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +423 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/auth.d.ts +7 -0
- package/dist/tools/auth.js +63 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/bridge.d.ts +4 -0
- package/dist/tools/bridge.js +115 -0
- package/dist/tools/bridge.js.map +1 -0
- package/dist/tools/docs.d.ts +13 -0
- package/dist/tools/docs.js +180 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/lifecycle.d.ts +3 -0
- package/dist/tools/lifecycle.js +156 -0
- package/dist/tools/lifecycle.js.map +1 -0
- package/dist/tools/script.d.ts +3 -0
- package/dist/tools/script.js +102 -0
- package/dist/tools/script.js.map +1 -0
- package/dist/tools/snapshot.d.ts +3 -0
- package/dist/tools/snapshot.js +174 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/state.d.ts +3 -0
- package/dist/tools/state.js +95 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// snapshot — render the current drawing and return it as an inline PNG image
|
|
2
|
+
// block plus the on-disk path.
|
|
3
|
+
//
|
|
4
|
+
// Rendering comes from @classcad/renderer (the shared engine) — this tool
|
|
5
|
+
// exposes its full verification toolkit: named views AND arbitrary cameras,
|
|
6
|
+
// section planes, four-view sheets, native/distinct colors, highlight ids,
|
|
7
|
+
// probe markers, sketch overlay, annotations, x-ray, frame pinning, layers.
|
|
8
|
+
//
|
|
9
|
+
// The PNG is also persisted under
|
|
10
|
+
// $CLASSCAD_SNAPSHOT_DIR (env override) — or
|
|
11
|
+
// <os.tmpdir()>/classcad-snapshots/ — default
|
|
12
|
+
// so the user can open it later. Files are NOT auto-cleaned.
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { mkdirSync, readFileSync } from 'fs';
|
|
15
|
+
import { isAbsolute, join, resolve } from 'path';
|
|
16
|
+
import { tmpdir } from 'os';
|
|
17
|
+
import { renderSession } from '@classcad/renderer/node';
|
|
18
|
+
function snapshotDir(outDir) {
|
|
19
|
+
const envDir = outDir ?? process.env.CLASSCAD_SNAPSHOT_DIR;
|
|
20
|
+
const dir = envDir ? resolve(envDir) : join(tmpdir(), 'classcad-snapshots');
|
|
21
|
+
mkdirSync(dir, { recursive: true });
|
|
22
|
+
return dir;
|
|
23
|
+
}
|
|
24
|
+
function timestamp() {
|
|
25
|
+
// 2026-05-01T12-34-56Z — filesystem-safe ISO basic format
|
|
26
|
+
return new Date().toISOString().replace(/[:.]/g, '-').replace(/-\d+Z$/, 'Z');
|
|
27
|
+
}
|
|
28
|
+
const viewSchema = z.union([
|
|
29
|
+
z.enum(['iso', 'top', 'bottom', 'front', 'back', 'left', 'right']),
|
|
30
|
+
z.object({ azimuth: z.number().optional(), elevation: z.number().optional() })
|
|
31
|
+
.describe('Turntable camera in DEGREES (Z-up): azimuth 0 = front, 90 = camera at +X; elevation 0 = horizon, 90 = top.'),
|
|
32
|
+
z.object({ direction: z.array(z.number()).length(3), up: z.array(z.number()).length(3).optional() })
|
|
33
|
+
.describe('Explicit orthographic look direction (from camera toward the scene).'),
|
|
34
|
+
]);
|
|
35
|
+
export function registerSnapshotTool(server, client) {
|
|
36
|
+
server.registerTool('snapshot', {
|
|
37
|
+
title: 'Snapshot drawing',
|
|
38
|
+
description: 'Render the current drawing as an inline PNG (also written to disk: outDir, else $CLASSCAD_SNAPSHOT_DIR, else <tmpdir>/classcad-snapshots). ' +
|
|
39
|
+
'The image is returned to the MODEL as an inline image block — no follow-up Read is needed to see it. ' +
|
|
40
|
+
'The USER may not see tool results (Claude Code / desktop Code tab do not render them): ' +
|
|
41
|
+
'send the saved PNG path through the host\'s file-sending tool (e.g. SendUserFile) if the user should see the render. ' +
|
|
42
|
+
'Hosts preview only files inside the session\'s own folders (Claude Code: the scratchpad directory or the project) — anywhere else the user gets a grey placeholder card. ' +
|
|
43
|
+
'So when you intend to send the render, pass outDir = your scratchpad directory (or a folder in the project). ' +
|
|
44
|
+
'Call after a meaningful geometry change, NOT after every parameter tweak. ' +
|
|
45
|
+
'Verification options: section (cut through internals), sheet (four labeled views, shared ortho scale), ' +
|
|
46
|
+
'drawing (technical drawing: front/top/side with hidden lines dashed, placed first- or third-angle — compare against a reference drawing), ' +
|
|
47
|
+
'lines (line style: visible edges solid, hidden dashed), ' +
|
|
48
|
+
'highlight (face/edge/body ids in signal color), markers (probe crosshairs at world points), ' +
|
|
49
|
+
'sketchOverlay (sketch curves on their real plane), annotate (extents + axes triad + scale bar), ' +
|
|
50
|
+
'xray (hidden geometry shines through), colors "distinct" (one color per body — booleans/splits/patterns), ' +
|
|
51
|
+
'frame (pin an earlier snapshot\'s reported frame for pixel-comparable before/after).',
|
|
52
|
+
inputSchema: {
|
|
53
|
+
label: z.string().optional().describe('Filename label. Default "snapshot".'),
|
|
54
|
+
outDir: z
|
|
55
|
+
.string()
|
|
56
|
+
.optional()
|
|
57
|
+
.describe('Absolute directory for the PNG (created if missing). Pass your session scratchpad when the user should see the file — hosts preview only files in session folders.'),
|
|
58
|
+
width: z.number().int().min(64).max(4096).optional().describe('Pixels (default 1200).'),
|
|
59
|
+
height: z.number().int().min(64).max(4096).optional().describe('Pixels (default 900).'),
|
|
60
|
+
supersample: z.number().int().min(1).max(4).optional()
|
|
61
|
+
.describe('Anti-aliasing: render at k× and downscale to width×height (default 2; 1 = raw aliased pixels). Output size and image tokens are unchanged.'),
|
|
62
|
+
view: viewSchema.optional().describe('Camera: named view (default "iso") or arbitrary orthographic camera.'),
|
|
63
|
+
zoom: z.number().min(0.05).max(50).optional()
|
|
64
|
+
.describe('Multiplier on auto-fit scale. 1=fit-all (default), >1 zooms in.'),
|
|
65
|
+
lookAt: z.array(z.number()).length(3).optional()
|
|
66
|
+
.describe('World-space [x,y,z] that lands at screen center. Omit for bbox center.'),
|
|
67
|
+
layers: z.array(z.enum(['solid', 'sketch', 'curves', 'workgeo'])).optional()
|
|
68
|
+
.describe('Content layers to render. Default ["solid"].'),
|
|
69
|
+
colors: z.enum(['native', 'distinct']).optional()
|
|
70
|
+
.describe('"native" (default): the model\'s own colors. "distinct": one palette color per body.'),
|
|
71
|
+
section: z.object({
|
|
72
|
+
origin: z.array(z.number()).length(3),
|
|
73
|
+
normal: z.array(z.number()).length(3),
|
|
74
|
+
cap: z.boolean().optional(),
|
|
75
|
+
}).optional().describe('Cut the solids at a plane; the positive side of the normal is removed. The cut faces are filled and hatched like a drawing\'s section (wall thicknesses, bores and pockets read directly); cap: false leaves the cut open with interior walls shaded. Combine with drawing for a section view.'),
|
|
76
|
+
sheet: z.union([z.boolean(), z.array(viewSchema).length(4), z.array(viewSchema).length(2)]).optional()
|
|
77
|
+
.describe('Multi-view sheet in ONE image. true or 4 views = quadrants (default top/iso/front/right; ortho views share one scale). 2 views = side-by-side panels labeled A | B — use for the mirror check: [matched view, same view with negated azimuth] in a single render.'),
|
|
78
|
+
lines: z.boolean().optional()
|
|
79
|
+
.describe('Line style instead of shading: visible edges and silhouettes solid, hidden edges dashed. Hidden lines show bores, pockets, hollow vs solid. Works for the single view and every sheet panel.'),
|
|
80
|
+
drawing: z.union([
|
|
81
|
+
z.boolean(),
|
|
82
|
+
z.enum(['first-angle', 'third-angle']),
|
|
83
|
+
z.object({
|
|
84
|
+
projection: z.enum(['first-angle', 'third-angle']).optional(),
|
|
85
|
+
side: z.enum(['left', 'right']).optional(),
|
|
86
|
+
iso: z.boolean().optional(),
|
|
87
|
+
}),
|
|
88
|
+
]).optional()
|
|
89
|
+
.describe('Technical drawing in ONE image: front, top and side view in line style (hidden edges dashed), aligned at one scale, plus a shaded iso. "first-angle" (ISO E, Europe; true): top view BELOW front, view from the left RIGHT of it. "third-angle" (ISO A, US): top view ABOVE front, view from the right RIGHT of it. Use the method of the reference drawing, then compare view by view. Takes precedence over sheet.'),
|
|
90
|
+
highlight: z.array(z.number()).optional()
|
|
91
|
+
.describe('Ids rendered in signal color: graphic container ids, owning solid ids, face mesh ids, edge ids. CAUTION: face/edge ids are only stable within one graphic payload (recalc reassigns them) — across tool calls use highlightAt.'),
|
|
92
|
+
highlightAt: z.array(z.array(z.number()).length(3)).optional()
|
|
93
|
+
.describe('World points [[x,y,z],…]: the closest FACE in the rendered payload is highlighted per point. Geometrically anchored — the robust way to highlight a face found via run_script (return a point on it, not its mesh id).'),
|
|
94
|
+
markers: z.array(z.object({
|
|
95
|
+
position: z.array(z.number()).length(3),
|
|
96
|
+
label: z.string().optional(),
|
|
97
|
+
color: z.array(z.number()).length(3).optional(),
|
|
98
|
+
})).optional().describe('Probe markers (crosshair + label) at world coordinates, drawn on top.'),
|
|
99
|
+
sketchOverlay: z.boolean().optional()
|
|
100
|
+
.describe('Draw sketch curves in 3D on their actual plane over the solid render.'),
|
|
101
|
+
annotate: z.boolean().optional()
|
|
102
|
+
.describe('Measurement overlay: bbox extents, view-oriented axes triad, scale bar.'),
|
|
103
|
+
xray: z.boolean().optional().describe('Translucent bodies — hidden geometry shines through.'),
|
|
104
|
+
frame: z.object({ scale: z.number(), midX: z.number(), midY: z.number() }).optional()
|
|
105
|
+
.describe('Pin the frame reported by an earlier snapshot (same view/size) for pixel-comparable before/after.'),
|
|
106
|
+
recalc: z.boolean().optional()
|
|
107
|
+
.describe('Default false. Opt in only to regenerate; keep false for solid.*/entity-injection sessions — recalc destroys injected bodies.'),
|
|
108
|
+
source: z.enum(['graphic', 'stl']).optional()
|
|
109
|
+
.describe('"stl": render the tessellated STL export instead of the engine graphic (explicit fallback; no brep edges).'),
|
|
110
|
+
},
|
|
111
|
+
}, async (input) => {
|
|
112
|
+
const { label, outDir, ...options } = input;
|
|
113
|
+
const safeLabel = (label ?? 'snapshot').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
114
|
+
if (outDir !== undefined && !isAbsolute(outDir)) {
|
|
115
|
+
return { content: [{ type: 'text', text: `outDir must be an absolute path (the daemon's working directory is not yours): ${outDir}` }], isError: true };
|
|
116
|
+
}
|
|
117
|
+
const dir = snapshotDir(outDir);
|
|
118
|
+
const prefix = `${safeLabel}-${timestamp()}`;
|
|
119
|
+
let renders;
|
|
120
|
+
try {
|
|
121
|
+
renders = await renderSession(client, prefix, dir, {
|
|
122
|
+
width: options.width ?? 1200,
|
|
123
|
+
height: options.height ?? 900,
|
|
124
|
+
supersample: options.supersample ?? 2,
|
|
125
|
+
vectorText: true,
|
|
126
|
+
...options,
|
|
127
|
+
layers: options.layers ?? ['solid'],
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
// renderSession fails LOUDLY with cause + remedies (e.g. no graphic
|
|
132
|
+
// data → suggests source: "stl"). Surface that verbatim to the model.
|
|
133
|
+
return { isError: true, content: [{ type: 'text', text: e instanceof Error ? e.message : String(e) }] };
|
|
134
|
+
}
|
|
135
|
+
const imageBlocks = [];
|
|
136
|
+
const paths = [];
|
|
137
|
+
for (const r of renders) {
|
|
138
|
+
const fullPath = join(dir, r.file);
|
|
139
|
+
try {
|
|
140
|
+
const buf = readFileSync(fullPath);
|
|
141
|
+
imageBlocks.push({ type: 'image', data: buf.toString('base64'), mimeType: 'image/png' });
|
|
142
|
+
paths.push(fullPath);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
/* skip files that didn't materialize */
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (imageBlocks.length === 0) {
|
|
149
|
+
return {
|
|
150
|
+
content: [{
|
|
151
|
+
type: 'text',
|
|
152
|
+
text: 'No renderable content. Add geometry first (a part, sketch, or feature) and try again.',
|
|
153
|
+
}],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Inline image first (what the MODEL sees), then the path note — with a reminder
|
|
157
|
+
// that the user may not see tool-result images — and, when available, the
|
|
158
|
+
// frame, so a later snapshot can pin it (before/after).
|
|
159
|
+
const noteLines = [paths.length === 1 ? `Saved: ${paths[0]}` : `Saved:\n${paths.join('\n')}`];
|
|
160
|
+
noteLines.push(`capture: ${JSON.stringify(renders[0]?.metadata)}`);
|
|
161
|
+
const framed = renders.find(r => r.frame);
|
|
162
|
+
if (framed && framed.frame)
|
|
163
|
+
noteLines.push(`frame: ${JSON.stringify(framed.frame)}`);
|
|
164
|
+
noteLines.push('Note: the user may not see this image in their transcript — send the saved file via the host\'s file-sending tool (e.g. SendUserFile) if they should see it.' +
|
|
165
|
+
(outDir ? '' : ' Hosts preview only files in session folders: re-run with outDir = your scratchpad before sending, or the user sees a grey placeholder.'));
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
...imageBlocks,
|
|
169
|
+
{ type: 'text', text: noteLines.join('\n') },
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/tools/snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// State tools: tree, find, inspect.
|
|
2
|
+
//
|
|
3
|
+
// Read-only access to the cached structure tree. The cache is updated as a
|
|
4
|
+
// side effect of any API call (server sends a full snapshot on every Result
|
|
5
|
+
// frame), so these tools never trigger a server round-trip unless `refresh`
|
|
6
|
+
// is requested.
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
function slim(n) {
|
|
9
|
+
const out = { id: n.id, class: n.class, name: n.name };
|
|
10
|
+
if (n.parent != null)
|
|
11
|
+
out.parent = n.parent;
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
export function registerStateTools(server, client) {
|
|
15
|
+
server.registerTool('tree', {
|
|
16
|
+
title: 'Structure tree',
|
|
17
|
+
description: 'Return the cached drawing structure tree. Pass refresh=true to force a fresh server fetch first.',
|
|
18
|
+
inputSchema: {
|
|
19
|
+
refresh: z.boolean().optional().describe('Force a server round-trip before reading the cache.'),
|
|
20
|
+
},
|
|
21
|
+
}, async ({ refresh }) => {
|
|
22
|
+
// Pulls when the cache is stale (or `refresh`), then the structure is current.
|
|
23
|
+
await client.getTree({ refresh });
|
|
24
|
+
const t = client.getStructure();
|
|
25
|
+
if (!t) {
|
|
26
|
+
return { content: [{ type: 'text', text: JSON.stringify({ tree: null, hint: 'No structure cached yet — make any API call first, or pass refresh=true.' }) }] };
|
|
27
|
+
}
|
|
28
|
+
const nodes = Object.values(t.tree);
|
|
29
|
+
const summary = {
|
|
30
|
+
root: t.root,
|
|
31
|
+
currentProduct: t.currentProduct,
|
|
32
|
+
currentInstance: t.currentInstance,
|
|
33
|
+
nodeCount: nodes.length,
|
|
34
|
+
nodes: nodes.map(slim),
|
|
35
|
+
};
|
|
36
|
+
return { content: [{ type: 'text', text: JSON.stringify(summary) }] };
|
|
37
|
+
});
|
|
38
|
+
server.registerTool('find', {
|
|
39
|
+
title: 'Find nodes',
|
|
40
|
+
description: 'Search the cached structure tree by class and/or name substring. Returns slim records (id, class, name, parent).',
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: z.string().optional().describe('Match nodes whose class === type (e.g. "CC_Part", "CC_Box").'),
|
|
43
|
+
name: z.string().optional().describe('Match nodes whose name contains this substring (case-insensitive).'),
|
|
44
|
+
refresh: z.boolean().optional(),
|
|
45
|
+
},
|
|
46
|
+
}, async ({ type, name, refresh }) => {
|
|
47
|
+
// Pulls when the cache is stale (or `refresh`), then the structure is current.
|
|
48
|
+
await client.getTree({ refresh });
|
|
49
|
+
const t = client.getStructure();
|
|
50
|
+
if (!t)
|
|
51
|
+
return { content: [{ type: 'text', text: '[]' }] };
|
|
52
|
+
const needle = name?.toLowerCase();
|
|
53
|
+
const hits = Object.values(t.tree).filter(n => {
|
|
54
|
+
if (type && n.class !== type)
|
|
55
|
+
return false;
|
|
56
|
+
if (needle && !String(n.name ?? '').toLowerCase().includes(needle))
|
|
57
|
+
return false;
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
return { content: [{ type: 'text', text: JSON.stringify({ count: hits.length, nodes: hits.map(slim) }) }] };
|
|
61
|
+
});
|
|
62
|
+
server.registerTool('inspect', {
|
|
63
|
+
title: 'Inspect node',
|
|
64
|
+
description: 'Return the full record for a single tree node by ID, including members and children.',
|
|
65
|
+
inputSchema: {
|
|
66
|
+
id: z.union([z.string(), z.number()]).describe('Node ID.'),
|
|
67
|
+
refresh: z.boolean().optional(),
|
|
68
|
+
},
|
|
69
|
+
}, async ({ id, refresh }) => {
|
|
70
|
+
// Pulls when the cache is stale (or `refresh`), then the structure is current.
|
|
71
|
+
await client.getTree({ refresh });
|
|
72
|
+
const t = client.getStructure();
|
|
73
|
+
const node = t?.tree[String(id)] ?? null;
|
|
74
|
+
if (!node) {
|
|
75
|
+
return { content: [{ type: 'text', text: JSON.stringify({ id, found: false }) }] };
|
|
76
|
+
}
|
|
77
|
+
// Include parent chain for orientation.
|
|
78
|
+
const chain = [];
|
|
79
|
+
let cur = node;
|
|
80
|
+
while (cur && cur.parent != null) {
|
|
81
|
+
const p = t.tree[String(cur.parent)];
|
|
82
|
+
if (!p)
|
|
83
|
+
break;
|
|
84
|
+
chain.push({ id: p.id, class: p.class, name: p.name });
|
|
85
|
+
cur = p;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
content: [{
|
|
89
|
+
type: 'text',
|
|
90
|
+
text: JSON.stringify({ found: true, node, parentChain: chain }),
|
|
91
|
+
}],
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/tools/state.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type Id = number | string;
|
|
2
|
+
export type Message = {
|
|
3
|
+
message: string;
|
|
4
|
+
level: number;
|
|
5
|
+
code: number;
|
|
6
|
+
api: string;
|
|
7
|
+
};
|
|
8
|
+
export type StructureNode = {
|
|
9
|
+
id: Id;
|
|
10
|
+
class: string;
|
|
11
|
+
name: string;
|
|
12
|
+
parent: Id | null;
|
|
13
|
+
flags: number;
|
|
14
|
+
children?: Id[];
|
|
15
|
+
members?: Record<string, {
|
|
16
|
+
value: unknown;
|
|
17
|
+
type: string;
|
|
18
|
+
visible: number;
|
|
19
|
+
expression: string;
|
|
20
|
+
}>;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
export type Structure = {
|
|
24
|
+
root: Id;
|
|
25
|
+
currentProduct: Id;
|
|
26
|
+
currentInstance: Id;
|
|
27
|
+
testRoot: Id;
|
|
28
|
+
tree: Record<string, StructureNode>;
|
|
29
|
+
};
|
|
30
|
+
export type GraphicContainer = {
|
|
31
|
+
id: Id;
|
|
32
|
+
type: number;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
};
|
|
35
|
+
export type Graphic = {
|
|
36
|
+
containers?: GraphicContainer[];
|
|
37
|
+
properties?: unknown;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
};
|
|
40
|
+
export type ApiResult<T = unknown> = {
|
|
41
|
+
result: T;
|
|
42
|
+
messages: Message[];
|
|
43
|
+
maxLevel: number;
|
|
44
|
+
structure: Structure | null;
|
|
45
|
+
graphic: Graphic | null;
|
|
46
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6CAA6C"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@classcad/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Model Context Protocol server for the ClassCAD CAD engine",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"classcad-mcp": "dist/server.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/server.js",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc && node scripts/copy-build-assets.mjs",
|
|
24
|
+
"dev": "tsc --watch",
|
|
25
|
+
"start": "node dist/server.js",
|
|
26
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
27
|
+
"postbuild": "node --test test/emission.mjs test/daemon.mjs test/auth.mjs test/ofb-export.mjs",
|
|
28
|
+
"test": "npm run build && node test/emission-live.mjs && node --test test/wasm-live.mjs"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@classcad/skill": "^0.0.6",
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
|
+
"sharp": "^0.34.5",
|
|
34
|
+
"ws": "^8.19.0",
|
|
35
|
+
"zod": "^4.4.3",
|
|
36
|
+
"@classcad/renderer": "^0.1.0",
|
|
37
|
+
"@classcad/script": "^0.1.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.0.0",
|
|
41
|
+
"@types/ws": "^8.5.13",
|
|
42
|
+
"typescript": "^5.6.0"
|
|
43
|
+
}
|
|
44
|
+
}
|