Blender MCP — driving Blender directly
The official Blender MCP server (blender.org extension, "Blender" in the MCP list) gives two ways into Blender. Pick the right one first — everything else follows from that choice.
1. Two modes — decide before anything else
| Live mode | CLI mode (*_for_cli) |
|
|---|---|---|
| Needs | Blender GUI running + MCP add-on server enabled (socket localhost:9876) |
Just a .blend file path + Blender installed |
| Tools | execute_blender_code, get_objects_summary, get_object_detail_summary, screenshots, render_viewport_to_path, jump_to_* |
execute_blender_code_for_cli, get_blendfile_summary_*_for_cli |
| Use for | Interactive work with the user watching, viewport checks, iterating on a scene they have open | Batch work, renders, analyzing files nobody has open, automation |
Detect, don't assume: try get_objects_summary (cheap, read-only). A connection error means no live Blender → either switch to _for_cli with the file path, or ask the user to open Blender and enable the add-on (Edit → Preferences → Add-ons → "MCP Server"). Don't retry the live tools in a loop.
CLI mode is safe with open files: the server detects when the GUI has the same file open with unsaved changes and works on a synced temp copy automatically. Still prefer live mode when the GUI is open — it's the same session the user sees.
If the MCP tools are deferred in your session, load them in ONE ToolSearch call (e.g. select:mcp__Blender__get_objects_summary,mcp__Blender__execute_blender_code,mcp__Blender__render_viewport_to_path,...), not one at a time.
2. Inspect before touching
Never assume object names, modes, or values — Blender state is whatever the user left it in.
- Live scene:
get_objects_summaryfirst, thenget_object_detail_summaryfor the objects you'll touch (transforms, modifiers, materials, vertex counts). - Cold .blend file: the
get_blendfile_summary_*family reads the file without opening it —datablocks(what's inside),usage_guess(what the file is for),missing_files(broken texture/asset links),path_info,linked_libraries. Rundatablocks+usage_guessbefore proposing anything about an unfamiliar file. - Respect existing naming. New objects/materials/collections follow the file's existing convention, not a generic one.
3. Executing bpy code
execute_blender_code(code) runs in the live instance; execute_blender_code_for_cli(blend_file, code) runs blender --background. Both return data only if you assign a JSON-serializable dict to a variable named result.
import bpy
obj = bpy.data.objects.get("Suzanne") # .get() — never KeyError on a guess
result = {"found": obj is not None, "loc": list(obj.location) if obj else None}
Rules that prevent 90% of silent failures:
- Operators vs data API:
bpy.opsfor standard actions (add primitive, apply modifier, set origin — it handles context/defaults);bpy.datafor precise edits without side effects. - Mode matters: many operators fail or silently no-op in the wrong mode. Check/set
bpy.context.object.modeexplicitly (bpy.ops.object.mode_set(mode='OBJECT')) before operator calls. - Active ≠ selected. Many ops need both. Set both explicitly between sequential ops — operators mutate selection as a side effect:
bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj - Depsgraph: after changes,
bpy.context.view_layer.update()before reading computed values (world matrices, modifier results). - Edit-mode geometry goes through bmesh, not
obj.data.vertices; flush withbmesh.update_edit_mesh(mesh). - Chunk long scripts into a few logical
execute_blender_codecalls, not one giant blob — a failure mid-blob leaves the scene half-mutated with no clue where. - Paths inside code strings: forward slashes or raw strings (
r"C:\..."on Windows). Non-ASCII folder names are fine — bpy handles UTF-8 paths.
4. Verify visually — every meaningful change
Never claim a scene change worked without looking at it:
- Live:
get_screenshot_of_window_as_image(whole UI) orget_screenshot_of_area_as_image(one editor, e.g. the 3D viewport — sharper for judging the scene).jump_to_view3d_object_by_nameframes an object first. - Real pixels:
render_viewport_to_path(fast OpenGL preview) orrender_thumbnail_to_path; full renders via code (bpy.ops.render.render(write_still=True)withscene.render.filepathset). Save to a temp/scratch dir, then read the image back. - Screenshot/viewport-render before and after destructive edits — the before image is the rollback reference.
5. Docs — the API changes between versions; check, don't recall
Memorized bpy signatures are often stale for the installed version. When an operator errors or a property is missing:
search_api_docs/get_python_api_docs— bpy reference matching the running version.search_manual_docs— concepts and workflow (modifiers, geometry nodes, render settings).- Cheaper for many lookups: the server bundles the same docs as plain RST files you can grep directly, under the extension's install dir at
blmcp/data/api/andblmcp/data/manual/(on Windows desktop-app installs:%APPDATA%\Claude\Claude Extensions\ant.dir.gh.blender.blender-mcp\blmcp\data\).
6. Safety with the user's files
- Backup before big edits:
bpy.ops.wm.save_as_mainfile(filepath=..., copy=True)to abackups/sibling or a temp dir — then edit. Cheap insurance, always worth it. - Destructive changes (deleting objects, applying modifiers, overwriting saves) on a file you didn't create this session → confirm with the user first.
- Don't save over the open file unless asked; the user may have undo history they care about.
_for_cliruns are non-interactive: never include modal operators (render preview windows, file browsers) in CLI code.
7. Hand-offs
- Export to web / glTF / draco-meshopt optimization is a separate concern — do the scene work here, then switch to your web-export workflow or skill (if one is installed) for the export step.
- Downstream consumption (Three.js, R3F, Babylon) belongs to the web side; this skill ends at a clean, verified Blender scene or rendered output.