Three.js MCP server and Claude Code plugin paprika3d turns your coding agent into a game studio.
It pulls references from the web, writes a look and character sheets and a design doc with the creative calls left to you, builds the game, then runs loops that keep improving it, all in one lean package of tools.
Docs llms.txt View as Markdown GitHub
$ claude plugin marketplace add paprika3d/paprika3d$ claude plugin install paprika3d@paprika3d$ npx -y paprika3d serveAs an MCP server in the client's settings (.cursor/mcp.json, Windsurf, VS Code): the JSON entry.
$ codex mcp add paprika -- npx -y paprika3d serveNeeds Google Chrome and Node 20.11 or later; the Claude Code plugin needs Claude Code 2.1.118 or later.
Or hand this to your coding agent
Install paprika3d (https://paprika3d.com/docs/install) and make me a small three.js game: <one line about it>. In Claude Code, run /paprika3d:paprika-make with that line and answer its questions with me. Before you say it’s done, play its controls with paprika3d, look for objects that never appear, and time a frame against the desktop budget.
01 · Research references paprika-make · reference · sheet
Research references.
Once you say yes, it searches the whole web, YouTube included, for how the look, camera and sound are done. The pictures the game is built from are ones you keep, each with its licence.
How it works
In Claude Code, /paprika3d:paprika-make asks first whether to search the web. On a yes, subagents read trailers, gameplay and the makers' own posts into refs/study/ and its notes (they stay on your machine and are never published), and look for free CC0 and CC BY models whose licence they read on the model's own page. When you bring no pictures, another one finds some on Wikimedia Commons and Openverse and you keep the ones you want, each as refs/01.jpg, refs/02.jpg, … with its role and whether to match it.
## References
…
refs/04.jpg · layout (village → countryside: poles, wires, paddies, mountains) · inspiration · flickr.com/photos/88664052@N00/2708207172 (CC BY)
refs/05.jpg · layout (narrow town alley, clutter, bikes) · inspiration · flickr.com/photos/16877319@N07/4635633228 (CC BY)
refs/06.jpg · layout (straight paddy road, open countryside) · inspiration · flickr.com/photos/86424983@N00/4770701716 (CC BY)
…
sheet {"pictures": [refs/04.jpg, refs/05.jpg, refs/06.jpg], "title": "Kaeru Flip · references", "out": "refs/sheets/refs.png"}
Saved refs/sheets/refs.png (1248 × 402): 3 pictures, numbered as given, and 0 swatches. Made here, free; nothing was sent anywhere.
sheet for free. Photos: 1 “miyanotsuka landscape” by Molly Des Jardin, 2 “Back Alley” by Guwashi999, 3 “Vanishing point” by Ghost of Kuji, each CC BY 2.0, cropped.02 · Design spec sheet · reference · asset_search
Write the design spec.
A style sheet with a palette sampled from the references, character sheets, and a design doc that leaves the creative calls to you. You pick where each key model comes from.
sheet: the CC BY photos above and a palette of colours sampled with reference from its style references (the colours only; those pictures are not shown).How it works
From the tagged pictures and your answers it writes LOOK.md (palette, light, materials, shapes, camera, UI, sound, and three to five checks a look can verify), CHARACTERS.md for characters and key props, and for a game DESIGN.md, which asks you up to two calls that change what the game is (tone, how it progresses, how it is won) and leaves the rest to the builder with a recommendation. Every line names the picture behind it. sheet composes refs/sheets/LOOK.png for free; with your own fal, OpenAI or Gemini key it also draws a look board and character turnarounds, and with a fal, Meshy or Tripo key it can make a model. Then one question per key item: the library, a free model from the web, your key, or code. A one-line request takes a quick path of about four questions, and nothing paid is used unasked.
## Must have
…
3. **The road is the highway**: five coloured lanes on a downhill road, with a strike line just ahead of the toad. **Keyboard**: frets A S D F G, strum Enter / ↑ / ↓. **Touch**: tap a lane (no strum).
…
## Left to the builder
- The toad's exact outfit, the trick animations, the camera, the demo song, and the HUD typography.
reference {"file": "refs/09.png", "sample": [[144, 144], [1440, 480], [240, 600], [600, 264]]}
Colours (5 × 5 mean): (144, 144) #6ec9bb, (1440, 480) #f1f4ec, (240, 600) #9e5753, (600, 264) #397852.
sheet {"pictures": [refs/04.jpg, refs/05.jpg, refs/06.jpg], "palette": [9 sampled colours], "title": "Look: Kaeru Flip"}
Saved refs/sheets/LOOK.png (1248 × 538): 3 pictures, numbered as given, and 9 swatches. Made here, free; nothing was sent anywhere.
# Look: Kaeru Flip
Board: refs/sheets/LOOK.png
## Palette
sky #6ec9bb · shadow #72928e · wall grey #828b82 · off-white #f1f4ec · accents #b58749 #9e5753 (refs/09.png style match: sampled at (144, 144), (1440, 480), (240, 600))
## Camera
low behind the rider, the road running to the horizon (refs/06.jpg, layout, inspiration)
## Checks
1. Sky sampled at top centre of the opening look within 30/255 of #6ec9bb.
2. The toad is the warmest object on screen (look's Subject line names it).
03 · Build paprika-make · asset_search · model_run · geo.js · fx.js
Build it, with a critic.
paprika-make builds from the brief and the sheets. Then a critic reads the pictures and lists what is broken or falls short of the look.
How it works
The first version is written from BRIEF.md and the sheets: LOOK.md's palette and camera as written, each key item from the source you picked, and DESIGN.md's controls and core loop as what gets played. Once the page runs, a critic subagent reads the newest look pictures and lists glitches (z-fighting, objects through each other, floating or clipped things), each LOOK.md check the pictures fail and what a viewer would notice first; they are closed one at a time. open also puts two helper files in the project, geo.js (procedural geometry) and fx.js (sound, textures, particles, a lighting setup). asset_search (preview) finds a ready-made model, PBR texture or HDRI sky in a hosted library of 57,732 models, 3,545 textures and 1,430 skies, and model_run builds a model in code and saves it as a .glb. The board behind this text pulls apart into what made it: the gates are geo.js booleans, the pebbles fx.js placement, the duck one asset_search pick.
model_audit's shrink then capped its textures at 256 px (74 KB to 46 KB).asset_search {"query": "rubber duck", "maxTris": 6000}
2. f1de4fc390db4266a509b9739350512a · Rubber duck · stylized · 3458 tris · 0.075 MB · about 0.1 m tall · CC-BY-4.0 · …
asset_search {"pick": "f1de4fc3", "height": 1.2}
Picked f1de4fc390db4266a509b9739350512a, the one shown id that starts with "f1de4fc3".
Saved assets/rubber-duck-f1de4f.glb (Rubber duck, CC-BY-4.0); credited in assets/CREDITS.md
If the import map has no `three/addons/`, map it to three's `examples/jsm/` folder.
04 · Iterate paprika-loop
Keep improving it for hours.
paprika-loop runs a builder and a judge session each round, scores the game against the brief and commits it, until the time you gave it is up.
How it works
/paprika3d:paprika-loop <request> for <time> writes the brief with you, then starts fresh claude -p sessions: a builder makes as many improvements as fit, a read-only judge scores the page against the brief's Must have list and writes the next three improvements, and each round is committed, with the best tagged paprika-loop/best. You can edit paprika-loop/PROMPT.md while it runs. It starts only when you type it, each round is two Claude Code sessions billed as such, and it needs claude and git on PATH. The bars behind this text are the six rounds below, each car lap one round.
# paprika-loop report
6 iterations in 57 minutes, $11.90.
| n | min | turns | tokens | commit | score |
|---|---|---|---|---|---|
| 18 | 8.3 | 45 | 3699609 | b6a2ba6 | 7.3 |
| 19 | 7.5 | 38 | 2951642 | 789479e | 7.4 |
| 20 | 3.4 | 16 | 931095 | 07e4879 | 7.4 |
| 21 | 30 | 20 | 1060576 | 61f2ff4 | 7.6 |
| 22 | 4.5 | 14 | 786807 | 246cab0 | 7.8 |
| 23 | 3.7 | 18 | 750452 | 4529600 | 7.8 |
Best: iteration 22 at 246cab0 (score 7.8), tagged paprika-loop/best; the latest is 4529600.
05 · See and play open · look · interact · observe · eval · feel
See it and play it, frame by frame.
Every object gets a box, and anything missing gets a reason. Keys, clicks and touches land on exact frames, so every run comes out the same.
How it works
Your agent sees what is on screen, what never appears and why (behind the camera, outside the view, too small), which files failed to load, and which lighting and surface faults show. In the scene behind this text, every named object gets its box in page pixels, the way look lists them, and the screw on the mat is too small to see. Then it presses keys, clicks, touches and scrolls on exact frames of a paused, seeded clock and reads the state after each input: scroll on and the car drives one lap, frame by frame, its trace drawn behind it.
look {}
Picture: <project>/paprika3d/runs/2026-10-14T07-50-50-163Z/look-1.png
ID image: <project>/paprika3d/runs/2026-10-14T07-50-50-163Z/look-1-ids.png
On screen (2):
ground 68.0% [0, 241, 1279, 799]
car 0.0% [638, 346, 641, 347]
Never visible: lamp (3 units, behind the camera)
eval {"code": "return stats(\"car\")"}
total 1 meshes 24 v 12 tri
car 24 v 12 tri closed vol 0 genus 0 size 0.04×0.014×0.02 [position, normal, uv]
interact {"steps": [{"key": "ArrowRight", "frames": 30}, {"key": "ArrowRight", "down": false}]}
{"changed":{"x":1.5}}
interact {"steps": [{"key": " "}, {"key": " ", "down": false}, {"wait": 18}], "look": true}
{"changed":{"y":0.95,"jumps":1}}
Picture: <project>/paprika3d/runs/2026-10-16T23-20-52-829Z/look-2.png
Pixels: brightness 14%, colour saturation 50%, 0% near black, 0% blown out; 2% of the picture changed since the last look.
Hues: blue 90%, green 9%.
On screen (2):
floor 8.8% [0, 614, 1279, 689]
ball 0.71% [735, 452, 831, 547]
Never visible: none
06 · Test and measure interact save · test · perf
Turn a play into a test, and time every frame.
Saved plays rerun after every edit. Each frame is timed against a desktop, phone or Quest budget, with the objects that cost the most.
This page, measured in your browser: the numbers appear once the scene runs.
How it works
A play your agent saves reruns from a fresh reload with test, and the after-edit hook reruns every saved check after each edit, speaking only when one starts or stops failing: on the second lap each gate turns green as the car passes it. perf times the frame against a desktop, mobile, Quest or site budget, finds what costs it, and with optimize: true keeps only the speed-ups that leave the picture unchanged. The bars that rise next are this scene's own named groups, counted in your browser the way perf's cost table counts them (the height is the square root of the triangles); the line above is this page's frame time.
test ran after a refactor broke the wall rule), and Measure three.js draw calls and FPS, 2026-10-28, on a server with no GPU (the reply says so); cut to the lines showninteract {"steps": [{"state": {"player": {"x": 3, "z": 0}}}, {"key": "ArrowRight"}], "expect": {"player.x": 4, "score": 10, "coins.0.x": 1}, "save": "far-coin"}
{"changed":{"player":{"x":4},"coins":[{"x":1,"z":1}],"score":10,"moves":1}}
Expect: player.x 4 ✓ · score 10 ✓ · coins.0.x 1 ✓
Saved check "far-coin" in game-tests.json (3 checks now); `test` reruns them all, each from a fresh reload.
test {}
✓ coin-pickup
✗ wall-blocks: player.x 2, expected 1; moves 2, expected 1
✓ far-coin
2 of 3 saved checks passed in 0.5 s
perf {"costs": true}
248.3 ms median frame (p95 273 ms, 4 fps on average), 1797 draw calls, 54298 triangles, 0 MB assets; over budget: frameMs 248.3 of 16.7 ms; desktop budget; software renderer (no GPU): frame time is no budget signal, do not optimize for it
…
statue: 16384 triangles, 16384 casting shadows, 1 draw calls, 0 MB of textures
crates: 10800 triangles, 10800 casting shadows, 900 draw calls, 0 MB of textures
floor: 2 triangles, 0 casting shadows, 1 draw calls, 0 MB of textures
07 · Tools 16 MCP tools, in any MCP client
The 16 tools, by stage.
paprika-make and paprika-loop are Claude Code skills; the tools work in any MCP client.
References and spec
- reference
- Reads a picture at full resolution: a crop with a pixel grid, colours at points; with the page open, compares the two.
- sheet
- Names the image and 3D keys set, composes a free LOOK.png, and with your key draws boards and turnarounds or starts a model job.
Build
- asset_search
- Finds a model, PBR texture or HDRI sky in the hosted CC BY and CC0 library, and downloads the pick with its loading code and credit.
- model_run
- Builds a model in code with three.js and Manifold, and saves a .glb the page loads.
- model_look
- Shows that model from four sides against a grid, with each object's size and triangles.
- model_audit
- Checks .glb, .gltf and USD files: size, triangles, textures, compression;
shrinkmakes one smaller.
See
- open
- Runs the page in headless Chrome on a paused, seeded clock and lists what loaded and what failed.
- look
- A screenshot, every object on screen with its box, and what never appears and why.
- observe
- Reads the game state as JSON, with renderer counts and new console errors.
- eval
- Runs JavaScript in the page, with the scene, camera and mesh stats in scope.
Play and test
- interact
- Plays keys, mouse, touch and scroll on exact frames and reports what changed;
savekeeps the play as a check. - feel
- Measures whether a hit, pickup or win shows on screen: shake, pops, flashes, particles, sounds.
- test
- Reruns every saved check from a fresh reload, one pass or fail line each.
Measure
- perf
- Times the frame against a budget with what costs it;
optimize: truekeeps only the speed-ups that leave the picture the same.
Share
- publish
- Puts the game on https://<name>.paprika3d.app when you ask (preview, invite-only).
- send_feedback
- Sends the paprika3d team a bug or criticism, with the last tool call.
Built with paprika3d
Play them in your browser.
-
Rhythm game
Kaeru Flip
A toad skates down a road that is the note highway, charted live from your music.
- Controls
- A S D F G and Enter, or tap a lane
- Runs on
- Desktop, or a phone with its mic
- Renderer
- three.js, WebGL
-
Walk-through
Beach House
An unofficial walk-through of a film house.
- Controls
- WASD and mouse, or touch
- Runs on
- Desktop and phone
- Renderer
- three.js, WebGL
-
Horror game · daily run
Backrooms Tape 0
Find the exit before the entity finds you.
- Controls
- Keyboard and mouse
- Runs on
- Desktop Chrome or Edge
- Renderer
- three.js, WebGPU
-
Cozy game
Shepherd Isle
Pet the sheep, call the dog and light the lighthouse on a tiny island.
- Controls
- Click or tap
- Runs on
- Desktop and phone
- Renderer
- three.js, WebGL
-
Arcade game
Night Shift Toss
Toss paper balls into the bin in a mailroom at 3 a.m., and mind the fan.
- Controls
- Swipe or drag to throw
- Runs on
- Desktop and phone
- Renderer
- three.js, WebGL
-
Puzzle game
Liquid Pour
Pour coloured liquid between tubes until each holds one colour.
- Controls
- Click or tap a tube to pour
- Runs on
- Desktop and phone
- Renderer
- three.js, WebGL
-
Focus timer
Sōzu
A bamboo fountain fills as you work and knocks as the session passes.
- Controls
- Space to start, or click
- Runs on
- Desktop and phone
- Renderer
- three.js, WebGL
From the intro reel
Watch the 46-second reel ↗-
Bloom A flower burst over a harbour.
-
Skull A stone skull figure typing at a keyboard.
-
Paprika The PAPRIKA end card.
Results
paprika3d vs Playwright MCP and Blender MCP
| Feature | paprika3d | Playwright MCP | Blender MCP |
|---|---|---|---|
| Sees the scene: named objects, sizes, what never appears | Yes | No | No |
| Same inputs give the same frames (paused, seeded clock) | Yes | Not built in | No |
| Input on an exact frame, with the game state back | Yes | No | No |
| Frame time against a budget, plus an optimizer | Yes | No | No |
| Names lighting and z-fighting faults | Yes | No | No |
- Flickering faces found in 133 finished objects (Sonnet 5.5)
- 75% vs 44% paprika3d vs Playwright MCP with a QA skill and a measuring script.
- Clean objects correctly passed (Sonnet 5.5)
- 80% vs 66% Same 133 objects, paprika3d vs Playwright MCP.
3JSBench
3JSBench by General Context Labs checks the 3D objects a model builds from one-line requests. In our run of its checks, more objects pass with paprika3d:
- Sonnet 5.5: objects that pass every check
- 66% → 86% +20 points (95% interval +11 to +29), 150 runs per arm
- Opus 5.5: objects that pass every check
- 63% → 78% +15 points (95% interval +4 to +26), 150 runs per arm
- Sonnet 5.5: objects with no flickering faces
- 68% → 88% +20 points (95% interval +11 to +29), 150 runs per arm
- Opus 5.5: objects with no flickering faces
- 69% → 89% +21 points (95% interval +11 to +31), 150 runs per arm
More results
- Imported glTF model loaded and shown at the right size (Sonnet 5.5)
- 1 → 9 of 11 runs Without vs with paprika3d.
- Draco-compressed model loaded (Sonnet 5.5)
- 0 → 3 of 3 runs Without vs with paprika3d.
- Main-thread time per frame, ~2,000 physics crates (Opus 5.5)
- 7–11 → 1.3–2.0 ms With game-state, which runs physics in a worker. 18 of 18 game checks pass.
This page was built and checked with paprika3d
We tested it with paprika3d at desktop and phone sizes.
- Desktop frame
- 4.8 ms
- Phone frame (390 × 844, JS 4× slower)
- 7.5 ms
- Draw calls
- 79
- First scene frame, fast 4G
- 1.6 s
- Bytes to first frame
- 0.28 MB