Skip to content

Shader Lab MCP server: layer control and custom shader authoring#107

Open
git-chad wants to merge 11 commits into
mainfrom
plan/009-shader-lab-mcp
Open

Shader Lab MCP server: layer control and custom shader authoring#107
git-chad wants to merge 11 commits into
mainfrom
plan/009-shader-lab-mcp

Conversation

@git-chad

@git-chad git-chad commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

MCP server that drives a running Shader Lab editor tab: create/remove/reorder/tweak layers, and — the headline — write custom TSL shaders with a real feedback loop (compile errors and canvas screenshots returned to the agent). Implements plans/009-shader-lab-mcp.md (included). Built with xmcp.

Architecture

  • packages/shader-lab-mcp/ — private xmcp app: one file per tool in src/tools/ (18 tools), the shader-lab://shader-api resource in src/resources/, server config (stdio transport, instructions, serverInfo) in xmcp.config.ts. xmcp build bundles to dist/stdio.js; registered in .mcp.json so Claude Code picks it up per-session.
  • The WebSocket bridge (src/lib/bridge.ts, on ws, localhost-only, origin-checked, optional token) relays tool calls into the editor tab.
  • src/lib/agent-bridge/ in the app — the editor-side client, command executor over the existing zustand store actions, compile-result events, screenshot capture. All mutations land in the normal undo history (Cmd+Z works on everything the agent does).
  • Topbar toggle: an xmcp-logo button enables/disables agent control (persisted in localStorage) with a live status dot — amber pulse while waiting for the MCP server, green when connected. ?agent=1 still force-enables for URL-based onboarding.

Tools (18)

  • Read: get_project_state, get_layer, list_layer_types, describe_layer_type (param schema from the layer registry), screenshot (export-pipeline render → PNG image content)
  • Mutate: add_layer, remove_layers, duplicate_layer, reorder_layer, rename_layer, set_layer_visibility, select_layer, update_layer, update_layer_params (clamp-and-report validation), reset_layer_params
  • Shaders: write_custom_shader (revision-keyed compile ack; returns the exact sanitizer/transpile/eval error), get_custom_shader, get_shader_api_reference (house util sources read from disk + three/tsl exports enumerated at runtime — can't drift)

Verified live

Driven end-to-end against a real Chrome Canary tab: wrote shaders that compiled on the GPU (fbm/cosine plasma, liquid-mercury chrome with RGB-split refraction, a Kuwahara oil-paint filter over a live webcam), tweaked params with live clamping, reordered layers, and screenshotted the results back. One doc fix came out of it: layer stacking is Photoshop-style (index 0 = top, applied last).

Testing

  • 28 unit tests (protocol codec + every command against the real stores headless) + 6 e2e tests that build the xmcp bundle, spawn the real dist/stdio.js, connect an MCP client over stdio, and fake an editor tab over the real bridge.
  • bun test 110 pass, lint clean, root + package typechecks green (CI gets a dedicated MCP typecheck step).

Notes

  • xmcp's parallel type-checker OOMs on the zod/tsl type surface → typescript.skipTypeCheck in xmcp.config.ts; the package's own tsc --noEmit is the type gate (in CI).
  • xmcp's runtime requires zod v4 schemas (_zod traits check) — package uses zod ^4.3.6, matching the app.
  • .gitignore broadened to node_modules/ + xmcp build outputs; changesets ignores the private MCP package.

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shader-lab Ready Ready Preview, Comment Jul 8, 2026 7:24pm

- packages/shader-lab-mcp: stdio MCP server + localhost WebSocket bridge
  (18 tools: project state, layer CRUD/reorder, schema-validated param
  updates with clamp-and-report, custom shader write with compile ack,
  runtime-enumerated shader API reference, screenshot via export pipeline)
- src/lib/agent-bridge: flag-gated editor client (?agent=1), command
  executor over zustand stores, compile-result events, screenshot capture
- custom-shader-pass emits revision-keyed compile results for the ack loop
- e2e test: real server + MCP client + fake editor tab over the bridge
@git-chad git-chad force-pushed the plan/009-shader-lab-mcp branch from 8a68baa to aa91405 Compare July 8, 2026 03:56
@git-chad git-chad changed the title Plan 009: Shader Lab MCP server — layer control and custom shader authoring Shader Lab MCP server: layer control and custom shader authoring Jul 8, 2026
git-chad added 2 commits July 8, 2026 14:54
- file-per-tool in src/tools (18 tools), shader-api resource in src/resources
- server config (stdio transport, instructions, serverInfo) in xmcp.config.ts
- bridge rewritten on ws (node-compatible, xmcp bundle runs under node)
- shader reference reads app sources from disk (repo-root resolution from cwd)
- zod v4 (xmcp runtime requires v4 _zod markers), xmcp checker disabled (OOMs)
- e2e test builds and spawns the real dist/stdio.js bundle
- agent-bridge zustand store: enabled (persisted to localStorage) + live status
- client reports connecting/connected through a status callback
- topbar button with the xmcp logo: off / waiting (amber pulse) / connected (green dot)
- ?agent=1 still force-enables for URL-based onboarding
- root tsc excludes packages/shader-lab-mcp (own alias config); CI gets a dedicated
  MCP package typecheck step
A failed bind previously left the bridge dead forever while every tool
reported 'no editor tab connected'. Now the bind retries every 2s and
tools report the real cause (port in use) until it succeeds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant