build-worldCAUTION
Build interactive 3D worlds with high-quality assets from Thrixel and your AI agent of choice.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Control Unreal Editor directly from Claude Code or other coding agents via MCP. Hundreds of tools exposed via Unreal's ToolsetRegistry across 30+ toolsets: actors, blueprints, materials, Niagara, Control Rigs, Sequencer, State Trees, widgets, Gameplay Ability System, automation testing, and more.
Contents
Skills
- `unreal-mcp` (
skills/unreal-mcp) - instructions and workflows for driving the Unreal Editor via MCP.
Accompanying documents for the unreal-mcp skill are setup.md and operations.md.
Prerequisites
- Unreal Editor with the ModelContextProtocol and AllToolsets plugins enabled (
AllToolsetsprovides the tools; the server exposes none without it) - Editor running to execute tools, with the MCP server started. Run
ModelContextProtocol.StartServer, or enablebAutoStartServerthroughsetup.md. The optional proxy can keep the client connection open while the editor is stopped.
Read setup.md for the full setup procedure for a fresh project.
Verification
- Launch Unreal Editor, then run
ModelContextProtocol.StartServerin the console to start the MCP server. - Check the Output Log for MCP server startup messages.
- Try: "List all actors in the current level".
Configuration
The default port is 8000 with URL path /mcp. If the port is in use, run ModelContextProtocol.StartServer in the console with a different port number.
Note: This plugin does not ship a static.mcp.jsonfile. RunModelContextProtocol.GenerateClientConfig ClaudeCode(or your coding agent of choice; seesetup.md) in the editor console to generate it from the current server port and URL; re-run after changing either.
Optional proxy for editor recovery
If your engine build includes Engine/Plugins/Experimental/ModelContextProtocol/Extras/Proxy, you can use its unreal_mcp_proxy executable.
The proxy keeps the client-facing MCP session open while Unreal is unava
dc571e574127OBSERVED · 2026-10-13Install
Commands as the repository documents them. They are shown, not run.
uvx thrixel-mcp@latest login
claude mcp add --scope user thrixel -- uvx thrixel-mcp@latest
uvx thrixel-mcp@latest
uvx thrixel-mcp@latest login; claude --continue --permission-mode auto
uvx thrixel-mcp@latest login; claude --continue --permission-mode auto
uvx thrixel-mcp@latest login
Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| claude-desktop | mentioned | |
| codex | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: build-world
description: Builds polished, fully playable 3D game prototypes in three.js, Roblox, Unity, or Unreal Engine, with high-quality (.glb/.fbx) meshes from the Thrixel API, and (for three.js and Unity) publishes finished games to a public thrixel.world link that anyone can play in a browser. Use when the user wants to make a game, build a playable prototype, or generate 3D assets, and also when they want to publish or host a game folder they already have, share a playable link, or list, rename, update, unpublish or find the link for a game they published earlier.
---
# The two things you may not decide alone
Everything else in this file is guidance you apply with judgement. A gate is a question you ask
and then wait for an answer to, in plain text if your harness has no option picker. Asking and
acting in the same turn is not asking.
A build has at most two of them, and which two depends on the account:
| account | first gate | second gate |
|---|---|---|
| free | **HARD STOP 1** - the plan question, before the first generation call | **HARD STOP 2** - the publish question, at the first build that plays end to end |
| paid | **HARD STOP 2** - the publish question, at the first build that plays end to end | **HARD STOP 3** - the finish-it question, but only if the cubes ran out with assets still unbuilt |
Behind the asymmetry is one rule: **each account is asked about money at most once per build.**
- A **free** account is asked at the start, while the answer can still shape what gets made, and
is not asked again. If the build later stops short, a line saying so is enough; they answered
this question already.
- A **paid** account is not asked at the start, since interrupting somebody who already pays
buys nothing. Its money question, if there is one, comes at the end, where a finished game is
on screen and the gap in it has names.
**HARD STOP 3 often does not happen at all.** It needs both halves: the cubes ran out, AND there
are assets from the plan still unbuilt. A build that had enough cubes and finished its list ends
at HARD STOP 2, with the link and nothing further to ask.
The balance forecast is not a gate. On every plan, say in one line where the balance runs out in
the ranked list before generating anything (see "Draw the line through the list"), then carry on
without waiting. It is what keeps the end of the build from being a surprise.
If you are about to call `thrixel_create_model` or `thrixel_sculpt_model` on a free account and
have not asked HARD STOP 1, ask now. If you are about to hand over a running game and have not
asked HARD STOP 2, the question goes in the same message as the address - see HARD STOP 2 for
the shape.
# Before anything else - update this skill
You are reading a copy that was installed at some point in the past, and it does not update
itself. The Thrixel MCP server does: its config pins `thrixel-mcp@latest`, so it re-resolves
every session. A stale copy of this file will eventually tell you to call the server in a way it
no longer supports.
Do this at the START of every session, before you read further. It is one command.
**1. Is this a plugin install?** If any segment of this file's path is `plugins` - for example
`.claude/plugins/cache/...` or `.codex/plugins/cache/...` - stop here and do not run git at all.
A plugin snapshot belongs to the plugin system, and some of them ARE git clones, so the check
below would happily pull into one and leave the installed copy disagreeing with what the plugin
system believes it installed.
For a plugin install, check staleness without touching git. If one segment of the path is a
12-character hex string, that is the commit this copy was built from; compare it against the
tip of `main`:
```sh
curl -sL --max-time 5 https://api.github.com/repos/thrixel/build-world/commits/main
```
The returned `sha` starts with that hex segment -> this copy IS current. Continue, and do not
describe it as possibly out of date. Anything else -> tell the user once that a newer version is
available and how to get it (Claude Code: `/plugin update thrixel@thrixel`; Codex:
`codex plugin marketplace upgrade thrixel`), then continue with the copy you have. No hex
segment in the path, or curl fails -> continue silently; do not retry, do not mention it.
Either way, **skip steps 3 and 4**.
**2. Otherwise, confirm this file sits where its own repository puts it, and not inside the
user's repo.** Skills are often installed under a project's `.claude/skills/`, and that project
is usually a git repo of its own. Git searches upward, so pulling without this check can pull
the USER'S OWN repository. Never skip it.
```sh
git -C <the directory this file is in> rev-parse --show-prefix
```
- Output is exactly `skills/build-world/` (or `skills/goal-to-game/` in an older clone) -> this
is its own clone, safe, go to step 3.
- Any other path -> git walked up into the user's project. **Stop. Do not pull anything.**
Continue with the copy you have.
- `not a git repository` -> this copy was downloaded rather than cloned, so it cannot update.
Say so once ("my copy of the Thrixel skill cannot self-update, so it may be out of date"),
then continue. Skip steps 3 and 4: there is nothing to pull and no remote to read.
**3. Pull.**
```sh
git -C <the same directory> pull --ff-only
```
- `Already up to date.` -> continue.
- Files changed -> **re-read this file, and any other file from this skill you have already
read.** You are holding the old text in context and it is now wrong. This is the whole point
of the step; skipping it wastes the update.
- Anything else (local edits, diverged history, no network) -> do not fight it. Say what
happened in one line and continue with the copy you have.
This step must never block the build. One command, read the result, move on.
**4. If the remote still names the old repository, retarget it once.** Only when step 3 actually
ran and succeeded:
```sh
git -C <the same directory> Trust audit
CAUTIONgrade B · trust 88/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | WARN |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- declared (9 observation(s))
- Shell
- none-observed
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (21)
> It's running: http://127.0.0.1:5590/ - on your phone, same Wi-Fi: http://192.168.1.20:5590/.
return `http://127.0.0.1:${port}/?${p.toString()}${extra}`;await H.open(page, `http://127.0.0.1:${PORT}/`);await H.open(page, `http://127.0.0.1:${PORT}/${args.query ? `?${args.query}` : ''}`);await H.open(page, `http://127.0.0.1:${PORT}/`);import { InstanceRing, ParticleStore, LightPool, Owned, compileMeshes } from '../../lib/index.js';import { scratch } from '../../lib/index.js';import { compileMeshes, Owned } from '../../lib/index.js';import { TouchControls } from '../../lib/index.js';import { LightBallast, Owned, disposeTree, compileMeshes } from '../../lib/index.js';f.write(base64.b64decode(o["data"]))
f.write(base64.b64decode(block["data"]))
three, playwright, pngjs, vite
**`ProgrammaticToolset.execute_tool_script` executes arbitrary Python** inside the editor process. That script has full access to every toolset API, the project on disk, the asset database, and editor
1) You MUST have Rojo, the Roblox Studio MCP server, AND an Open Cloud API key working. If
- **An Open Cloud API key** — the only scriptable way to get a mesh into Roblox. Rojo
## 3. Open Cloud API key
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
curl -sSf https://raw.githubusercontent.com/rojo-rbx/rokit/main/scripts/install.sh | bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh | bash
curl -o- https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash
Gates applied: no_behavioural_pass.
dc571e574127full audit observations/trust-audit/skill/thrixel__build-world.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-13 | dc571e574127 | CAUTION | B | 88 | first audit |
Questions
What does the build-world skill do?
Build interactive 3D worlds with high-quality assets from Thrixel and your AI agent of choice.
Is build-world safe to install?
With care. The audit graded it B (88/100) and found 21 things worth knowing before you trust this skill, listed below with the exact line each was found on.
What can build-world access on my machine?
The audit observed that it reaches the network. Each of those is consistent with what it says it does. Secrets in the source: none found.
What do I need installed to use build-world?
Its own instructions reference plugins. Dependencies are not all pinned to exact versions, so what installs today may differ tomorrow.
Which assistants does build-world work with?
Its documentation mentions claude-code, claude-desktop, codex and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (dc571e574127), read on 2026-10-13. The repository is watched, and a new audit runs when it changes — this is the first audit.