Atlas / Skills / thrixel / build-world

build-worldCAUTION

skills/thrixel/build-world

Build interactive 3D worlds with high-quality assets from Thrixel and your AI agent of choice.

Verdict
CAUTION
Grade
B
Trust score
88 /100
Version
—
Hosts
4 documented
License
Apache-2.0
Stars
103
01

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

  1. Unreal Editor with the ModelContextProtocol and AllToolsets plugins enabled (AllToolsets provides the tools; the server exposes none without it)
  2. Editor running to execute tools, with the MCP server started. Run ModelContextProtocol.StartServer, or enable bAutoStartServer through setup.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

  1. Launch Unreal Editor, then run ModelContextProtocol.StartServer in the console to start the MCP server.
  2. Check the Output Log for MCP server startup messages.
  3. 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.json file. Run ModelContextProtocol.GenerateClientConfig ClaudeCode (or your coding agent of choice; see setup.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

Read from source at commit dc571e574127OBSERVED · 2026-10-13
02

Install

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
03

Host compatibility

What the documentation claims. We have not run a compatibility test.

HostStatusNotes
claude-codementioned
claude-desktopmentioned
codexmentioned
cursormentioned
04

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> 
05

Trust audit

CAUTIONgrade B · trust 88/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (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)

MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
SKILL.md:1060
> It's running: http://127.0.0.1:5590/ - on your phone, same Wi-Fi: http://192.168.1.20:5590/.
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
engines/threejs/tools/lib/harness.mjs:154
return `http://127.0.0.1:${port}/?${p.toString()}${extra}`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
engines/threejs/tools/mobilecheck.mjs:93
await H.open(page, `http://127.0.0.1:${PORT}/`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
engines/threejs/tools/profile.mjs:58
await H.open(page, `http://127.0.0.1:${PORT}/${args.query ? `?${args.query}` : ''}`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
engines/threejs/tools/smoke.mjs:57
await H.open(page, `http://127.0.0.1:${PORT}/`);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
engines/threejs/example/systems/fx.js:2
import { InstanceRing, ParticleStore, LightPool, Owned, compileMeshes } from '../../lib/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
engines/threejs/example/systems/player.js:2
import { scratch } from '../../lib/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
engines/threejs/example/systems/render.js:2
import { compileMeshes, Owned } from '../../lib/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
engines/threejs/example/systems/ui.js:15
import { TouchControls } from '../../lib/index.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
engines/threejs/example/systems/world.js:2
import { LightBallast, Owned, disposeTree, compileMeshes } from '../../lib/index.js';
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
engines/unreal/tools/uemcp.py:157
f.write(base64.b64decode(o["data"]))
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
engines/unreal/tools/uemcp.py:170
f.write(base64.b64decode(block["data"]))
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
engines/threejs/package.json
three, playwright, pngjs, vite
Why it matters. 4 dependency range(s) float
Fix. pin exact versions or ship a lockfile
INFOPrompt injection · prompt.authority_framing · CWE-94, CWE-1427
engines/unreal/EpicGames-UnrealMCP-skills/README.md:52
**`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
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
engines/roblox/roblox.md:15
1) You MUST have Rojo, the Roblox Studio MCP server, AND an Open Cloud API key working. If
Why it matters. asks the agent to read credentials
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
engines/roblox/setup.md:6
- **An Open Cloud API key** — the only scriptable way to get a mesh into Roblox. Rojo
Why it matters. asks the agent to read credentials
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
engines/roblox/setup.md:92
## 3. Open Cloud API key
Why it matters. asks the agent to read credentials
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
SetupAndInstallationFlow.md:158
curl -LsSf https://astral.sh/uv/install.sh | sh          # macOS / Linux
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
engines/roblox/setup.md:28
curl -sSf https://raw.githubusercontent.com/rojo-rbx/rokit/main/scripts/install.sh | bash
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
engines/threejs/setup.md:8
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh | bash
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
engines/threejs/setup.md:18
curl -o- https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | bash

Gates applied: no_behavioural_pass.

Audited 2026-10-13 · audit v0.4.1 · source sha dc571e574127full audit observations/trust-audit/skill/thrixel__build-world.json · Report an issue / request a re-scan
06

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-13dc571e574127CAUTIONB88first audit
07

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.

Advertisement