AI-powered Blender control via Claude Code using the Model Context Protocol (MCP).
Control Blender through natural language, execute Python scripts, generate 3D content with local AI models, and render scenes - all from Claude Code.
Rendered end-to-end by Claude through the MCP tools — see examples/.
- Natural Language Control: Control Blender via Claude Code commands
- MCP Integration: Built on MCP SDK v2 (protocol 2026-07-28) — 28 tools, 3 resources, and workflow prompts, with tool annotations and structured output
- Visual Feedback Loop: Screenshots and renders come back inline so Claude can see, critique, and iterate on its own work
- Import / Export: OBJ, STL, PLY, FBX, glTF/GLB, USD, Collada, Alembic
- Animation Rendering: MP4 turntables and image sequences with inline preview stills
- Camera Framing: One call positions and aims a camera to frame any object
- Undo Checkpoints: Checkpoint before risky edits, roll back when they go wrong
- JSON-RPC API: Direct programmatic access to Blender over TCP
- Scene Introspection: Get detailed scene information in multiple formats
- Text-to-3D: Generate 3D models using Shap-E (OpenAI) - runs locally
- Image-to-3D: Convert images to 3D with TripoSR (Stability AI) - runs locally
- Procedural Generation: Create rocks, trees, terrain, buildings algorithmically
- ComfyUI Bridge: Connect to local ComfyUI for Stable Diffusion workflows
- Depth-to-Mesh: Convert depth maps to 3D meshes
Claude Code CLI
"Create a low-poly dragon"
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ MCP SERVER (Python) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Scene Tools │ │ AI Tools │ │ Render Tools │ │
│ │ - execute │ │ - text_to_3d│ │ - render │ │
│ │ - get_scene │ │ - img_to_3d │ │ - screenshot │ │
│ │ - add_object│ │ - procedural│ │ - export │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
JSON-RPC over TCP (localhost:9876)
▼
┌─────────────────────────────────────────────────────────────────┐
│ BLENDER ADDON (Python) │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌───────────┐ │
│ │ Server │ │ Executor │ │ AI Router │ │ Scene │ │
│ │(Timer-poll)│ │(Main thrd) │ │ (Dispatch) │ │ Utils │ │
│ └────────────┘ └────────────┘ └────────────┘ └───────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ LOCAL AI SERVICES │ │
│ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌───────────────┐ │ │
│ │ │ Shap-E │ │ TripoSR │ │Depth2Mesh│ │ ComfyUI │ │ │
│ │ │ (Local) │ │ (Local) │ │ (Local) │ │ Bridge │ │ │
│ │ └─────────┘ └──────────┘ └─────────┘ └───────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- Blender 4.0+ (tested on 4.3)
- uv (manages Python 3.10+ and dependencies)
Option A: Symlink (recommended when working from a clone — picks up edits)
# macOS (replace <version> with your Blender version, e.g. 4.3)
ln -s /path/to/claude-blender/claude_blender/blender_addon \
~/Library/Application\ Support/Blender/<version>/scripts/addons/claude_blender
# Linux
ln -s /path/to/claude-blender/claude_blender/blender_addon \
~/.config/blender/<version>/scripts/addons/claude_blenderThe link must be named claude_blender — that name becomes the addon's
Python module name, which the headless script and the AI tools rely on.
Then enable "Claude Blender" in Edit > Preferences > Add-ons.
You can also ask claude/codex to configure this.
Option B: Install from zip
Blender's installer accepts only .py/.zip files (not folders), so build
the zip first:
./scripts/build_addon.shThen Edit > Preferences > Add-ons > ∨ (dropdown) > Install from Disk...
and select claude_blender.zip. The script pins the in-zip folder name to
claude_blender for the same module-name reason as above.
The addon auto-starts its server on launch (toggle in the addon preferences; the toggle takes effect immediately).
This is a uv project (root pyproject.toml + uv.lock, built on mcp>=2.0.0, MCP protocol revision 2026-07-28). From the repo root:
uv syncThat creates .venv/ and installs the pinned dependencies. Local AI features (Shap-E, TripoSR, etc.) have their own optional dependencies — see Local AI Services below.
This repository ships a project-scoped .mcp.json at the repo root; opening the repo in Claude Code will prompt you to enable the blender server. It launches the server with uv run claude-blender, so it works as soon as uv sync has been run (uv also re-syncs automatically on launch).
To register it user-wide instead (available in every project):
claude mcp add --scope user blender \
--env BLENDER_HOST=127.0.0.1 --env BLENDER_PORT=9876 \
-- uv run --project /path/to/claude-blender claude-blenderWith auto-start enabled (the default), just open Blender. Otherwise:
- Press N to show the sidebar
- Go to the Claude tab
- Click Start Server
The panel reads the real server state (it survives File > New/Open), and a failed start reports the reason — e.g. which process holds the port.
Simply ask Claude to interact with Blender:
"Add a red cube at position (0, 0, 2)"
"Create a simple scene with a sphere and a light"
"Render the current scene and show me the result"
"Generate a procedural rock using local AI"
import socket
import json
# Connect
sock = socket.socket()
sock.connect(('127.0.0.1', 9876))
# Send request
request = {
"jsonrpc": "2.0",
"id": 1,
"method": "add_object",
"params": {
"object_type": "cube",
"location": [0, 0, 2],
"scale": [0.5, 0.5, 0.5]
}
}
sock.send(json.dumps(request).encode() + b'\n')
# Get response
response = json.loads(sock.recv(4096).decode())
print(response)Run a background Blender that serves the addon — renders, imports/exports, and all object tools work; only viewport screenshots and undo need the GUI:
blender --background --python scripts/headless_blender.py -- --port 9876
# macOS: the default install doesn't put blender on PATH
/Applications/Blender.app/Contents/MacOS/Blender --background \
--python scripts/headless_blender.py -- --port 9876uv run pytest -m "not live" # full suite against a fake Blender server
BLENDER_LIVE=1 uv run pytest -m live # against a real Blender on port 9876The fake server compiles every generated execute payload, so quoting or
injection regressions fail in CI without needing Blender.
# Run all tests (talks JSON-RPC directly to the addon)
uv run python claude_blender/test_client.py
# Interactive mode
uv run python claude_blender/test_client.py -i| Tool | Description |
|---|---|
blender_ping |
Health check |
blender_version |
Get Blender and addon versions |
blender_get_scene |
Get scene info (minimal/basic/detailed/full) |
blender_get_object |
Get detailed object information |
| Tool | Description |
|---|---|
blender_add_object |
Add primitive (cube, sphere, lights with energy/color/size, etc.) |
blender_modify_object |
Transform object, visibility, smooth/flat shading |
blender_delete_object |
Delete object by name |
| Tool | Description |
|---|---|
blender_execute |
Execute arbitrary Python code in Blender |
| Tool | Description |
|---|---|
blender_screenshot |
Capture viewport — returns the image inline so Claude can see it |
blender_render |
Render scene — defaults are a fast draft; renders never leak settings into the scene |
blender_render_animation |
Render MP4 video or PNG sequence — returns preview stills inline |
blender_save |
Save the .blend file (in place or as a copy) |
| Tool | Description |
|---|---|
blender_frame_camera |
Position and aim a camera to frame objects (fit math included) |
| Tool | Description |
|---|---|
blender_import_model |
Import OBJ, STL, PLY, FBX, glTF/GLB, USD, DAE, ABC |
blender_export |
Export scene or selected objects to any of the above |
| Tool | Description |
|---|---|
blender_modifier |
Add, apply, or remove modifiers (SUBSURF, BOOLEAN, ARRAY, ...) |
blender_duplicate |
Duplicate N times with cumulative offset (one-call arrays) |
blender_organize |
Parent/unparent objects, move to collections |
| Tool | Description |
|---|---|
blender_checkpoint |
Push an undo checkpoint before risky edits |
blender_undo |
Undo/redo N steps |
| Tool | Description |
|---|---|
blender_create_material |
Create and assign materials |
blender_set_keyframe |
Set animation keyframes (with easing, e.g. LINEAR for loops) |
blender_set_frame_range |
Set animation frame range |
| Tool | Description |
|---|---|
ai_generate_procedural |
Generate rocks, trees, terrain, buildings |
ai_local_text_to_3d |
Text-to-3D with Shap-E (local) |
ai_local_image_to_3d |
Image-to-3D with TripoSR (local) |
ai_comfyui_generate |
Generate images via local ComfyUI |
ai_check_local_services |
Check which AI services are available |
| Item | Description |
|---|---|
blender://scene (resource) |
Live JSON snapshot of the scene graph |
blender://object/{name} (resource) |
Full details of one object (transform, mesh stats, modifiers) |
blender://render/latest (resource) |
The most recent render/screenshot as PNG |
studio_lighting (prompt) |
Guided three-point lighting workflow |
turntable_animation (prompt) |
Guided 360° turntable animation workflow |
Working inside this repo, three slash commands encode complete workflows (each is a walkthrough in examples/):
/blender-iterate <visual goal> # render–critique–adjust loop
/blender-studio-shot <object> # lighting + framing + final render
/blender-turntable <object> [secs] # 360° turntable video
Requires:
pip install torch diffusers transformers trimeshRequires:
pip install torch transformers trimesh rembgRequires ComfyUI running locally on http://127.0.0.1:8188
No additional dependencies - uses Blender's built-in modifiers.
claude-blender/
├── claude_blender/
│ ├── blender_addon/
│ │ ├── __init__.py # Addon entry point (bl_info, RPC registry)
│ │ ├── core/
│ │ │ ├── server.py # Timer-polled TCP server
│ │ │ ├── protocol.py # JSON-RPC 2.0 handler
│ │ │ ├── executor.py # Objects, modifiers, duplicate, undo
│ │ │ ├── scene_utils.py # Introspection, render, render_animation
│ │ │ ├── io_utils.py # Import/export (format from extension)
│ │ │ └── camera_utils.py # frame_camera fit math (headless-safe)
│ │ └── ai_services/
│ │ ├── base.py # Base service classes
│ │ ├── local_text_to_3d.py # Shap-E, Point-E, Procedural
│ │ ├── local_image_to_3d.py # TripoSR, Depth2Mesh
│ │ └── comfyui_bridge.py # ComfyUI integration
│ │
│ ├── claude_blender_mcp/
│ │ ├── __init__.py # MCP entry point
│ │ ├── server.py # MCPServer (MCP SDK v2): 27 tools, resources, prompts
│ │ └── blender_client.py # Async Blender client
│ │
│ ├── test_client.py # Raw JSON-RPC test script
│ └── demo_creative.py # Creative demo script
│
├── tests/ # pytest suite (fake Blender, fake bpy, live markers)
├── scripts/
│ ├── headless_blender.py # Serve the addon from blender --background
│ └── build_addon.sh # Build claude_blender.zip for Install from Disk
├── examples/ # Walkthroughs with real committed renders
├── .claude/skills/ # /blender-iterate, /blender-studio-shot, /blender-turntable
├── .github/workflows/ci.yml # uv + pytest on 3.11/3.13
├── CLAUDE.md # Architecture & invariants for agents/devs
├── pyproject.toml # uv project / package configuration
├── uv.lock # Locked dependencies (managed by uv)
├── .mcp.json # Project-scoped Claude Code MCP config
├── LICENSE # MIT License
└── README.md # This file
Blender's Python API is NOT thread-safe. Using threading.Thread will crash Blender. The timer system (bpy.app.timers) runs callbacks in the main thread, ensuring safe API access.
- Standard protocol with good tooling
- Bidirectional communication
- Built-in error handling
- Easy to debug and test
- MCP runs outside Blender process
- Can restart without affecting Blender
- Clean separation of concerns
- Easier testing
MIT License - see LICENSE for details.
Contributions are welcome! Please feel free to submit issues and pull requests.
