construct-shader-graph-mcp 0.7.0 → 0.9.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/package.json +1 -1
- package/src/guidance/skill.md +4 -3
- package/src/server.mjs +63 -122
package/package.json
CHANGED
package/src/guidance/skill.md
CHANGED
|
@@ -124,6 +124,7 @@ Read-only calls:
|
|
|
124
124
|
- `getManifest`
|
|
125
125
|
- `nodes.list`
|
|
126
126
|
- `nodes.get`
|
|
127
|
+
- `nodes.getInfo`
|
|
127
128
|
- `nodes.getPorts`
|
|
128
129
|
- `nodes.search`
|
|
129
130
|
- `nodeTypes.list`
|
|
@@ -223,7 +224,7 @@ This is one of the most important workflows.
|
|
|
223
224
|
|
|
224
225
|
To change a node's editable input values:
|
|
225
226
|
|
|
226
|
-
1. Read the node with `nodes.
|
|
227
|
+
1. Read the node with `nodes.getInfo(nodeId)`.
|
|
227
228
|
2. Inspect `editableInputValues` to see which inputs are editable and currently unconnected.
|
|
228
229
|
3. Edit with `nodes.edit(nodeId, { inputValues: ... })`.
|
|
229
230
|
|
|
@@ -236,10 +237,10 @@ Rules:
|
|
|
236
237
|
|
|
237
238
|
Example workflow:
|
|
238
239
|
|
|
239
|
-
- call `nodes.
|
|
240
|
+
- call `nodes.getInfo(nodeId)`
|
|
240
241
|
- inspect `editableInputValues`
|
|
241
242
|
- call `nodes.edit(nodeId, { inputValues: { B: [0, 0, 0, 1] } })`
|
|
242
|
-
- re-read the node with `nodes.
|
|
243
|
+
- re-read the node with `nodes.getInfo(nodeId)`
|
|
243
244
|
|
|
244
245
|
Name-based example:
|
|
245
246
|
|
package/src/server.mjs
CHANGED
|
@@ -33,7 +33,60 @@ function nowIso() {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function loadSkillText() {
|
|
36
|
-
|
|
36
|
+
try {
|
|
37
|
+
return fs.readFileSync(SKILL_PATH, "utf8");
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function fetchGuidanceFromApp() {
|
|
44
|
+
if (!selectedSessionId) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const session = sessions.get(selectedSessionId);
|
|
49
|
+
if (!session) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const result = await invokeSession(session, "getGuidance", []);
|
|
55
|
+
if (result?.ok && result.result) {
|
|
56
|
+
return result.result;
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// Fall back to local file.
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function getSkillText() {
|
|
66
|
+
const appGuidance = await fetchGuidanceFromApp();
|
|
67
|
+
if (appGuidance?.skill) {
|
|
68
|
+
return appGuidance.skill;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return loadSkillText() || "No guidance available.";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function getQuickstartText() {
|
|
75
|
+
const appGuidance = await fetchGuidanceFromApp();
|
|
76
|
+
if (appGuidance?.quickstart) {
|
|
77
|
+
return appGuidance.quickstart;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return loadQuickstartText();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function getPromptPreambleText() {
|
|
84
|
+
const appGuidance = await fetchGuidanceFromApp();
|
|
85
|
+
if (appGuidance?.preamble) {
|
|
86
|
+
return appGuidance.preamble;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return getPromptPreamble();
|
|
37
90
|
}
|
|
38
91
|
|
|
39
92
|
function loadQuickstartText() {
|
|
@@ -65,7 +118,7 @@ Use MCP tools only.
|
|
|
65
118
|
## Important method patterns
|
|
66
119
|
|
|
67
120
|
- Discover node types: nodeTypes.search, nodeTypes.list, nodeTypes.get
|
|
68
|
-
- Inspect graph: nodes.list, nodes.
|
|
121
|
+
- Inspect graph: nodes.list, nodes.getInfo, nodes.getPorts, wires.getAll, uniforms.list
|
|
69
122
|
- Edit node input values: nodes.edit(nodeId, { inputValues: { PortName: value } })
|
|
70
123
|
- Wire nodes: wires.create({ from, to }) after inspecting both ports
|
|
71
124
|
- Validate: ai.runDebugCheck({ includeScreenshot: true })
|
|
@@ -86,7 +139,7 @@ function getPromptPreamble() {
|
|
|
86
139
|
function getSessionSummary(session) {
|
|
87
140
|
return {
|
|
88
141
|
sessionId: session.sessionId,
|
|
89
|
-
|
|
142
|
+
projectName: session.project?.name || "Untitled Shader",
|
|
90
143
|
connectedAt: session.connectedAt,
|
|
91
144
|
updatedAt: session.updatedAt,
|
|
92
145
|
manifestVersion: session.manifest?.version || null,
|
|
@@ -170,7 +223,7 @@ function createToolDefinitions() {
|
|
|
170
223
|
handler: async () => {
|
|
171
224
|
const result = {
|
|
172
225
|
title: "Construct Shader Graph MCP Guidance",
|
|
173
|
-
content:
|
|
226
|
+
content: await getSkillText(),
|
|
174
227
|
};
|
|
175
228
|
return {
|
|
176
229
|
content: [{ type: "text", text: result.content }],
|
|
@@ -188,14 +241,7 @@ function createToolDefinitions() {
|
|
|
188
241
|
projects: z.array(
|
|
189
242
|
z.object({
|
|
190
243
|
sessionId: z.string(),
|
|
191
|
-
|
|
192
|
-
name: z.string(),
|
|
193
|
-
version: z.string().optional(),
|
|
194
|
-
author: z.string().optional(),
|
|
195
|
-
category: z.string().optional(),
|
|
196
|
-
description: z.string().optional(),
|
|
197
|
-
shaderInfo: z.any().optional(),
|
|
198
|
-
}),
|
|
244
|
+
projectName: z.string(),
|
|
199
245
|
connectedAt: z.string(),
|
|
200
246
|
updatedAt: z.string(),
|
|
201
247
|
manifestVersion: z.string().nullable(),
|
|
@@ -234,7 +280,7 @@ function createToolDefinitions() {
|
|
|
234
280
|
},
|
|
235
281
|
outputSchema: {
|
|
236
282
|
sessionId: z.string(),
|
|
237
|
-
|
|
283
|
+
projectName: z.string(),
|
|
238
284
|
},
|
|
239
285
|
},
|
|
240
286
|
handler: async ({ sessionId }) => {
|
|
@@ -242,7 +288,7 @@ function createToolDefinitions() {
|
|
|
242
288
|
selectedSessionId = sessionId;
|
|
243
289
|
const result = {
|
|
244
290
|
sessionId,
|
|
245
|
-
|
|
291
|
+
projectName: session.project?.name || "Untitled Shader",
|
|
246
292
|
};
|
|
247
293
|
return {
|
|
248
294
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
@@ -263,7 +309,6 @@ function createToolDefinitions() {
|
|
|
263
309
|
},
|
|
264
310
|
outputSchema: {
|
|
265
311
|
sessionId: z.string(),
|
|
266
|
-
project: z.any(),
|
|
267
312
|
manifest: z.any(),
|
|
268
313
|
},
|
|
269
314
|
},
|
|
@@ -273,7 +318,6 @@ function createToolDefinitions() {
|
|
|
273
318
|
: ensureSelectedSession();
|
|
274
319
|
const result = {
|
|
275
320
|
sessionId: session.sessionId,
|
|
276
|
-
project: session.project,
|
|
277
321
|
manifest: session.manifest,
|
|
278
322
|
};
|
|
279
323
|
return {
|
|
@@ -304,7 +348,7 @@ function createToolDefinitions() {
|
|
|
304
348
|
},
|
|
305
349
|
outputSchema: {
|
|
306
350
|
sessionId: z.string(),
|
|
307
|
-
project: z.any(),
|
|
351
|
+
// project: z.any(),
|
|
308
352
|
method: z.string(),
|
|
309
353
|
args: z.array(z.any()),
|
|
310
354
|
durationMs: z.number(),
|
|
@@ -348,7 +392,7 @@ function registerResources(server) {
|
|
|
348
392
|
{
|
|
349
393
|
uri: uri.href,
|
|
350
394
|
mimeType: "text/markdown",
|
|
351
|
-
text:
|
|
395
|
+
text: await getSkillText(),
|
|
352
396
|
},
|
|
353
397
|
],
|
|
354
398
|
}),
|
|
@@ -367,108 +411,7 @@ function registerResources(server) {
|
|
|
367
411
|
{
|
|
368
412
|
uri: uri.href,
|
|
369
413
|
mimeType: "text/markdown",
|
|
370
|
-
text:
|
|
371
|
-
},
|
|
372
|
-
],
|
|
373
|
-
}),
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function registerPrompts(server) {
|
|
378
|
-
server.registerPrompt(
|
|
379
|
-
"work-with-shader-graph",
|
|
380
|
-
{
|
|
381
|
-
title: "Work With Shader Graph",
|
|
382
|
-
description:
|
|
383
|
-
"General prompt for safely inspecting and editing a Construct Shader Graph project.",
|
|
384
|
-
argsSchema: z.object({
|
|
385
|
-
task: z.string().optional().describe("The user task to accomplish."),
|
|
386
|
-
}),
|
|
387
|
-
},
|
|
388
|
-
({ task }) => ({
|
|
389
|
-
messages: [
|
|
390
|
-
{
|
|
391
|
-
role: "user",
|
|
392
|
-
content: {
|
|
393
|
-
type: "text",
|
|
394
|
-
text: `${getPromptPreamble()}\n\nFollow the full guidance resource if more detail is needed.\n\nTask: ${task || "Inspect the current project, understand its graph state, and proceed safely."}`,
|
|
395
|
-
},
|
|
396
|
-
},
|
|
397
|
-
],
|
|
398
|
-
}),
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
server.registerPrompt(
|
|
402
|
-
"inspect-graph",
|
|
403
|
-
{
|
|
404
|
-
title: "Inspect Graph",
|
|
405
|
-
description:
|
|
406
|
-
"Prompt for safely inspecting the current graph before any edits.",
|
|
407
|
-
argsSchema: z.object({
|
|
408
|
-
focus: z
|
|
409
|
-
.string()
|
|
410
|
-
.optional()
|
|
411
|
-
.describe(
|
|
412
|
-
"Optional area to inspect, like uniforms, preview, or node types.",
|
|
413
|
-
),
|
|
414
|
-
}),
|
|
415
|
-
},
|
|
416
|
-
({ focus }) => ({
|
|
417
|
-
messages: [
|
|
418
|
-
{
|
|
419
|
-
role: "user",
|
|
420
|
-
content: {
|
|
421
|
-
type: "text",
|
|
422
|
-
text: `${getPromptPreamble()}\n\nInspect the current graph without mutating it. Read nodes, wires, uniforms, shader info, and any relevant settings first. ${focus ? `Focus on: ${focus}.` : ""}`,
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
],
|
|
426
|
-
}),
|
|
427
|
-
);
|
|
428
|
-
|
|
429
|
-
server.registerPrompt(
|
|
430
|
-
"edit-graph-safely",
|
|
431
|
-
{
|
|
432
|
-
title: "Edit Graph Safely",
|
|
433
|
-
description: "Prompt for making a small validated graph edit with MCP.",
|
|
434
|
-
argsSchema: z.object({
|
|
435
|
-
task: z.string().describe("The graph edit to perform."),
|
|
436
|
-
}),
|
|
437
|
-
},
|
|
438
|
-
({ task }) => ({
|
|
439
|
-
messages: [
|
|
440
|
-
{
|
|
441
|
-
role: "user",
|
|
442
|
-
content: {
|
|
443
|
-
type: "text",
|
|
444
|
-
text: `${getPromptPreamble()}\n\nMake the smallest valid change that satisfies this task: ${task}\n\nBefore wiring, inspect ports. Before choosing a node type, use nodeTypes.search or nodeTypes.list. After each structural edit, re-read affected nodes or ports and validate preview/code if relevant.`,
|
|
445
|
-
},
|
|
446
|
-
},
|
|
447
|
-
],
|
|
448
|
-
}),
|
|
449
|
-
);
|
|
450
|
-
|
|
451
|
-
server.registerPrompt(
|
|
452
|
-
"debug-preview-errors",
|
|
453
|
-
{
|
|
454
|
-
title: "Debug Preview Errors",
|
|
455
|
-
description:
|
|
456
|
-
"Prompt for debugging generated code or preview issues in a shader graph project.",
|
|
457
|
-
argsSchema: z.object({
|
|
458
|
-
issue: z
|
|
459
|
-
.string()
|
|
460
|
-
.optional()
|
|
461
|
-
.describe("Optional description of the observed preview issue."),
|
|
462
|
-
}),
|
|
463
|
-
},
|
|
464
|
-
({ issue }) => ({
|
|
465
|
-
messages: [
|
|
466
|
-
{
|
|
467
|
-
role: "user",
|
|
468
|
-
content: {
|
|
469
|
-
type: "text",
|
|
470
|
-
text: `${getPromptPreamble()}\n\nDebug the current shader graph by inspecting shader.getGeneratedCode, preview.getErrors, preview settings, node preview, and ai.runDebugCheck. ${issue ? `Observed issue: ${issue}` : ""}`,
|
|
471
|
-
},
|
|
414
|
+
text: await getQuickstartText(),
|
|
472
415
|
},
|
|
473
416
|
],
|
|
474
417
|
}),
|
|
@@ -482,7 +425,6 @@ function createLocalServer() {
|
|
|
482
425
|
});
|
|
483
426
|
|
|
484
427
|
registerResources(server);
|
|
485
|
-
registerPrompts(server);
|
|
486
428
|
createToolDefinitions().forEach((tool) => {
|
|
487
429
|
server.registerTool(tool.name, tool.config, tool.handler);
|
|
488
430
|
});
|
|
@@ -697,7 +639,6 @@ function createProxyServer() {
|
|
|
697
639
|
});
|
|
698
640
|
|
|
699
641
|
registerResources(server);
|
|
700
|
-
registerPrompts(server);
|
|
701
642
|
createToolDefinitions().forEach((tool) => {
|
|
702
643
|
server.registerTool(tool.name, tool.config, async (input = {}) => {
|
|
703
644
|
return callPrimaryTool(tool.name, input);
|