construct-shader-graph-mcp 0.1.0 → 0.3.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/README.md +31 -0
- package/caw-icon-512.png +0 -0
- package/package.json +2 -2
- package/src/guidance/skill.md +472 -35
- package/src/server.mjs +615 -270
package/README.md
CHANGED
|
@@ -27,6 +27,18 @@ Construct Shader Graph is a visual editor for building Construct effect shaders
|
|
|
27
27
|
- `get_project_manifest`
|
|
28
28
|
- `call_project_method`
|
|
29
29
|
|
|
30
|
+
## MCP resources
|
|
31
|
+
|
|
32
|
+
- `construct-shader-graph://guidance/skill`
|
|
33
|
+
- `construct-shader-graph://guidance/quickstart`
|
|
34
|
+
|
|
35
|
+
## MCP prompts
|
|
36
|
+
|
|
37
|
+
- `work-with-shader-graph`
|
|
38
|
+
- `inspect-graph`
|
|
39
|
+
- `edit-graph-safely`
|
|
40
|
+
- `debug-preview-errors`
|
|
41
|
+
|
|
30
42
|
## Install as a package
|
|
31
43
|
|
|
32
44
|
Global install:
|
|
@@ -68,6 +80,7 @@ npm start
|
|
|
68
80
|
Optional environment variable:
|
|
69
81
|
|
|
70
82
|
- `MCP_BRIDGE_PORT` to change the browser bridge port from `6359`
|
|
83
|
+
- `MCP_CONTROL_PORT` to change the internal local control port used for multi-host sharing
|
|
71
84
|
|
|
72
85
|
Example:
|
|
73
86
|
|
|
@@ -75,6 +88,19 @@ Example:
|
|
|
75
88
|
MCP_BRIDGE_PORT=6360 construct-shader-graph-mcp
|
|
76
89
|
```
|
|
77
90
|
|
|
91
|
+
## Multiple MCP hosts
|
|
92
|
+
|
|
93
|
+
This package supports multiple MCP clients on the same machine.
|
|
94
|
+
|
|
95
|
+
- The first process becomes the primary backend and owns the browser bridge port.
|
|
96
|
+
- Later processes detect the running backend and act as lightweight followers.
|
|
97
|
+
- This allows tools like Claude Desktop and LM Studio to share the same live Construct Shader Graph connection.
|
|
98
|
+
|
|
99
|
+
By default:
|
|
100
|
+
|
|
101
|
+
- browser bridge: `6359`
|
|
102
|
+
- local control port: `6360`
|
|
103
|
+
|
|
78
104
|
## How it works
|
|
79
105
|
|
|
80
106
|
There are two sides to the integration:
|
|
@@ -155,6 +181,11 @@ Global install example:
|
|
|
155
181
|
- inspect available methods with `get_project_manifest`
|
|
156
182
|
- execute API calls with `call_project_method`
|
|
157
183
|
|
|
184
|
+
For better AI guidance, the host can also:
|
|
185
|
+
|
|
186
|
+
- read the built-in guidance resources
|
|
187
|
+
- use the built-in workflow prompts for common tasks
|
|
188
|
+
|
|
158
189
|
## Publish notes
|
|
159
190
|
|
|
160
191
|
This package is configured for npm publishing with:
|
package/caw-icon-512.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "construct-shader-graph-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Standalone MCP server for Construct Shader Graph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin",
|
|
8
8
|
"src",
|
|
9
9
|
"README.md",
|
|
10
|
-
"caw-icon.png"
|
|
10
|
+
"caw-icon-512.png"
|
|
11
11
|
],
|
|
12
12
|
"bin": {
|
|
13
13
|
"construct-shader-graph-mcp": "./bin/construct-shader-graph-mcp.js"
|
package/src/guidance/skill.md
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
# Construct Shader Graph MCP
|
|
1
|
+
# Construct Shader Graph MCP Guidance
|
|
2
2
|
|
|
3
|
-
Use this guidance when
|
|
3
|
+
Use this guidance when controlling Construct Shader Graph through the MCP bridge.
|
|
4
|
+
|
|
5
|
+
This document is intentionally focused on best practices, workflow, and domain knowledge. All execution should happen through MCP tools.
|
|
4
6
|
|
|
5
7
|
## Purpose
|
|
6
8
|
|
|
7
|
-
- Use
|
|
8
|
-
- Inspect the current graph, make targeted
|
|
9
|
-
- Treat the graph as the source of truth for shader logic.
|
|
9
|
+
- Use MCP as the only execution surface.
|
|
10
|
+
- Inspect the current graph, make targeted edits, validate the result, and report progress clearly.
|
|
11
|
+
- Treat the graph as the source of truth for shader logic.
|
|
12
|
+
- Use preview tools only to inspect, debug, or visually validate the graph.
|
|
10
13
|
|
|
11
14
|
## MCP tool contract
|
|
12
15
|
|
|
13
|
-
Use these tools for all work:
|
|
16
|
+
Use these MCP tools for all work:
|
|
14
17
|
|
|
15
18
|
- `list_projects`
|
|
16
19
|
- `select_project`
|
|
@@ -19,10 +22,11 @@ Use these tools for all work:
|
|
|
19
22
|
|
|
20
23
|
Execution rules:
|
|
21
24
|
|
|
22
|
-
- Always
|
|
23
|
-
- Always
|
|
24
|
-
- Always use exact return values from MCP calls;
|
|
25
|
-
- Always
|
|
25
|
+
- Always begin with `list_projects`.
|
|
26
|
+
- Always choose the active project using `shader.getInfo()` metadata, especially `name` and `version`.
|
|
27
|
+
- Always use exact return values from MCP calls; never guess state.
|
|
28
|
+
- Always inspect the manifest if available methods, method names, or argument shapes are unclear.
|
|
29
|
+
- If a call returns an id, use that id for follow-up operations instead of searching by labels.
|
|
26
30
|
|
|
27
31
|
## Operating contract
|
|
28
32
|
|
|
@@ -30,14 +34,43 @@ Execution rules:
|
|
|
30
34
|
- Identify the correct connected project before mutating anything.
|
|
31
35
|
- Inspect first, mutate second.
|
|
32
36
|
- Make the smallest valid change that satisfies the request.
|
|
33
|
-
- Verify after every structural edit such as creating nodes, deleting nodes, or
|
|
37
|
+
- Verify after every structural edit such as creating nodes, deleting nodes, rewiring ports, or changing preview settings.
|
|
34
38
|
- Use stable ids from API results; do not rely on labels, visual position, or selection alone.
|
|
35
39
|
- Do not open arbitrary local files or save project files autonomously.
|
|
36
40
|
- Built-in examples are safe to open.
|
|
37
41
|
- Export is allowed because it triggers a download rather than silently overwriting a project.
|
|
38
42
|
|
|
43
|
+
## Execution priorities
|
|
44
|
+
|
|
45
|
+
1. Preserve the current graph and user intent.
|
|
46
|
+
2. Select the correct project.
|
|
47
|
+
3. Inspect graph state before editing.
|
|
48
|
+
4. Prefer existing nodes and helper nodes over rebuilding standard shader math.
|
|
49
|
+
5. Prefer small, reversible edits over large speculative rewrites.
|
|
50
|
+
6. Verify graph integrity and preview behavior after each important edit.
|
|
51
|
+
7. End with a short recap.
|
|
52
|
+
|
|
53
|
+
## Hard rules
|
|
54
|
+
|
|
55
|
+
- Always start by calling `list_projects`.
|
|
56
|
+
- If more than one project is connected, select the correct one before doing anything else.
|
|
57
|
+
- Always call `session.initAIWork()` when starting a task.
|
|
58
|
+
- Always call `session.endAIWork()` when finishing a task.
|
|
59
|
+
- Use `session.updateAIWork()` only for short phase updates.
|
|
60
|
+
- Always inspect preview errors after meaningful shader edits.
|
|
61
|
+
- Always use preview and screenshots for non-trivial visual validation.
|
|
62
|
+
- Prefer setting editable input port values directly before adding constant/vector nodes.
|
|
63
|
+
- Never assume a node id, port index, or wire id without reading it first.
|
|
64
|
+
- Never connect ports without checking the actual node ports.
|
|
65
|
+
- Never replace an output connection blindly; inspect the affected ports first.
|
|
66
|
+
- Never use startup scripts as a substitute for graph logic.
|
|
67
|
+
- Never assume renderer-specific branching is needed; the tool already generates WebGL 1, WebGL 2, and WebGPU from one graph.
|
|
68
|
+
- Never create or edit custom node definitions unless the user explicitly asks for advanced custom node authoring.
|
|
69
|
+
|
|
39
70
|
## Preferred workflow
|
|
40
71
|
|
|
72
|
+
Use this loop for most tasks:
|
|
73
|
+
|
|
41
74
|
1. Call `list_projects`.
|
|
42
75
|
2. Select the correct project with `select_project`.
|
|
43
76
|
3. Read `get_project_manifest` once per task or when capabilities are unclear.
|
|
@@ -50,48 +83,452 @@ Execution rules:
|
|
|
50
83
|
10. Repeat only if needed.
|
|
51
84
|
11. End the session with a recap.
|
|
52
85
|
|
|
53
|
-
##
|
|
86
|
+
## Status update guidance
|
|
54
87
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
- Keep progress messages to about 4 to 10 words.
|
|
89
|
+
- Update only when changing phase or completing a meaningful step.
|
|
90
|
+
- Good examples:
|
|
91
|
+
- `"Inspecting graph"`
|
|
92
|
+
- `"Finding output node"`
|
|
93
|
+
- `"Adding variable nodes"`
|
|
94
|
+
- `"Rewiring preview path"`
|
|
95
|
+
- `"Verifying generated code"`
|
|
96
|
+
- Avoid noisy or repetitive updates.
|
|
97
|
+
|
|
98
|
+
## Environment assumptions
|
|
99
|
+
|
|
100
|
+
- The graph has nodes, ports, wires, uniforms, shader settings, preview settings, and camera state.
|
|
101
|
+
- The tool compiles one graph to three targets: WebGL 1, WebGL 2, and WebGPU.
|
|
102
|
+
- The preview normally uses the `Output` node unless node preview is enabled.
|
|
103
|
+
- Project identity comes from `shader.getInfo()` metadata.
|
|
104
|
+
|
|
105
|
+
## Method mapping
|
|
106
|
+
|
|
107
|
+
Use `call_project_method` with method names from the manifest.
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
|
|
111
|
+
- `call_project_method({ method: "shader.getInfo", args: [] })`
|
|
112
|
+
- `call_project_method({ method: "nodes.create", args: [{ ... }] })`
|
|
113
|
+
- `call_project_method({ method: "wires.create", args: [{ ... }] })`
|
|
114
|
+
- `call_project_method({ method: "session.initAIWork", args: [{ ... }] })`
|
|
66
115
|
|
|
67
|
-
|
|
116
|
+
The method names match the public API names; MCP only changes the transport.
|
|
117
|
+
|
|
118
|
+
## Safe vs side-effecting calls
|
|
119
|
+
|
|
120
|
+
Read-only calls:
|
|
121
|
+
|
|
122
|
+
- `help`
|
|
123
|
+
- `getProjectIdentity`
|
|
124
|
+
- `getManifest`
|
|
125
|
+
- `nodes.list`
|
|
126
|
+
- `nodes.get`
|
|
127
|
+
- `nodes.getPorts`
|
|
128
|
+
- `nodes.search`
|
|
129
|
+
- `nodeTypes.list`
|
|
130
|
+
- `nodeTypes.search`
|
|
131
|
+
- `nodeTypes.get`
|
|
132
|
+
- `ports.get`
|
|
133
|
+
- `ports.listConnections`
|
|
134
|
+
- `wires.get`
|
|
135
|
+
- `wires.getAll`
|
|
136
|
+
- `uniforms.list`
|
|
137
|
+
- `uniforms.get`
|
|
138
|
+
- `uniforms.getNodeTypes`
|
|
139
|
+
- `shader.getInfo`
|
|
140
|
+
- `shader.getGeneratedCode`
|
|
141
|
+
- `preview.getSettings`
|
|
142
|
+
- `preview.getConsoleEntries`
|
|
143
|
+
- `preview.getErrors`
|
|
144
|
+
- `preview.getNodePreview`
|
|
145
|
+
- `preview.getStartupScriptInfo`
|
|
146
|
+
- `camera.getState`
|
|
147
|
+
- `projects.listExamples`
|
|
148
|
+
- `customNodes.list`
|
|
149
|
+
- `customNodes.get`
|
|
150
|
+
- `ai.getWarnings`
|
|
151
|
+
- `ai.runDebugCheck`
|
|
152
|
+
|
|
153
|
+
Side-effecting calls:
|
|
154
|
+
|
|
155
|
+
- `session.initAIWork`
|
|
156
|
+
- `session.updateAIWork`
|
|
157
|
+
- `session.endAIWork`
|
|
158
|
+
- `runCommands`
|
|
159
|
+
- `nodes.create`
|
|
160
|
+
- `nodes.edit`
|
|
161
|
+
- `nodes.delete`
|
|
162
|
+
- `wires.create`
|
|
163
|
+
- `wires.delete`
|
|
164
|
+
- `uniforms.create`
|
|
165
|
+
- `uniforms.createNode`
|
|
166
|
+
- `uniforms.edit`
|
|
167
|
+
- `uniforms.reorder`
|
|
168
|
+
- `uniforms.delete`
|
|
169
|
+
- `shader.updateInfo`
|
|
170
|
+
- `preview.updateSettings`
|
|
171
|
+
- `preview.clearConsole`
|
|
172
|
+
- `preview.resetSettings`
|
|
173
|
+
- `preview.setNodePreview`
|
|
174
|
+
- `preview.toggleNodePreview`
|
|
175
|
+
- `preview.screenshot`
|
|
176
|
+
- `layout.autoArrange`
|
|
177
|
+
- `camera.center`
|
|
178
|
+
- `camera.zoomToFit`
|
|
179
|
+
- `camera.setPosition`
|
|
180
|
+
- `camera.setZoom`
|
|
181
|
+
- `projects.openExample`
|
|
182
|
+
- `projects.exportAddon`
|
|
183
|
+
|
|
184
|
+
## Discovery guidance
|
|
185
|
+
|
|
186
|
+
When the model does not know which node type to use:
|
|
187
|
+
|
|
188
|
+
- Prefer `nodeTypes.search(query)` to search by concept.
|
|
189
|
+
- Use `nodeTypes.list()` to inspect all available node types.
|
|
190
|
+
- Use `nodeTypes.get(typeKey)` to inspect one exact type before creating it.
|
|
191
|
+
- Use `nodes.search(query)` as a convenience alias for node type search.
|
|
192
|
+
- Use `uniforms.getNodeTypes()` to discover generated uniform-backed node types.
|
|
193
|
+
- Use `customNodes.list()` to discover reusable custom node definitions already in the project.
|
|
194
|
+
|
|
195
|
+
Good search queries:
|
|
196
|
+
|
|
197
|
+
- `"depth"`
|
|
198
|
+
- `"uv"`
|
|
199
|
+
- `"gradient"`
|
|
200
|
+
- `"noise"`
|
|
201
|
+
- `"premultiply"`
|
|
202
|
+
- `"light"`
|
|
203
|
+
|
|
204
|
+
Use discovery before guessing a `typeKey`.
|
|
205
|
+
|
|
206
|
+
## Node and port discipline
|
|
68
207
|
|
|
69
208
|
- Always inspect ports before creating wires.
|
|
70
209
|
- Use explicit port refs: `{ nodeId, kind, index }`.
|
|
71
210
|
- Prefer `index` over `name` for automation stability.
|
|
72
211
|
- Use `declaredType` and `resolvedType` to understand generic or dynamic nodes.
|
|
73
212
|
- If an input port is editable and unconnected, prefer setting its value directly instead of creating a separate constant node.
|
|
74
|
-
-
|
|
213
|
+
- This applies to editable floats, vec2, vec3, and vec4 values when the input is intended to be a local literal.
|
|
214
|
+
|
|
215
|
+
Port reference examples:
|
|
216
|
+
|
|
217
|
+
- `{ nodeId: 12, kind: "input", index: 0 }`
|
|
218
|
+
- `{ nodeId: 12, kind: "output", index: 1 }`
|
|
219
|
+
|
|
220
|
+
## Editing node input values
|
|
221
|
+
|
|
222
|
+
This is one of the most important workflows.
|
|
223
|
+
|
|
224
|
+
To change a node's editable input values:
|
|
225
|
+
|
|
226
|
+
1. Read the node with `nodes.get(nodeId)`.
|
|
227
|
+
2. Inspect `editableInputValues` to see which inputs are editable and currently unconnected.
|
|
228
|
+
3. Edit with `nodes.edit(nodeId, { inputValues: ... })`.
|
|
229
|
+
|
|
230
|
+
Rules:
|
|
231
|
+
|
|
232
|
+
- Only editable, unconnected input ports can be changed this way.
|
|
233
|
+
- If a port is already wired, disconnect or rewire it before editing its direct value.
|
|
234
|
+
- Prefer editing the input value directly when the value is local and used once.
|
|
235
|
+
- Prefer adding nodes or variables when the value needs to be reused elsewhere.
|
|
236
|
+
|
|
237
|
+
Example workflow:
|
|
238
|
+
|
|
239
|
+
- call `nodes.get(nodeId)`
|
|
240
|
+
- inspect `editableInputValues`
|
|
241
|
+
- call `nodes.edit(nodeId, { inputValues: { B: [0, 0, 0, 1] } })`
|
|
242
|
+
- re-read the node with `nodes.get(nodeId)`
|
|
243
|
+
|
|
244
|
+
Name-based example:
|
|
245
|
+
|
|
246
|
+
- `nodes.edit(42, { inputValues: { B: [0, 0, 0, 1] } })`
|
|
247
|
+
|
|
248
|
+
Index-based example:
|
|
249
|
+
|
|
250
|
+
- `nodes.edit(42, { inputValues: { 0: 1.25 } })`
|
|
251
|
+
|
|
252
|
+
Prefer this over adding a `Vec4` or `Float` node when the value is just a local literal used once.
|
|
253
|
+
|
|
254
|
+
## Node editing guidance
|
|
255
|
+
|
|
256
|
+
`nodes.edit(nodeId, patch)` is used for targeted edits to an existing node.
|
|
257
|
+
|
|
258
|
+
Common patch fields:
|
|
259
|
+
|
|
260
|
+
- `x`
|
|
261
|
+
- `y`
|
|
262
|
+
- `position: { x, y }`
|
|
263
|
+
- `operation`
|
|
264
|
+
- `customInput`
|
|
265
|
+
- `selectedVariable`
|
|
266
|
+
- `inputValues`
|
|
267
|
+
- `gradientStops`
|
|
268
|
+
- `data`
|
|
269
|
+
|
|
270
|
+
Examples:
|
|
75
271
|
|
|
76
|
-
|
|
272
|
+
- move a node: `nodes.edit(nodeId, { position: { x: 400, y: 220 } })`
|
|
273
|
+
- change an operation dropdown: `nodes.edit(nodeId, { operation: "multiply" })`
|
|
274
|
+
- rename a variable node: `nodes.edit(nodeId, { customInput: "baseMask" })`
|
|
275
|
+
- set editable inputs: `nodes.edit(nodeId, { inputValues: { Strength: 0.5 } })`
|
|
276
|
+
|
|
277
|
+
Do not send empty patches.
|
|
278
|
+
|
|
279
|
+
## Wires
|
|
280
|
+
|
|
281
|
+
Before wiring:
|
|
282
|
+
|
|
283
|
+
- inspect both sides with `nodes.getPorts(nodeId)`
|
|
284
|
+
- confirm output vs input direction
|
|
285
|
+
- confirm `resolvedType` compatibility
|
|
286
|
+
|
|
287
|
+
Rules:
|
|
288
|
+
|
|
289
|
+
- A wire should connect one output port to one input port.
|
|
290
|
+
- Reconnecting an already-connected input may replace the current connection.
|
|
291
|
+
- Recreating the exact same connection should be treated as idempotent.
|
|
292
|
+
- After wiring, verify with `ports.listConnections(portRef)` or `wires.getAll()`.
|
|
293
|
+
|
|
294
|
+
Recommended wiring loop:
|
|
295
|
+
|
|
296
|
+
1. inspect source node ports
|
|
297
|
+
2. inspect target node ports
|
|
298
|
+
3. create wire
|
|
299
|
+
4. re-read connections on the source or target port
|
|
300
|
+
|
|
301
|
+
## Variables
|
|
302
|
+
|
|
303
|
+
Use variable nodes to reduce wire clutter.
|
|
304
|
+
|
|
305
|
+
- `Set Variable` stores a computed value once.
|
|
306
|
+
- `Get Variable` reads it back in multiple places.
|
|
307
|
+
- The `Get Variable` output type is inferred from the matching `Set Variable` input.
|
|
308
|
+
|
|
309
|
+
Preferred rule:
|
|
310
|
+
|
|
311
|
+
- If one output would feed many distant nodes, prefer a variable instead of many long wires.
|
|
312
|
+
- This makes `autoArrange()` cleaner and keeps the graph easier to inspect.
|
|
313
|
+
|
|
314
|
+
AI-specific warning system:
|
|
315
|
+
|
|
316
|
+
- Use `ai.getWarnings` during verification.
|
|
317
|
+
- The multi-output warning only matters when one output fans out to multiple different target nodes.
|
|
318
|
+
- If multiple wires from one output all go into the same node, that warning does not apply.
|
|
319
|
+
- If it reports that an output port fans out multiple times:
|
|
320
|
+
- use `Set Variable` and `Get Variable` if the value represents a larger computed tree or reusable branch
|
|
321
|
+
- duplicate small local nodes if the output is just a simple leaf value and duplication is cleaner
|
|
322
|
+
- Treat these warnings as layout and maintainability guidance, not as compile errors.
|
|
323
|
+
|
|
324
|
+
Good variable cases:
|
|
325
|
+
|
|
326
|
+
- reused UV transforms
|
|
327
|
+
- reused masks
|
|
328
|
+
- reused sampled colors
|
|
329
|
+
- reused lighting terms
|
|
330
|
+
- any value with 3 or more downstream uses
|
|
331
|
+
|
|
332
|
+
## Existing custom nodes
|
|
333
|
+
|
|
334
|
+
Existing custom nodes are part of the project and can be inspected and used.
|
|
335
|
+
|
|
336
|
+
- It is safe to inspect existing custom node definitions.
|
|
337
|
+
- It is safe to place existing custom nodes in the graph if they already exist in the project.
|
|
338
|
+
- Creating a new custom node definition is the advanced escape hatch and should be avoided unless the user explicitly asks for it.
|
|
339
|
+
- Prefer built-in nodes first, but if a project already contains a custom node designed for a task, using it is acceptable.
|
|
340
|
+
|
|
341
|
+
Inspect existing custom nodes with:
|
|
342
|
+
|
|
343
|
+
- `customNodes.list()`
|
|
344
|
+
- `customNodes.get(id)`
|
|
345
|
+
- `nodeTypes.get("custom_<id>")`
|
|
346
|
+
|
|
347
|
+
When a custom node already exists:
|
|
348
|
+
|
|
349
|
+
- inspect its ports and code first
|
|
350
|
+
- treat it like a project-specific reusable node
|
|
351
|
+
- understand it before placing or wiring it
|
|
352
|
+
|
|
353
|
+
## Uniform workflows
|
|
354
|
+
|
|
355
|
+
Uniform workflow usually looks like this:
|
|
356
|
+
|
|
357
|
+
1. `uniforms.create(...)`
|
|
358
|
+
2. `uniforms.createNode(uniformId, ...)`
|
|
359
|
+
3. inspect the created node with `nodes.getPorts(nodeId)`
|
|
360
|
+
4. wire it into the graph
|
|
361
|
+
|
|
362
|
+
Use uniforms for exposed user-facing values that should exist outside a single node.
|
|
363
|
+
|
|
364
|
+
Prefer direct editable input values for local literals and uniforms for reusable effect controls.
|
|
365
|
+
|
|
366
|
+
## Preview guidance
|
|
77
367
|
|
|
78
368
|
- Default preview compiles from `Output`.
|
|
79
|
-
-
|
|
369
|
+
- Node preview compiles from one selected intermediate node instead.
|
|
370
|
+
- Use node preview for masks, UVs, gradients, lighting terms, and intermediate color values.
|
|
371
|
+
- A node can only be previewed if it resolves to `float`, `vec2`, `vec3`, or `vec4` on one output.
|
|
80
372
|
- Use the preview console as part of the normal debug loop.
|
|
81
|
-
- Use screenshots to confirm that the visual result matches the intent.
|
|
82
|
-
|
|
373
|
+
- Use screenshots to confirm that the visual result actually matches the intent.
|
|
374
|
+
|
|
375
|
+
Recommended debug loop:
|
|
376
|
+
|
|
377
|
+
1. inspect graph state
|
|
378
|
+
2. make one structural change or one tight batch
|
|
379
|
+
3. verify affected nodes and wires
|
|
380
|
+
4. call `shader.getGeneratedCode`
|
|
381
|
+
5. clear preview console and inspect `preview.getErrors`
|
|
382
|
+
6. use node preview for intermediate values if needed
|
|
383
|
+
7. take a screenshot with `preview.screenshot` for visual verification
|
|
384
|
+
8. inspect `ai.getWarnings` for layout and reuse issues
|
|
385
|
+
9. adjust and repeat only if needed
|
|
83
386
|
|
|
84
|
-
|
|
387
|
+
You can also use the bundled helper:
|
|
388
|
+
|
|
389
|
+
- `ai.runDebugCheck()`
|
|
390
|
+
- `ai.runDebugCheck({ includeScreenshot: true })`
|
|
391
|
+
- `ai.runDebugCheck({ takeScreenshot: true })`
|
|
392
|
+
|
|
393
|
+
`ai.runDebugCheck()` bundles:
|
|
394
|
+
|
|
395
|
+
- generated code validation
|
|
396
|
+
- preview error collection
|
|
397
|
+
- AI graph warnings
|
|
398
|
+
- optional screenshot capture
|
|
399
|
+
|
|
400
|
+
## Renderer guidance
|
|
401
|
+
|
|
402
|
+
- Normally build one graph and let the tool generate all targets.
|
|
403
|
+
- Only branch behavior when absolutely necessary.
|
|
404
|
+
- If renderer-specific logic is needed, prefer the shader test node.
|
|
405
|
+
- Use preview `shaderLanguage` switching to test generated targets.
|
|
406
|
+
|
|
407
|
+
## Scale-aware values
|
|
408
|
+
|
|
409
|
+
- Do not rely on tiny arbitrary constants for widths, offsets, blur radii, distortion amounts, or outline thickness.
|
|
410
|
+
- Prefer `pixelSize` for screen-space scaling.
|
|
411
|
+
- Prefer `texelSize` for texture or world-sampling offsets.
|
|
412
|
+
- If an effect looks too subtle or too tiny, first check whether it should be scaled by `pixelSize` or `texelSize` instead of increasing magic constants.
|
|
413
|
+
|
|
414
|
+
Rule of thumb:
|
|
415
|
+
|
|
416
|
+
- screen-relative effect -> `pixelSize`
|
|
417
|
+
- texture/sample offset effect -> `texelSize`
|
|
418
|
+
|
|
419
|
+
## Construct shader guidance
|
|
420
|
+
|
|
421
|
+
Construct Shader Graph is a Construct effect authoring tool, so the AI should understand a few Construct-specific ideas.
|
|
85
422
|
|
|
86
423
|
- Important shader settings include `blendsBackground`, `usesDepth`, `crossSampling`, `animated`, `mustPredraw`, `supports3DDirectRendering`, `extendBoxH`, and `extendBoxV`.
|
|
87
424
|
- Background sampling only makes sense when `blendsBackground` is enabled.
|
|
88
425
|
- Depth sampling only makes sense when `usesDepth` is enabled.
|
|
89
426
|
- Construct uses premultiplied alpha, so many color workflows should use `unpremultiply` before edits and `premultiply` before output.
|
|
90
|
-
|
|
427
|
+
|
|
428
|
+
Official references:
|
|
429
|
+
|
|
430
|
+
- `https://www.construct.net/en/make-games/manuals/addon-sdk/guide/configuring-effects`
|
|
431
|
+
- `https://www.construct.net/en/make-games/manuals/addon-sdk/guide/configuring-effects/webgl-shaders`
|
|
432
|
+
- `https://www.construct.net/en/make-games/manuals/addon-sdk/guide/configuring-effects/webgpu-shaders`
|
|
433
|
+
- `https://www.construct.net/en/make-games/manuals/construct-3/project-primitives/objects/effects`
|
|
434
|
+
- `https://www.construct.net/en/make-games/manuals/construct-3/scripting/scripting-reference/object-interfaces/ieffectinstance`
|
|
435
|
+
|
|
436
|
+
## Prefer existing Construct helper nodes
|
|
437
|
+
|
|
438
|
+
Many common Construct shader calculations are already implemented as nodes. Prefer these over rebuilding the math manually.
|
|
439
|
+
|
|
440
|
+
- Sampling and UV nodes: `frontUV`, `backUV`, `depthUV`, `textureFront`, `textureBack`, `textureDepth`, `samplerFront`, `samplerBack`, `samplerDepth`, `textureSample`, `textureSampleLOD`, `textureSampleGrad`, `texelFetch`
|
|
441
|
+
- Built-in Construct values: `builtinSrcStart`, `builtinSrcEnd`, `builtinSrcSize`, `builtinSrcCenter`, `builtinSrcOriginStart`, `builtinSrcOriginEnd`, `builtinSrcOriginSize`, `builtinSrcOriginCenter`, `builtinLayoutStart`, `builtinLayoutEnd`, `builtinLayoutCenter`, `builtinLayoutSize`, `builtinDestStart`, `builtinDestEnd`, `builtinDestCenter`, `builtinDestSize`, `builtinDevicePixelRatio`, `builtinLayerScale`, `builtinLayerAngle`, `builtinSeconds`, `builtinZNear`, `builtinZFar`
|
|
442
|
+
- Coordinate helpers: `pixelSize`, `texelSize`, `layoutPixelSize`, `srcOriginToNorm`, `srcToNorm`, `normToSrc`, `normToSrcOrigin`, `srcToDest`, `clampToSrc`, `clampToSrcOrigin`, `clampToDest`, `getLayoutPos`
|
|
443
|
+
- Color and depth helpers: `premultiply`, `unpremultiply`, `linearizeDepth`, `normalFromDepth`, `grayscale`, `rgbToHsl`, `hslToRgb`
|
|
444
|
+
- Higher-level helpers: `gradientMap`, `blendMode`, `directionalLight`, `rimLight`, `hemisphereLight`, `specularLight`, `matcap`
|
|
445
|
+
|
|
446
|
+
## Startup script guidance
|
|
447
|
+
|
|
448
|
+
The startup script is optional and exists only to make preview testing easier.
|
|
449
|
+
|
|
450
|
+
- Use it for preview interactivity, not shader logic.
|
|
451
|
+
- Good uses: camera setup, object rotation, layout tweaks, quick runtime animation.
|
|
452
|
+
- Keep it short and preview-focused.
|
|
453
|
+
- Do not depend on it for exported shader behavior.
|
|
454
|
+
|
|
455
|
+
Available startup script variables:
|
|
456
|
+
|
|
457
|
+
- `runtime`
|
|
458
|
+
- `sprite`
|
|
459
|
+
- `shape3D`
|
|
460
|
+
- `background`
|
|
461
|
+
- `background3d`
|
|
462
|
+
- `camera`
|
|
463
|
+
- `layout`
|
|
464
|
+
- `layer`
|
|
465
|
+
|
|
466
|
+
Construct scripting reference:
|
|
467
|
+
|
|
468
|
+
- `https://www.construct.net/en/make-games/manuals/construct-3/scripting/scripting-reference`
|
|
469
|
+
|
|
470
|
+
## Projects and session workflow
|
|
471
|
+
|
|
472
|
+
Use the session API for start, progress, and finish through `call_project_method`.
|
|
473
|
+
|
|
474
|
+
Project rules:
|
|
475
|
+
|
|
476
|
+
- Use `projects.listExamples` and `projects.openExample` for built-in examples.
|
|
477
|
+
- Do not assume the AI should open arbitrary local files.
|
|
478
|
+
- Do not assume the AI should save project files on its own.
|
|
479
|
+
- Use `projects.exportAddon` when the user wants a downloadable export.
|
|
480
|
+
|
|
481
|
+
## Good vs bad behavior
|
|
482
|
+
|
|
483
|
+
Good:
|
|
484
|
+
|
|
485
|
+
- Inspect ids before editing.
|
|
486
|
+
- Inspect ports before wiring.
|
|
487
|
+
- Use `runCommands` for a tightly related group of edits when batching helps.
|
|
488
|
+
- Re-read affected nodes and ports after structural changes.
|
|
489
|
+
- Prefer helper nodes and variable nodes.
|
|
490
|
+
- Reuse an existing custom node when it is clearly the project-specific tool for the job.
|
|
491
|
+
- Use preview errors, node preview, and screenshots as part of verification.
|
|
492
|
+
- Scale visible effects with `pixelSize` or `texelSize` instead of tiny magic constants.
|
|
493
|
+
|
|
494
|
+
Bad:
|
|
495
|
+
|
|
496
|
+
- Guess node ids from names.
|
|
497
|
+
- Rebuild a whole graph for a tiny fix.
|
|
498
|
+
- Create many long wires from one output when variables would do.
|
|
499
|
+
- Use startup scripts to simulate graph logic.
|
|
500
|
+
- Split the graph by renderer without a real need.
|
|
501
|
+
- Create new custom nodes casually instead of composing the graph from existing nodes.
|
|
91
502
|
|
|
92
503
|
## Troubleshooting
|
|
93
504
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
505
|
+
- `No projects listed`
|
|
506
|
+
- Make sure the page is connected to the MCP bridge.
|
|
507
|
+
- Re-run `list_projects`.
|
|
508
|
+
- `Wrong project selected`
|
|
509
|
+
- Re-check `shader.getInfo()` metadata from the selected project.
|
|
510
|
+
- Pick the correct session with `select_project`.
|
|
511
|
+
- `Node not found`
|
|
512
|
+
- Re-run `nodes.list` and resolve the correct id.
|
|
513
|
+
- `Unknown node type`
|
|
514
|
+
- Use `nodeTypes.search` or `nodeTypes.list` before guessing a `typeKey`.
|
|
515
|
+
- Inspect `nodeTypes.get(typeKey)` before creating a node.
|
|
516
|
+
- `Wire creation failed`
|
|
517
|
+
- Inspect both nodes with `nodes.getPorts`.
|
|
518
|
+
- Check port direction and `resolvedType`.
|
|
519
|
+
- `Generated code failed`
|
|
520
|
+
- Make sure an `Output` node exists.
|
|
521
|
+
- Re-check required connections.
|
|
522
|
+
- `Preview looks wrong`
|
|
523
|
+
- Inspect `preview.getSettings`.
|
|
524
|
+
- Clear and inspect `preview.getErrors`.
|
|
525
|
+
- Test node preview on intermediate values.
|
|
526
|
+
- Capture a screenshot and inspect the actual visible result.
|
|
527
|
+
- Switch `shaderLanguage` to compare targets.
|
|
528
|
+
- `Graph became cluttered`
|
|
529
|
+
- Replace repeated fan-out with `Set Variable` and `Get Variable`.
|
|
530
|
+
- Run `layout.autoArrange` after structural edits.
|
|
531
|
+
- `Value is reused too many times`
|
|
532
|
+
- Inspect `ai.getWarnings`.
|
|
533
|
+
- Use a variable for reused computed branches.
|
|
534
|
+
- Duplicate tiny leaf nodes when that is simpler and cleaner.
|