{"_id":"@basementstudio/shader-lab-mcp","name":"@basementstudio/shader-lab-mcp","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@basementstudio/shader-lab-mcp","description":"MCP server that drives the Shader Lab editor: layer control and custom shader authoring. Built with xmcp.","version":"0.1.0","license":"MIT","repository":{"type":"git","url":"git+https://github.com/basementstudio/shader-lab.git","directory":"packages/shader-lab-mcp"},"homepage":"https://github.com/basementstudio/shader-lab/tree/main/packages/shader-lab-mcp#readme","keywords":["mcp","shader","webgpu","tsl","three","shader-lab"],"bin":{"shader-lab-mcp":"dist/stdio.js"},"publishConfig":{"access":"public"},"scripts":{"generate":"bun run scripts/generate-reference-data.ts","build":"bun run generate && xmcp build 1>&2","dev":"xmcp dev","start":"xmcp build 1>&2 && node dist/stdio.js","prepublishOnly":"bun run build","typecheck":"tsc --noEmit"},"dependencies":{"ws":"^8.21.0","xmcp":"^0.6.13","zod":"^4.3.6"},"devDependencies":{"@modelcontextprotocol/sdk":"1.17.5","@types/bun":"^1.3.6","@types/node":"^26.1.1","@types/ws":"^8.18.1","typescript":"^5.9.3"},"_id":"@basementstudio/shader-lab-mcp@0.1.0","bugs":{"url":"https://github.com/basementstudio/shader-lab/issues"},"_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-hNnuym6HVwOz/XPEgU7R49MZWG990qXYCXMtB0TDqL+Kf7QjJuhQG36+LzFc620/UvW4fEAV0LrzikTMnrZ1QQ==","shasum":"c9888fdce5ec5c31a6d98d4d05640409784c1e49","tarball":"https://registry.npmjs.org/@basementstudio/shader-lab-mcp/-/shader-lab-mcp-0.1.0.tgz","fileCount":23,"unpackedSize":3106838,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD0SZfortWyb9N2pbeCQjnFR09T/R97Edn1F/bzLO4vNwIhAKSH49KV1s1ogHHf2qIQi07hcPdV+1gukT1x4gMEyENI"}]},"_npmUser":{"name":"gitchad","email":"tobias@basement.studio"},"directories":{},"maintainers":[{"name":"fedealvarezcampos","email":"fedealvarezcampos@gmail.com"},{"name":"bertodev","email":"bautista@basement.studio"},{"name":"gitchad","email":"tobias@basement.studio"},{"name":"mesteban","email":"mariana@basement.studio"},{"name":"valentinabearzotti","email":"valebearzotti1@gmail.com"},{"name":"mike.aguilar.bsmnt","email":"miqueas@basement.studio"},{"name":"ignmandagaran","email":"ignaciofmandagaran@gmail.com"},{"name":"tomasfdev","email":"hellotomasdev@gmail.com"},{"name":"joserago","email":"jose@basement.studio"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/shader-lab-mcp_0.1.0_1786722410729_0.5465488363281601"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-14T15:46:50.549Z","0.1.0":"2026-08-14T15:46:51.013Z","modified":"2026-08-14T15:46:51.309Z"},"maintainers":[{"name":"fedealvarezcampos","email":"fedealvarezcampos@gmail.com"},{"name":"bertodev","email":"bautista@basement.studio"},{"name":"gitchad","email":"tobias@basement.studio"},{"name":"mesteban","email":"mariana@basement.studio"},{"name":"valentinabearzotti","email":"valebearzotti1@gmail.com"},{"name":"mike.aguilar.bsmnt","email":"miqueas@basement.studio"},{"name":"ignmandagaran","email":"ignaciofmandagaran@gmail.com"},{"name":"tomasfdev","email":"hellotomasdev@gmail.com"},{"name":"joserago","email":"jose@basement.studio"}],"description":"MCP server that drives the Shader Lab editor: layer control and custom shader authoring. Built with xmcp.","homepage":"https://github.com/basementstudio/shader-lab/tree/main/packages/shader-lab-mcp#readme","keywords":["mcp","shader","webgpu","tsl","three","shader-lab"],"repository":{"type":"git","url":"git+https://github.com/basementstudio/shader-lab.git","directory":"packages/shader-lab-mcp"},"bugs":{"url":"https://github.com/basementstudio/shader-lab/issues"},"license":"MIT","readme":"# @basementstudio/shader-lab-mcp\n\nMCP server that lets an AI agent drive a running Shader Lab editor tab: create,\nremove, reorder, and tweak layers — and write custom TSL shaders with a real\nfeedback loop (compile errors and canvas screenshots go straight back to the\nagent). Built with [xmcp](https://xmcp.dev): tools live as files in\n`src/tools/`, the server config (transport, instructions) lives in\n`xmcp.config.ts`, and `xmcp build` bundles everything into `dist/stdio.js`.\n\n## How it works\n\n```\nMCP client (Claude Code) ⇄ stdio ⇄ shader-lab-mcp (Bun process)\n                                        ⇅ WebSocket (127.0.0.1:7420)\n                                  editor tab (?agent=1)\n```\n\nThe server speaks MCP over stdio and hosts a localhost-only WebSocket bridge.\nThe editor connects to the bridge when opened with `?agent=1`; every tool call\nis relayed to the tab and executed through the editor's normal zustand store\nactions, so **everything the agent does lands in the undo history** (Cmd+Z\nworks).\n\n## Setup\n\nYou do **not** need this repo, and you do not need to run the app. Add the\nserver to your MCP client (Claude Code, Cursor, …):\n\n```json\n{\n  \"mcpServers\": {\n    \"shader-lab\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@basementstudio/shader-lab-mcp\"]\n    }\n  }\n}\n```\n\nThen open the editor in a WebGPU browser with `?agent=1` appended — a\ndeployment (`https://eng.basement.studio/tools/shader-lab?agent=1`, or any\n`*.vercel.app` preview) or a local dev server\n(`http://localhost:3000/tools/shader-lab?agent=1`). Ask your agent for\n`get_project_state` to confirm the connection.\n\nThe server always runs on your own machine and the bridge is loopback-only, so\na deployed tab connects back to your localhost — the deployment itself is never\ninvolved.\n\n**One editor tab at a time.** The bridge holds a single connection; opening a\nsecond tab takes the slot, and the two will trade it back and forth every few\nseconds until you close one.\n\nWorking inside this repo instead? `.mcp.json` at the root already registers the\nserver via `bun run --cwd packages/shader-lab-mcp start`, so Claude Code picks\nit up with no config.\n\nEnvironment variables:\n\n- `SHADER_LAB_MCP_PORT` — bridge port (default `7420`; pass `?agentPort=` to\n  the editor if you change it)\n- `SHADER_LAB_AGENT_TOKEN` — optional shared secret; when set, the tab must be\n  opened with `?agent=1&agentToken=<token>`\n- `SHADER_LAB_ALLOWED_ORIGINS` — extra origins allowed to connect (comma\n  separated, wildcards like `https://*.example.com` supported). Localhost,\n  production (`https://eng.basement.studio`), and Vercel previews\n  (`https://*.vercel.app`) are always allowed — deployed tabs work with zero\n  configuration. The server always runs on your machine; deployed tabs\n  connect to your own loopback.\n\nOnly connections from `localhost` origins (plus any explicitly allowed extra\norigins) are accepted, and the bridge binds to `127.0.0.1`.\n\n## Tools\n\n- **Read** — `get_project_state`, `get_layer`, `list_layer_types`,\n  `describe_layer_type` (full param schema with ranges/options/defaults),\n  `screenshot` (renders through the export pipeline, returns a PNG)\n- **Mutate** — `add_layer`, `remove_layers`, `duplicate_layer`,\n  `reorder_layer`, `rename_layer`, `set_layer_visibility`, `select_layer`,\n  `update_layer` (opacity/hue/saturation/blend/composite/mask),\n  `update_layer_params` (validated against the layer schema — out-of-range\n  numbers are clamped and reported, bad keys/types rejected with reasons),\n  `reset_layer_params`\n- **Custom shaders** — `write_custom_shader` (writes TSL source and waits for\n  the compile result; returns the exact compiler/runtime error on failure),\n  `get_custom_shader`, `get_shader_api_reference` (the shader contract plus\n  every global available to sketches — house util sources are read from disk\n  and `three/tsl` exports are enumerated at runtime, so the reference can\n  never drift from what actually executes)\n\n## Hidden tabs\n\nThe editor tab does not need to stay foregrounded. Chrome pauses\n`requestAnimationFrame` in hidden tabs, which would normally park the render\nloop — bridge commands that need a frame (shader compiles, screenshots) pump\none manually instead, so the whole loop works with the tab buried behind\nother windows.\n\n## The shader loop\n\n```\nget_shader_api_reference → write_custom_shader → (error? fix → write again)\n    → screenshot → tweak params → screenshot\n```\n\n`write_custom_shader` resolves when the editor finishes compiling that exact\nsource revision, so the agent sees `{ compiled: false, error: \"...\" }` with\nthe real sanitizer/transpile/eval message and can iterate immediately.\n\n## Development\n\n- `bun run --cwd packages/shader-lab-mcp dev` — xmcp dev server with hot reload\n- `bun run --cwd packages/shader-lab-mcp build` — bundle to `dist/stdio.js`\n- `bun run --cwd packages/shader-lab-mcp typecheck` — xmcp's own build-time\n  checker is disabled (it OOMs on the zod/tsl type surface); this is the type\n  gate instead\n- `bun test packages/shader-lab-mcp` — end-to-end test that builds the bundle,\n  spawns the real `dist/stdio.js`, connects an MCP client over stdio, and fakes\n  an editor tab over the real WebSocket bridge (headless stores, no GPU needed)\n\nLayout: one file per tool in `src/tools/` (xmcp file-system routing), the\n`shader-lab://shader-api` resource in `src/resources/(shader-lab)/`, and the\nshared WebSocket bridge + shader reference in `src/lib/`.\n","readmeFilename":"README.md","_rev":"1-73a8d35567fc015f4fcb3aa650ae6f13"}