Blender 3D Skill
Drive Blender programmatically through BlenderMCP — a socket bridge that lets an agent
run arbitrary bpy Python inside a live Blender, see the result, and iterate. This skill is
the distilled method for doing that well: how to connect, the working loop, the real command
surface, version-specific bpy facts, and per-domain technique references.
Mental model (read this first)
Claude does not model by clicking tools. It:
- Decomposes the target into an ordered build plan (blockout → parts → detail → material → light → render).
- Writes a
bpy script for one step and runs it via execute_code.
- Looks at the result with
get_viewport_screenshot, and introspects state with get_scene_info / get_object_info.
- Corrects and moves to the next step.
execute_code is the workhorse — roughly 90% of all work is Python you send through it. The
other commands exist so you can see and verify. Never assume a step worked; screenshot and
check, because errors compound when the next piece snaps or parents to a wrong origin.
When to use
- For an explainer-video shot, read references/explainer-video.md: editable scene, PNG sequence and a timed handoff to
codebase-video or ComfyUI.
- Create or edit 3D models, sculpts, or scenes programmatically
- Author PBR materials / shader node graphs
- Set up cameras, lights, and render a scene
- Batch-process or procedurally generate 3D assets
- Build modular asset libraries or environments
When NOT to use
- 2D image processing (resize, crop, filter, convert) → imagemagick skill
- AI image generation from a text prompt → comfyui skill
- Diagrams / flowcharts → mermaid-diagrams skill
- Video editing / transcoding / audio → ffmpeg-processing skill
- Geospatial 3D → qgis skill
Connecting (do this before any modelling)
BlenderMCP has two halves that must both be running:
- Blender side: the "Blender MCP" addon runs a raw TCP JSON server. Enable the addon, open
View3D > Sidebar (N) > BlenderMCP, and click Connect to MCP server. It listens on
localhost:9876 by default. This is per-session — a fresh Blender starts with the socket
closed even though the addon stays enabled.
- Agent side: an MCP server launched with
uvx blender-mcp, registered in your MCP client
(.mcp.json entry: {"command": "uvx", "args": ["blender-mcp"]}).
Verify the link before working — run the health check, which distinguishes the failure
modes that actually happen:
node tools/blender-health.js # PASS / FAIL [refused|silent-close|timeout|bad-json]
# env: BLENDER_HOST (default localhost), BLENDER_PORT (default 9876)
Full setup, the uvx registration, container-split topology, asset-integration toggles, and
troubleshooting: references/connection-and-protocol.md.
Deployment topology (agentbox)
There are two paths, because agentbox's main image is nix-built and nix binaries don't
search /usr/lib, where the nvidia-container-runtime injects the GPU driver libraries — so
in-container Blender is blind to the GPU for both CUDA and GL unless helped.
- Headless GPU batch (local, works now): run
tools/blender-batch.sh script.py (or
--render file.blend out.png). It prepends /usr/lib to LD_LIBRARY_PATH so Cycles finds
the injected libcuda and renders on the GPUs. No GL context / socket server needed. This is
the reliable path for "run a bpy script, render an image."
- Interactive BlenderMCP (GPU sidecar): the socket server needs a GUI GL context, which the
in-container VNC display can't provide. So Blender runs in the
gui-tools-service GPU
sidecar (Arch/FHS, VirtualGL → GPU EGL), and tools/blender-mcp-proxy.js bridges
localhost:9876 → gui-tools-service:9876. Bring the sidecar up with
./agentbox.sh gui-tools up. If it's down, the proxy accepts then closes with no reply —
the health check reports silent-close, not refused.
Run node tools/blender-health.js to confirm the interactive path is live before using it.
Native MCP tools are optional (on-demand). The supervised proxy already exposes the
socket on localhost:9876, so you can drive Blender through it directly (or via
tools/mcp-blender-client.js) without any MCP registration. When you want the BlenderMCP
tools to appear natively in the session, register them on demand with
tools/register-mcp.sh (adds uvx blender-mcp → localhost:9876 to the workspace
.mcp.json; idempotent; --remove to unregister). This keeps .mcp.json lean by default
and only loads the heavy sidecar-backed server when 3D work actually needs it.
The real command surface
Everything BlenderMCP exposes (anything else goes through execute_code):
| Command |
Purpose |
get_scene_info |
List objects, materials, scene state |
get_object_info(name) |
Mesh/transform detail for one object |
get_viewport_screenshot(max_size, filepath, format) |
See the current viewport |
execute_code(code) |
Run arbitrary bpy Python — the workhorse |
get_telemetry_consent |
Addon housekeeping |
Optional, only if the user enables the matching toggle in the addon panel:
- PolyHaven (free HDRIs/textures/models):
get_polyhaven_categories, search_polyhaven_assets, download_polyhaven_asset, set_texture
- Hyper3D Rodin (text/image→mesh):
create_rodin_job, poll_rodin_job_status, import_generated_asset
- Sketchfab:
search_sketchfab_models, get_sketchfab_model_preview, download_sketchfab_model
- Hunyuan3D:
create_hunyuan_job, poll_hunyuan_job_status, import_generated_asset_hunyuan
Technique references (route by task)
Each is a dense, practical reference for an agent mid-task — workflow phases, concrete bpy,
prompt strategy, and pitfalls.
| Task |
Reference |
| Connect, protocol, the loop, troubleshooting |
connection-and-protocol.md |
| Box/primitive modelling, decomposition, blockout |
modeling-foundations.md |
| Hard-surface, Boolean & non-destructive, vehicles/mechanical |
hard-surface-and-boolean.md |
| Digital sculpting, dyntopo/remesh/multires, organic & portraits |
sculpting-organic.md |
| Low-poly/stylized, modular asset libraries, environments |
stylized-and-environments.md |
| PBR materials & shader node graphs |
materials-and-pbr.md |
| Cameras, lighting (3-point/portrait/HDRI), rendering, basic rig/anim |
lighting-rendering-and-scene.md |
| Verified anatomy of 52 finished pro scenes (render/modifier/material/tri norms) |
reference-scenes.md |
Version facts (verified against the installed Blender 5.1.2)
The course material this skill distils was authored for Blender 4.x. On 5.x, three things drift
— a snippet copied from a 4.x tutorial will otherwise throw:
- Render engine enum is
('BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'CYCLES'). The 4.2–4.5 name
BLENDER_EEVEE_NEXT does not exist on 5.1.2; setting it raises TypeError. Use
scene.render.engine = "BLENDER_EEVEE".
Material.use_nodes / World.use_nodes are deprecated (removal expected in Blender 6.0).
New materials/worlds already have a node_tree. Guard rather than assert: if not mat.use_nodes: mat.use_nodes = True.
bpy.ops.render.render(write_still=True) needs a camera. Assert scene.camera is not None
first, or it raises RuntimeError: Cannot render, no camera.
Verified-working on 5.1.2: primitive_*_add, transform_apply, bmesh.from_edit_mesh,
modifiers BEVEL/SUBSURF/BOOLEAN/MIRROR/ARRAY/SOLIDIFY via obj.modifiers.new,
shade_smooth/shade_flat, Principled BSDF inputs Base Color/Metallic/Roughness,
ShaderNodeTexImage+ShaderNodeNormalMap, lights SUN/AREA/POINT/SPOT, camera + TRACK_TO
constraint, world ShaderNodeTexEnvironment, armature_add + keyframe_insert.
Tools
| File |
Purpose |
tools/blender-batch.sh |
Headless GPU batch runner — prepends /usr/lib so nix Blender finds the injected CUDA driver; run a bpy script or --render file.blend out.png on the GPUs |
tools/blender-health.js |
Health check — round-trips get_scene_info, diagnoses refused/silent-close/timeout/bad-json |
tools/mcp-blender-client.js |
Stdio↔TCP bridge; maps {tool, params} → BlenderMCP {type, params} on port 9876 |
tools/blender-mcp-proxy.js |
TCP proxy to the GPU sidecar (localhost:9876 → gui-tools-service:9876) |
Security
execute_code runs arbitrary Python inside Blender with full filesystem and process access
of the Blender process. Treat it as a trust boundary: only run scripts you constructed for the
task, never opaque code from an untrusted source, and be deliberate about scripts that read/write
files or reach the network. See the trust-boundary section in
connection-and-protocol.md.
Attribution
- BlenderMCP addon and MCP server: Siddharth Ahuja, MIT — github.com/ahujasid/blender-mcp.
Command names, parameters, and socket behaviour documented here are read from that source.
- Workflow techniques were distilled — in original form — from Blender-with-Claude-Code
courseware the operator licensed. The operator's private staged
.blend files, prompt
transcripts, and lesson material live outside this skill at
/home/devuser/workspace/blender-course-assets/ (not shipped with the skill). This skill
contains original method, not course text.
1---2name: blender3description: Meta-skill for driving Blender via BlenderMCP: 3D modelling (box, hard-surface, boolean), digital sculpting, PBR material authoring, lighting, rendering, and scene assembly. Claude writes and runs bpy Python (execute_code), screenshots the viewport, inspects, and corrects — with GPU renders via blender-batch and interactive sessions via the gui-tools GPU sidecar. Use this whenever a task involves Blender, a .blend file, 3D modelling/sculpting/texturing, a Cycles or EEVEE render, or generating and processing 3D assets — even when the user does not name Blender explicitly (e.g. 'model a low-poly house', 'sculpt a creature head', 'make a PBR metal material', 'render this scene on the GPU', 'build a modular sci-fi corridor kit'). Not for 2D image editing (use imagemagick), text-to-image generation (use comfyui), or GIS map rendering (use qgis).4---56# Blender 3D Skill78Drive Blender programmatically through **BlenderMCP** — a socket bridge that lets an agent9run arbitrary `bpy` Python inside a live Blender, see the result, and iterate. This skill is10the distilled method for doing that well: how to connect, the working loop, the real command11surface, version-specific `bpy` facts, and per-domain technique references.1213## Mental model (read this first)1415Claude does **not** model by clicking tools. It:16171. **Decomposes** the target into an ordered build plan (blockout → parts → detail → material → light → render).182. **Writes a `bpy` script** for one step and runs it via `execute_code`.193. **Looks** at the result with `get_viewport_screenshot`, and introspects state with `get_scene_info` / `get_object_info`.204. **Corrects** and moves to the next step.2122`execute_code` is the workhorse — roughly 90% of all work is Python you send through it. The23other commands exist so you can *see* and *verify*. Never assume a step worked; screenshot and24check, because errors compound when the next piece snaps or parents to a wrong origin.2526## When to use2728- For an explainer-video shot, read [references/explainer-video.md](references/explainer-video.md): editable scene, PNG sequence and a timed handoff to `codebase-video` or ComfyUI.29- Create or edit 3D models, sculpts, or scenes programmatically30- Author PBR materials / shader node graphs31- Set up cameras, lights, and render a scene32- Batch-process or procedurally generate 3D assets33- Build modular asset libraries or environments3435## When NOT to use3637- 2D image processing (resize, crop, filter, convert) → **imagemagick** skill38- AI image generation from a text prompt → **comfyui** skill39- Diagrams / flowcharts → **mermaid-diagrams** skill40- Video editing / transcoding / audio → **ffmpeg-processing** skill41- Geospatial 3D → **qgis** skill4243## Connecting (do this before any modelling)4445BlenderMCP has two halves that must both be running:4647- **Blender side**: the "Blender MCP" addon runs a raw TCP JSON server. Enable the addon, open48 `View3D > Sidebar (N) > BlenderMCP`, and click **Connect to MCP server**. It listens on49 `localhost:9876` by default. This is **per-session** — a fresh Blender starts with the socket50 closed even though the addon stays enabled.51- **Agent side**: an MCP server launched with `uvx blender-mcp`, registered in your MCP client52 (`.mcp.json` entry: `{"command": "uvx", "args": ["blender-mcp"]}`).5354**Verify the link before working** — run the health check, which distinguishes the failure55modes that actually happen:5657```bash58node tools/blender-health.js # PASS / FAIL [refused|silent-close|timeout|bad-json]59# env: BLENDER_HOST (default localhost), BLENDER_PORT (default 9876)60```6162Full setup, the `uvx` registration, container-split topology, asset-integration toggles, and63troubleshooting: **[references/connection-and-protocol.md](references/connection-and-protocol.md)**.6465### Deployment topology (agentbox)6667There are two paths, because agentbox's main image is **nix-built** and nix binaries don't68search `/usr/lib`, where the nvidia-container-runtime injects the GPU driver libraries — so69in-container Blender is blind to the GPU for both CUDA and GL unless helped.7071- **Headless GPU batch (local, works now):** run `tools/blender-batch.sh script.py` (or72 `--render file.blend out.png`). It prepends `/usr/lib` to `LD_LIBRARY_PATH` so Cycles finds73 the injected `libcuda` and renders on the GPUs. No GL context / socket server needed. This is74 the reliable path for "run a `bpy` script, render an image."75- **Interactive BlenderMCP (GPU sidecar):** the socket server needs a GUI GL context, which the76 in-container VNC display can't provide. So Blender runs in the **`gui-tools-service`** GPU77 sidecar (Arch/FHS, VirtualGL → GPU EGL), and `tools/blender-mcp-proxy.js` bridges78 `localhost:9876 → gui-tools-service:9876`. Bring the sidecar up with79 `./agentbox.sh gui-tools up`. If it's down, the proxy accepts then closes with no reply —80 the health check reports `silent-close`, not `refused`.8182Run `node tools/blender-health.js` to confirm the interactive path is live before using it.8384**Native MCP tools are optional (on-demand).** The supervised proxy already exposes the85socket on `localhost:9876`, so you can drive Blender through it directly (or via86`tools/mcp-blender-client.js`) without any MCP registration. When you want the BlenderMCP87tools to appear natively in the session, register them on demand with88`tools/register-mcp.sh` (adds `uvx blender-mcp → localhost:9876` to the workspace89`.mcp.json`; idempotent; `--remove` to unregister). This keeps `.mcp.json` lean by default90and only loads the heavy sidecar-backed server when 3D work actually needs it.9192## The real command surface9394Everything BlenderMCP exposes (anything else goes through `execute_code`):9596| Command | Purpose |97|---|---|98| `get_scene_info` | List objects, materials, scene state |99| `get_object_info(name)` | Mesh/transform detail for one object |100| `get_viewport_screenshot(max_size, filepath, format)` | See the current viewport |101| `execute_code(code)` | Run arbitrary `bpy` Python — **the workhorse** |102| `get_telemetry_consent` | Addon housekeeping |103104Optional, only if the user enables the matching toggle in the addon panel:105106- **PolyHaven** (free HDRIs/textures/models): `get_polyhaven_categories`, `search_polyhaven_assets`, `download_polyhaven_asset`, `set_texture`107- **Hyper3D Rodin** (text/image→mesh): `create_rodin_job`, `poll_rodin_job_status`, `import_generated_asset`108- **Sketchfab**: `search_sketchfab_models`, `get_sketchfab_model_preview`, `download_sketchfab_model`109- **Hunyuan3D**: `create_hunyuan_job`, `poll_hunyuan_job_status`, `import_generated_asset_hunyuan`110111## Technique references (route by task)112113Each is a dense, practical reference for an agent mid-task — workflow phases, concrete `bpy`,114prompt strategy, and pitfalls.115116| Task | Reference |117|---|---|118| Connect, protocol, the loop, troubleshooting | [connection-and-protocol.md](references/connection-and-protocol.md) |119| Box/primitive modelling, decomposition, blockout | [modeling-foundations.md](references/modeling-foundations.md) |120| Hard-surface, Boolean & non-destructive, vehicles/mechanical | [hard-surface-and-boolean.md](references/hard-surface-and-boolean.md) |121| Digital sculpting, dyntopo/remesh/multires, organic & portraits | [sculpting-organic.md](references/sculpting-organic.md) |122| Low-poly/stylized, modular asset libraries, environments | [stylized-and-environments.md](references/stylized-and-environments.md) |123| PBR materials & shader node graphs | [materials-and-pbr.md](references/materials-and-pbr.md) |124| Cameras, lighting (3-point/portrait/HDRI), rendering, basic rig/anim | [lighting-rendering-and-scene.md](references/lighting-rendering-and-scene.md) |125| Verified anatomy of 52 finished pro scenes (render/modifier/material/tri norms) | [reference-scenes.md](references/reference-scenes.md) |126127## Version facts (verified against the installed Blender 5.1.2)128129The course material this skill distils was authored for Blender 4.x. On 5.x, three things drift130— a snippet copied from a 4.x tutorial will otherwise throw:131132- **Render engine enum is `('BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'CYCLES')`.** The 4.2–4.5 name133 `BLENDER_EEVEE_NEXT` does **not** exist on 5.1.2; setting it raises `TypeError`. Use134 `scene.render.engine = "BLENDER_EEVEE"`.135- **`Material.use_nodes` / `World.use_nodes` are deprecated** (removal expected in Blender 6.0).136 New materials/worlds already have a `node_tree`. Guard rather than assert: `if not mat.use_nodes: mat.use_nodes = True`.137- **`bpy.ops.render.render(write_still=True)` needs a camera.** Assert `scene.camera is not None`138 first, or it raises `RuntimeError: Cannot render, no camera`.139140Verified-working on 5.1.2: `primitive_*_add`, `transform_apply`, `bmesh.from_edit_mesh`,141modifiers `BEVEL/SUBSURF/BOOLEAN/MIRROR/ARRAY/SOLIDIFY` via `obj.modifiers.new`,142`shade_smooth`/`shade_flat`, Principled BSDF inputs `Base Color`/`Metallic`/`Roughness`,143`ShaderNodeTexImage`+`ShaderNodeNormalMap`, lights `SUN/AREA/POINT/SPOT`, camera + `TRACK_TO`144constraint, world `ShaderNodeTexEnvironment`, `armature_add` + `keyframe_insert`.145146## Tools147148| File | Purpose |149|---|---|150| `tools/blender-batch.sh` | Headless GPU batch runner — prepends `/usr/lib` so nix Blender finds the injected CUDA driver; run a `bpy` script or `--render file.blend out.png` on the GPUs |151| `tools/blender-health.js` | Health check — round-trips `get_scene_info`, diagnoses refused/silent-close/timeout/bad-json |152| `tools/mcp-blender-client.js` | Stdio↔TCP bridge; maps `{tool, params}` → BlenderMCP `{type, params}` on port 9876 |153| `tools/blender-mcp-proxy.js` | TCP proxy to the GPU sidecar (`localhost:9876 → gui-tools-service:9876`) |154155## Security156157`execute_code` runs **arbitrary Python inside Blender** with full filesystem and process access158of the Blender process. Treat it as a trust boundary: only run scripts you constructed for the159task, never opaque code from an untrusted source, and be deliberate about scripts that read/write160files or reach the network. See the trust-boundary section in161[connection-and-protocol.md](references/connection-and-protocol.md).162163## Attribution164165- **BlenderMCP** addon and MCP server: Siddharth Ahuja, MIT — github.com/ahujasid/blender-mcp.166 Command names, parameters, and socket behaviour documented here are read from that source.167- Workflow techniques were distilled — in original form — from Blender-with-Claude-Code168 courseware the operator licensed. The operator's private staged `.blend` files, prompt169 transcripts, and lesson material live outside this skill at170 `/home/devuser/workspace/blender-course-assets/` (not shipped with the skill). This skill171 contains original method, not course text.