Blender AI MCP
Modular MCP Server + Blender Addon for AI-Driven 3D Modeling.
blender-ai-mcp
π‘ Support the Project
This project is currently developed after hours as a passion project. Creating a stable bridge between AI and Blender's complex API requires significant time and effort.
If you find this tool useful or want to accelerate the development of advanced features (like Edit Mode tools, Auto-Rigging, or Macro Generators), please consider supporting the project. Your sponsorship allows me to dedicate more time to:
- Implementing critical Mesh Editing Tools (Extrude, Bevel, Loop Cut).
- Creating high-level Macro Tools (e.g., "Create Human Blockout", "Organify").
- Ensuring day-one support for new Blender versions.
Modular MCP Server + Blender Addon for AI-Driven 3D Modeling.
Enable LLMs (Claude, ChatGPT) to control Blender reliably. Built with Clean Architecture for stability and scalability.
π Why use this MCP Server instead of raw Python code?
Most AI solutions for Blender rely on asking the LLM to "write a Python script". This often fails because:
- Hallucinations: AI frequently uses outdated
bpyAPI methods (mixing Blender 2.8 with 5.0). - Context Errors: Running operators requires specific context (active window, selected object, correct mode). Raw scripts often crash Blender due to
poll()failures. - No Feedback Loop: If a script fails, the AI doesn't know why. Our MCP server returns precise error messages.
- Safety: Executing arbitrary Python code is risky. Our tools are sandboxed endpoints with validated inputs.
Blender AI MCP acts as a stable Translation Layer, handling the complexity of Blender's internal state machine so the AI can focus on creativity.
ποΈ Architecture
This project uses a split-architecture design:
- MCP Server (Python/FastMCP): Handles AI communication.
- Blender Addon (Python/bpy): Executes 3D operations.
Communication happens via JSON-RPC over TCP sockets.
See ARCHITECTURE.md for deep dive.
β Support Matrix
- Blender: tested on Blender 5.0 (E2E). The addon declares minimum Blender 4.0, but 4.x support is best-effort.
- Python (MCP server): 3.11 is the CI baseline. 3.10+ works for core tools, but Router semantic features (LaBSE/LanceDB) require 3.11+.
- OS: macOS / Windows / Linux (Docker recommended). On Linux, use host networking or proper host resolution for
BLENDER_RPC_HOST. - Memory: Router semantic matching uses a local LaBSE model (~2GB RAM).
π§ͺ Testing
Unit Tests (no Blender required):
PYTHONPATH=. poetry run pytest tests/unit/ -v
To see the current unit test count:
poetry run pytest tests/unit --collect-only
E2E Tests (requires Blender):
# Automated: build β install addon β start Blender β run tests β cleanup
python3 scripts/run_e2e_tests.py
To see the current E2E test count:
poetry run pytest tests/e2e --collect-only
| Type | Coverage |
|---|---|
| Unit Tests | All tool handlers |
| E2E Tests | Blender addon integration (Scene, Mesh, Material, UV, Export, Import, Baking, System, Sculpt, Router) |
See _docs/_TESTS/README.md for detailed testing documentation.
============================= test session starts ==============================
platform darwin -- Python 3.13.9, pytest-9.0.1, Blender 5.0
collected 142 items
tests/e2e/tools/baking/test_baking_tools.py βββββββ
tests/e2e/tools/collection/test_collection_tools.py ββββββββββ
tests/e2e/tools/export/test_export_tools.py βββββββββββββ
tests/e2e/tools/import_tool/test_import_tools.py βββββββββ
tests/e2e/tools/knife_cut/test_knife_cut_tools.py βββββββββ
tests/e2e/tools/material/test_material_tools.py ββββββββββββββ
tests/e2e/tools/mesh/test_mesh_cleanup.py βββββββββββββββββ
tests/e2e/tools/mesh/test_mesh_edge_weights.py ββββββββββββββββ
tests/e2e/tools/scene/test_*.py βββββββ
tests/e2e/tools/sculpt/test_sculpt_tools.py βββββββββββββ
tests/e2e/tools/system/test_system_tools.py ββββββββββββ
tests/e2e/tools/uv/test_uv_tools.py ββββββββββββ
============================= 142 passed in 12.25s =============================
πΊοΈ Roadmap & Capabilities
Legend: β Done | π§ To Do
Our goal is to enable AI to model complex 3D assetsβfrom organs and biological structures to hard-surface precision parts (cars, devices).
Scene Tools (scene_*)
Object Mode operations for scene management and inspection.
| Tool | Description | Status |
|---|---|---|
scene_list_objects | List all objects in scene | β |
scene_delete_object | Delete object by name | β |
scene_clean_scene | Remove all objects | β |
scene_duplicate_object | Duplicate object | β |
scene_set_active_object | Set active object | β |
scene_get_viewport | Capture viewport image (AI vision) | β |
scene_get_mode | Report current Blender mode | β |
scene_list_selection | List selected objects/components | β |
scene_inspect_object | Detailed object info | β |
scene_snapshot_state | Capture scene snapshot | β |
scene_compare_snapshot | Compare two snapshots | β |
scene_inspect_material_slots | Material slot assignments | β |
scene_inspect_mesh_topology | Topology stats | β |
scene_inspect_modifiers | Modifier stack info | β |
scene_rename_object | Rename object by name | β |
scene_hide_object | Hide/show object in viewport | β |
scene_show_all_objects | Show all hidden objects | β |
scene_isolate_object | Isolate object (hide all others) | β |
scene_camera_orbit | Orbit viewport around target | β |
scene_camera_focus | Focus viewport on object | β |
scene_get_custom_properties | Get object metadata/custom properties | β |
scene_set_custom_property | Set/delete custom property on object | β |
scene_get_hierarchy | Get parent-child hierarchy | β |
scene_get_bounding_box | Get precise bounding box corners | β |
scene_get_origin_info | Get origin/pivot point info | β |
Modeling Tools (modeling_*)
Object Mode operations for creating and transforming objects.
| Tool | Description | Status |
|---|---|---|
modeling_create_primitive | Create cube, sphere, cylinder, etc. | β |
modeling_transform_object | Move, rotate, scale objects | β |
modeling_add_modifier | Add modifier to object | β |
modeling_apply_modifier | Apply (bake) modifier | β |
modeling_list_modifiers | List modifiers on object | β |
modeling_convert_to_mesh | Convert curve/text to mesh | β |
modeling_join_objects | Join multiple objects | β |
modeling_separate_object | Separate by loose parts/material | β |
modeling_set_origin | Set object origin point | β |
Lattice Deformation
| Tool | Description | Status |
|---|---|---|
lattice_create | Create lattice fitted to object | β |
lattice_bind | Bind object to lattice deformer | β |
lattice_edit_point | Move lattice control points | β |
Text Objects
| Tool | Description | Status |
|---|---|---|
text_create | Create 3D text object | β |
text_edit | Modify text content and properties | β |
text_to_mesh | Convert text to mesh for export | β |
Skin Modifier (Tubular Structures)
| Tool | Description | Status |
|---|---|---|
skin_create_skeleton | Create skeleton for skin modifier | β |
skin_set_radius | Set skin radius at vertices | β |
Mesh Tools (mesh_*)
Edit Mode operations for geometry manipulation.
Selection
| Tool | Description | Status |
|---|---|---|
mesh_select_all | Select/deselect all geometry | β |
mesh_select_by_index | Select by vertex/edge/face index | β |
mesh_select_linked | Select connected geometry | β |
mesh_select_more | Grow selection | β |
mesh_select_less | Shrink selection | β |
mesh_select_boundary | Select boundary edges | β |
mesh_select_loop | Select edge loop | β |
mesh_select_ring | Select edge ring | β |
mesh_select_by_location | Select by 3D position | β |
mesh_get_vertex_data | Get vertex positions | β |
Core Operations
| Tool | Description | Status |
|---|---|---|
mesh_extrude_region | Extrude selected faces | β |
mesh_delete_selected | Delete selected geometry | β |
mesh_fill_holes | Fill holes with faces | β |
mesh_bevel | Bevel edges/vertices | β |
mesh_loop_cut | Add loop cuts | β |
mesh_inset | Inset faces | β |
mesh_boolean | Boolean operations | β |
mesh_merge_by_distance | Merge nearby vertices | β |
mesh_subdivide | Subdivide geometry | β |
Transform & Geometry
| Tool | Description | Status |
|---|---|---|
mesh_transform_selected | Move/rotate/scale selected geometry | β |
mesh_bridge_edge_loops | Bridge two edge loops | β |
mesh_duplicate_selected | Duplicate selected geometry | β |
Deformation
| Tool | Description | Status |
|---|---|---|
mesh_smooth | Smooth vertices | β |
mesh_flatten | Flatten to plane | β |
mesh_randomize | Randomize vertex positions | β |
mesh_shrink_fatten | Move along normals | β |
Precision Tools
| Tool | Description | Status |
|---|---|---|
mesh_bisect | Cut mesh with plane | β |
mesh_edge_slide | Slide edges along topology | β |
mesh_vert_slide | Slide vertices along edges | β |
mesh_triangulate | Convert to triangles | β |
mesh_remesh_voxel | Voxel remesh | β |
Procedural
| Tool | Description | Status |
|---|---|---|
mesh_spin | Spin/lathe geometry around axis | β |
mesh_screw | Create spiral/helix geometry | β |
mesh_add_vertex | Add single vertex | β |
mesh_add_edge_face | Create edge/face from selection | β |
Vertex Groups
| Tool | Description | Status |
|---|---|---|
mesh_list_groups | List vertex groups | β |
mesh_create_vertex_group | Create new vertex group | β |
mesh_assign_to_group | Assign vertices to group | β |
mesh_remove_from_group | Remove vertices from group | β |
Edge Weights & Creases
| Tool | Description | Status |
|---|---|---|
mesh_edge_crease | Set crease weight for subdivision | β |
mesh_bevel_weight | Set bevel weight for bevel modifier | β |
mesh_mark_sharp | Mark/clear sharp edges | β |
Cleanup & Optimization
| Tool | Description | Status |
|---|---|---|
mesh_dissolve | Dissolve vertices/edges/faces (limited dissolve) | β |
mesh_tris_to_quads | Convert triangles to quads | β |
mesh_normals_make_consistent | Recalculate normals | β |
mesh_decimate | Reduce polycount on selection | β |
Knife & Cut
| Tool | Description | Status |
|---|---|---|
mesh_knife_project | Project cut from selected geometry | β |
mesh_rip | Rip/tear geometry at selection | β |
mesh_split | Split selection from mesh | β |
mesh_edge_split | Split mesh at selected edges | β |
Symmetry & Fill
| Tool | Description | Status |
|---|---|---|
mesh_symmetrize | Make mesh symmetric | β |
mesh_grid_fill | Fill boundary with quad grid | β |
mesh_poke_faces | Poke faces (add center vertex) | β |
mesh_beautify_fill | Rearrange triangles uniformly | β |
mesh_mirror | Mirror selected geometry | β |
mesh_set_proportional_edit | Enable soft selection falloff | β |
Curve Tools (curve_*)
Curve creation and conversion.
| Tool | Description | Status |
|---|---|---|
curve_create | Create Bezier/NURBS/Path/Circle curve | β |
curve_to_mesh | Convert curve to mesh | β |
Collection Tools (collection_*)
Collection management and hierarchy.
| Tool | Description | Status |
|---|---|---|
collection_list | List all collections | β |
collection_list_objects | List objects in collection | β |
collection_manage | Create/delete/move collections | β |
Material Tools (material_*)
Material creation and assignment.
| Tool | Description | Status |
|---|---|---|
material_list | List all materials | β |
material_list_by_object | List materials on object | β |
material_create | Setup PBR materials | β |
material_assign | Assign to objects/faces | β |
material_set_params | Adjust roughness, metallic, etc. | β |
material_set_texture | Bind image textures | β |
material_inspect_nodes | Inspect shader node graph | β |
UV Tools (uv_*)
UV mapping operations.
| Tool | Description | Status |
|---|---|---|
uv_list_maps | List UV maps on object | β |
uv_unwrap | Smart UV Project / Cube Projection | β |
uv_pack_islands | Pack UV islands | β |
uv_create_seam | Mark/clear UV seams | β |
System Tools (system_*)
Global project-level operations.
| Tool | Description | Status |
|---|---|---|
system_set_mode | High-level mode switching | β |
system_undo | Safe undo for AI | β |
system_redo | Safe redo for AI | β |
system_save_file | Save .blend file | β |
system_new_file | Create new file | β |
system_snapshot | Quick save/restore checkpoints | β |
Export Tools (export_*)
File export operations.
| Tool | Description | Status |
|---|---|---|
export_glb | Export to GLB format | β |
export_fbx | Export to FBX format | β |
export_obj | Export to OBJ format | β |
Import Tools (import_*)
File import operations.
| Tool | Description | Status |
|---|---|---|
import_obj | Import OBJ file | β |
import_fbx | Import FBX file | β |
import_glb | Import GLB/GLTF file | β |
import_image_as_plane | Import image as textured plane (reference) | β |
Baking Tools (bake_*)
Texture baking for game dev workflows.
| Tool | Description | Status |
|---|---|---|
bake_normal_map | Bake normal map (high-to-low or self) | β |
bake_ao | Bake ambient occlusion map | β |
bake_combined | Bake full render to texture | β |
bake_diffuse | Bake diffuse/albedo color | β |
Extraction Tools (extraction_*)
Analysis tools for the Automatic Workflow Extraction System. Enables deep topology analysis, component detection, symmetry detection, and multi-angle rendering for LLM Vision integration.
| Tool | Description | Status |
|---|---|---|
extraction_deep_topology | Deep topology analysis with feature detection | β |
extraction_component_separate | Separate mesh into loose parts | β |
extraction_detect_symmetry | Detect X/Y/Z symmetry planes | β |
extraction_edge_loop_analysis | Analyze edge loops and patterns | β |
extraction_face_group_analysis | Analyze face groups by normal/height | β |
extraction_render_angles | Multi-angle renders for LLM Vision | β |
Metaball Tools (metaball_*)
Organic blob primitives for medical/biological modeling.
| Tool | Description | Status |
|---|---|---|
metaball_create | Create metaball object | β |
metaball_add_element | Add element (ball, capsule, ellipsoid) | β |
metaball_to_mesh | Convert metaball to mesh | β |
Macro Tools (macro_*)
High-level abstractions where one command executes hundreds of Blender operations.
| Tool | Description | Status |
|---|---|---|
macro_organify | Convert blockouts to organic shapes | π§ |
macro_create_phone_base | Generate smartphone chassis | π§ |
macro_human_blockout | Generate proportional human mesh | π§ |
macro_retopologize | Automate low-poly conversion | π§ |
macro_panel_cut | Hard-surface panel cutting | π§ |
macro_lowpoly_convert | Reduce polycount preserving silhouette | π§ |
macro_cleanup_all | Scene-wide mesh cleanup | π§ |
Sculpting Tools (sculpt_*)
Organic shaping and sculpt workflows.
Core Brushes
| Tool | Description | Status |
|---|---|---|
sculpt_auto | High-level sculpt operation (mesh filters) | β |
sculpt_brush_smooth | Smooth brush | β |
sculpt_brush_grab | Grab brush | β |
sculpt_brush_crease | Crease brush | β |
Organic Brushes
| Tool | Description | Status |
|---|---|---|
sculpt_brush_clay | Add clay-like material | β |
sculpt_brush_inflate | Inflate/deflate areas | β |
sculpt_brush_blob | Create organic bulges | β |
sculpt_brush_snake_hook | Pull long tendrils (vessels, nerves) | β |
sculpt_brush_draw | Basic sculpt draw | β |
sculpt_brush_pinch | Pinch geometry together | β |
Dynamic Topology
| Tool | Description | Status |
|---|---|---|
sculpt_enable_dyntopo | Enable dynamic topology | β |
sculpt_disable_dyntopo | Disable dynamic topology | β |
sculpt_dyntopo_flood_fill | Apply detail level to entire mesh | β |
Armature Tools (armature_*)
Skeletal rigging and animation.
| Tool | Description | Status |
|---|---|---|
armature_create | Create armature with initial bone | β |
armature_add_bone | Add bone to armature | β |
armature_bind | Bind mesh to armature (auto weights) | β |
armature_pose_bone | Pose armature bone | β |
armature_weight_paint_assign | Assign weights to vertex group | β |
π€ Router Supervisor β
Intelligent Router acting as supervisor over LLM tool calls - not just an "intent matcher". Intercepts, corrects, expands, and overrides tool calls before execution.
Status: β Complete | All 6 Phases Done | Test counts vary β see π§ͺ Testing for up-to-date numbers
Documentation: See
_docs/_ROUTER/for full documentation including Quick Start, Configuration, Patterns, and API Reference.
All Phases Complete β
| Phase | Components | Status |
|---|---|---|
| Phase 1: Foundation | Directory structure, Domain entities, Interfaces, Metadata loader (119 JSON files), Config | β |
| Phase 2: Analysis | Tool interceptor, Scene context analyzer, Geometry pattern detector, Proportion calculator | β |
| Phase 3: Engines | Tool correction, Tool override, Workflow expansion, Error firewall, Intent classifier (LaBSE) | β |
| Phase 4: Integration | SupervisorRouter orchestrator, MCP integration, Logging & telemetry | β |
| Phase 5: Workflows | Phone workflow, Tower workflow, Screen cutout workflow, Custom YAML workflows | β |
| Phase 6: Testing & Docs | E2E test suite (see π§ͺ Testing), Complete documentation (6 guides) | β |
Key Features
| Feature | Description |
|---|---|
| LLM Supervisor | Intercepts and corrects LLM tool calls before execution |
| Scene-Aware | Analyzes Blender state via RPC for informed decisions |
| Pattern Detection | Recognizes 9 patterns: tower, phone, table, pillar, wheel, box, sphere, cylinder |
| Auto-Correction | Fixes mode violations, missing selection, invalid parameters |
| Workflow Expansion | Single tool β complete multi-step workflow |
| Error Firewall | Blocks/fixes invalid operations before they crash |
| 100% Offline | No external API calls - LaBSE runs locally (~1.8GB RAM) |
| Multilingual | LaBSE supports 109 languages for intent classification |
| Semantic Matching | Match workflows by meaning, not just keywords (LaBSE embeddings) |
| Generalization | Use similar workflow when exact match missing |
| Feedback Learning | Improve matching from user corrections |
| LanceDB Vector Store | O(log N) HNSW search with metadata filtering (TASK-047) |
| Confidence Adaptation | HIGH/MEDIUM/LOW confidence β full/filtered/core workflow (TASK-051) |
| Parametric Variables | $variable syntax with defaults and modifiers for dynamic params (TASK-052) |
Workflow-First Quick Start (recommended)
Use this when you want the LLM to prefer existing YAML workflows and only fall back to manual tool-calling when no workflow matches.
1) Optional: preview likely workflow matches (read-only)
workflow_catalog(action="search", query="<your prompt>", top_k=5, threshold=0.0)
2) Set the goal (mandatory)
router_set_goal(goal="<your prompt including modifiers>")
3) Handle Router response
- status == "needs_input": call router_set_goal(goal, resolved_params={...})
- status == "ready": proceed (workflow executes / expands into tool calls)
- status == "no_match": switch to manual tool-calling
- status == "error": router malfunction (fail-fast). Check logs and open a GitHub issue.
Example: LLM sends mesh tool in wrong mode
LLM: mesh_extrude(depth=0.5) # In OBJECT mode, no selection
Router detects:
- Mode: OBJECT (mesh tool needs EDIT)
- Selection: None (extrude needs faces)
- Pattern: phone_like
Router outputs:
1. system_set_mode(mode="EDIT")
2. mesh_select(action="all", mode="FACE")
3. mesh_inset(thickness=0.03)
4. mesh_extrude(depth=-0.02)
5. system_set_mode(mode="OBJECT")
Result: Screen cutout created instead of crash!
Semantic Workflow Matching
User: "zrΓ³b krzesΕo" (make a chair)
Router behavior:
β LaBSE semantic similarity search
β Found: table_workflow (0.72), tower_workflow (0.45)
β Uses table_workflow with inherited proportions
β Chair has proper leg ratios from table, vertical proportions from tower
Parametric Variables (TASK-052)
# In workflow YAML:
defaults:
leg_angle: 0.32 # A-frame legs (default)
modifiers:
"straight legs":
leg_angle: 0 # Override for vertical legs
"proste nogi": # Polish support
leg_angle: 0
steps:
- tool: modeling_transform_object
params:
rotation: [0, "$leg_angle", 0] # Uses variable
User: "table with straight legs"
β Modifier "straight legs" matches
β leg_angle = 0 (vertical legs instead of A-frame)
User: "stΓ³Ε z proste nogi"
β Polish modifier matches
β Same result: vertical legs
Configuration Presets
from server.router.infrastructure.config import RouterConfig
# Default (recommended)
config = RouterConfig()
# Strict mode (no auto-fixes)
config = RouterConfig(auto_mode_switch=False, auto_selection=False)
# Performance mode (longer cache)
config = RouterConfig(cache_ttl_seconds=2.0, log_decisions=False)
π§ LLM Context Optimization
Unified "mega tools" that consolidate multiple related operations to reduce LLM context usage.
Scene Mega Tools
| Mega Tool | Actions | Savings | Status |
|---|---|---|---|
scene_context | mode, selection | -1 | β |
scene_create | light, camera, empty | -2 | β |
scene_inspect | object, topology, modifiers, materials | -3 | β |
Mesh Mega Tools
| Mega Tool | Actions | Savings | Status |
|---|---|---|---|
mesh_select | all, none, linked, more, less, boundary | -4 | β |
mesh_select_targeted | by_index, loop, ring, by_location | -3 | β |
Total: 18 tools β 5 mega tools (-13 definitions for LLM context)
π Quick Start
1. Install the Blender Addon
- Download
blender_ai_mcp.zipfrom the Releases Page. - Open Blender -> Edit -> Preferences -> Add-ons.
- Click Install... and select the zip file.
- Enable the addon. It will start a local server on port
8765.
2. Configure your MCP Client (Cline / Claude Code / Codex CLI)
We recommend using Docker to run the MCP Server.
{
"mcpServers": {
"blender-ai-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e", "BLENDER_RPC_HOST=host.docker.internal",
"ghcr.io/patrykiti/blender-ai-mcp:latest"
],
"disabled": false,
"autoApprove": [
"scene_list_objects",
"scene_delete_object",
"scene_clean_scene",
"scene_duplicate_object",
"scene_set_active_object",
"scene_get_viewport",
"scene_set_mode",
"scene_context",
"scene_create",
"scene_inspect",
"scene_snapshot_state",
"scene_compare_snapshot",
"scene_rename_object",
"scene_hide_object",
"scene_show_all_objects",
"scene_isolate_object",
"scene_camera_orbit",
"scene_camera_focus",
"scene_get_custom_properties",
"scene_set_custom_property",
"scene_get_hierarchy",
"scene_get_bounding_box",
"scene_get_origin_info",
"collection_list",
"collection_list_objects",
"collection_manage",
"material_list",
"material_list_by_object",
"material_create",
"material_assign",
"material_set_params",
"material_set_texture",
"material_inspect_nodes",
"uv_list_maps",
"uv_unwrap",
"uv_pack_islands",
"uv_create_seam",
"modeling_create_primitive",
"modeling_transform_object",
"modeling_add_modifier",
"modeling_apply_modifier",
"modeling_convert_to_mesh",
"modeling_join_objects",
"modeling_separate_object",
"modeling_set_origin",
"modeling_list_modifiers",
"mesh_select",
"mesh_select_targeted",
"mesh_delete_selected",
"mesh_extrude_region",
"mesh_fill_holes",
"mesh_bevel",
"mesh_loop_cut",
"mesh_inset",
"mesh_boolean",
"mesh_merge_by_distance",
"mesh_subdivide",
"mesh_smooth",
"mesh_flatten",
"mesh_list_groups",
"mesh_get_vertex_data",
"mesh_randomize",
"mesh_shrink_fatten",
"mesh_create_vertex_group",
"mesh_assign_to_group",
"mesh_remove_from_group",
"mesh_bisect",
"mesh_edge_slide",
"mesh_vert_slide",
"mesh_triangulate",
"mesh_remesh_voxel",
"mesh_transform_selected",
"mesh_bridge_edge_loops",
"mesh_duplicate_selected",
"mesh_spin",
"mesh_screw",
"mesh_add_vertex",
"mesh_add_edge_face",
"mesh_edge_crease",
"mesh_bevel_weight",
"mesh_mark_sharp",
"mesh_dissolve",
"mesh_tris_to_quads",
"mesh_normals_make_consistent",
"mesh_decimate",
"mesh_knife_project",
"mesh_rip",
"mesh_split",
"mesh_edge_split",
"mesh_symmetrize",
"mesh_grid_fill",
"mesh_poke_faces",
"mesh_beautify_fill",
"mesh_mirror",
"curve_create",
"curve_to_mesh",
"text_create",
"text_edit",
"text_to_mesh",
"export_glb",
"export_fbx",
"export_obj",
"sculpt_auto",
"sculpt_brush_smooth",
"sculpt_brush_grab",
"sculpt_brush_crease",
"sculpt_brush_clay",
"sculpt_brush_inflate",
"sculpt_brush_blob",
"sculpt_brush_snake_hook",
"sculpt_brush_draw",
"sculpt_brush_pinch",
"sculpt_enable_dyntopo",
"sculpt_disable_dyntopo",
"sculpt_dyntopo_flood_fill",
"metaball_create",
"metaball_add_element",
"metaball_to_mesh",
"skin_create_skeleton",
"skin_set_radius",
"lattice_create",
"lattice_bind",
"lattice_edit_point",
"mesh_set_proportional_edit",
"system_set_mode",
"system_undo",
"system_redo",
"system_save_file",
"system_new_file",
"system_snapshot",
"bake_normal_map",
"bake_ao",
"bake_combined",
"bake_diffuse",
"import_obj",
"import_fbx",
"import_glb",
"import_image_as_plane",
"extraction_deep_topology",
"extraction_component_separate",
"extraction_detect_symmetry",
"extraction_edge_loop_analysis",
"extraction_face_group_analysis",
"extraction_render_angles",
"armature_create",
"armature_add_bone",
"armature_bind",
"armature_pose_bone",
"armature_weight_paint_assign",
"workflow_catalog",
"router_set_goal",
"router_get_status",
"router_clear_goal"
]
}
}
}
{
"mcpServers": {
"blender-ai-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--network", "host",
"-e", "BLENDER_RPC_HOST=127.0.0.1",
"ghcr.io/patrykiti/blender-ai-mcp:latest"
],
"disabled": false,
"autoApprove": [
"scene_list_objects",
"scene_delete_object",
"scene_clean_scene",
"scene_duplicate_object",
"scene_set_active_object",
"scene_get_viewport",
"scene_set_mode",
"scene_context",
"scene_create",
"scene_inspect",
"scene_snapshot_state",
"scene_compare_snapshot",
"scene_rename_object",
"scene_hide_object",
"scene_show_all_objects",
"scene_isolate_object",
"scene_camera_orbit",
"scene_camera_focus",
"scene_get_custom_properties",
"scene_set_custom_property",
"scene_get_hierarchy",
"scene_get_bounding_box",
"scene_get_origin_info",
"collection_list",
"collection_list_objects",
"collection_manage",
"material_list",
"material_list_by_object",
"material_create",
"material_assign",
"material_set_params",
"material_set_texture",
"material_inspect_nodes",
"uv_list_maps",
"uv_unwrap",
"uv_pack_islands",
"uv_create_seam",
"modeling_create_primitive",
"modeling_transform_object",
"modeling_add_modifier",
"modeling_apply_modifier",
"modeling_convert_to_mesh",
"modeling_join_objects",
"modeling_separate_object",
"modeling_set_origin",
"modeling_list_modifiers",
"mesh_select",
"mesh_select_targeted",
"mesh_delete_selected",
"mesh_extrude_region",
"mesh_fill_holes",
"mesh_bevel",
"mesh_loop_cut",
"mesh_inset",
"mesh_boolean",
"mesh_merge_by_distance",
"mesh_subdivide",
"mesh_smooth",
"mesh_flatten",
"mesh_list_groups",
"mesh_get_vertex_data",
"mesh_randomize",
"mesh_shrink_fatten",
"mesh_create_vertex_group",
"mesh_assign_to_group",
"mesh_remove_from_group",
"mesh_bisect",
"mesh_edge_slide",
"mesh_vert_slide",
"mesh_triangulate",
"mesh_remesh_voxel",
"mesh_transform_selected",
"mesh_bridge_edge_loops",
"mesh_duplicate_selected",
"mesh_spin",
"mesh_screw",
"mesh_add_vertex",
"mesh_add_edge_face",
"mesh_edge_crease",
"mesh_bevel_weight",
"mesh_mark_sharp",
"mesh_dissolve",
"mesh_tris_to_quads",
"mesh_normals_make_consistent",
"mesh_decimate",
"mesh_knife_project",
"mesh_rip",
"mesh_split",
"mesh_edge_split",
"mesh_symmetrize",
"mesh_grid_fill",
"mesh_poke_faces",
"mesh_beautify_fill",
"mesh_mirror",
"curve_create",
"curve_to_mesh",
"text_create",
"text_edit",
"text_to_mesh",
"export_glb",
"export_fbx",
"export_obj",
"sculpt_auto",
"sculpt_brush_smooth",
"sculpt_brush_grab",
"sculpt_brush_crease",
"sculpt_brush_clay",
"sculpt_brush_inflate",
"sculpt_brush_blob",
"sculpt_brush_snake_hook",
"sculpt_brush_draw",
"sculpt_brush_pinch",
"sculpt_enable_dyntopo",
"sculpt_disable_dyntopo",
"sculpt_dyntopo_flood_fill",
"metaball_create",
"metaball_add_element",
"metaball_to_mesh",
"skin_create_skeleton",
"skin_set_radius",
"lattice_create",
"lattice_bind",
"lattice_edit_point",
"mesh_set_proportional_edit",
"system_set_mode",
"system_undo",
"system_redo",
"system_save_file",
"system_new_file",
"system_snapshot",
"bake_normal_map",
"bake_ao",
"bake_combined",
"bake_diffuse",
"import_obj",
"import_fbx",
"import_glb",
"import_image_as_plane",
"extraction_deep_topology",
"extraction_component_separate",
"extraction_detect_symmetry",
"extraction_edge_loop_analysis",
"extraction_face_group_analysis",
"extraction_render_angles",
"armature_create",
"armature_add_bone",
"armature_bind",
"armature_pose_bone",
"armature_weight_paint_assign",
"workflow_catalog",
"router_set_goal",
"router_get_status",
"router_clear_goal"
]
}
}
}
Copilot uses a slightly different config structure. Ensure you map the temp directory properly if you want file outputs.
{
"mcpServers": {
"blender-ai-mcp": {
"type": "local",
"command": "docker",
"tools": [
"*"
],
"args": [
"run",
"-i",
"--rm",
"-v",
"/tmp:/tmp",
"ghcr.io/patrykiti/blender-ai-mcp:latest"
],
"env": {
"BLENDER_AI_TMP_INTERNAL_DIR": "/tmp",
"BLENDER_AI_TMP_EXTERNAL_DIR": "/tmp",
"BLENDER_RPC_HOST": "host.docker.internal"
}
}
}
}
Create/update ~/.codex/config.toml:
[mcp_servers.blender-ai-mcp]
command = "docker"
# Optional
args = [
"run",
"-i",
"-v",
"/tmp:/tmp",
"-e",
"BLENDER_AI_TMP_INTERNAL_DIR=/tmp",
"-e",
"BLENDER_AI_TMP_EXTERNAL_DIR=/tmp",
"-e",
"ROUTER_ENABLED=true",
"-e",
"LOG_LEVEL=DEBUG",
"-e",
"BLENDER_RPC_HOST=host.docker.internal",
"blender-ai-mcp:latest"
]
# Optional: propagate additional env vars to the MCP server.
# A default whitelist of env vars will be propagated to the MCP server.
# https://github.com/openai/codex/blob/main/codex-rs/rmcp-client/src/utils.rs#L82
env = {}
enabled_tools = [
"scene_list_objects",
"scene_delete_object",
"scene_clean_scene",
"scene_duplicate_object",
"scene_set_active_object",
"scene_get_viewport",
"scene_set_mode",
"scene_context",
"scene_create",
"scene_inspect",
"scene_snapshot_state",
"scene_compare_snapshot",
"scene_rename_object",
"scene_hide_object",
"scene_show_all_objects",
"scene_isolate_object",
"scene_camera_orbit",
"scene_camera_focus",
"scene_get_custom_properties",
"scene_set_custom_property",
"scene_get_hierarchy",
"scene_get_bounding_box",
"scene_get_origin_info",
"collection_list",
"collection_list_objects",
"collection_manage",
"material_list",
"material_list_by_object",
"material_create",
"material_assign",
"material_set_params",
"material_set_texture",
"material_inspect_nodes",
"uv_list_maps",
"uv_unwrap",
"uv_pack_islands",
"uv_create_seam",
"modeling_create_primitive",
"modeling_transform_object",
"modeling_add_modifier",
"modeling_apply_modifier",
"modeling_convert_to_mesh",
"modeling_join_objects",
"modeling_separate_object",
"modeling_set_origin",
"modeling_list_modifiers",
"mesh_select",
"mesh_select_targeted",
"mesh_delete_selected",
"mesh_extrude_region",
"mesh_fill_holes",
"mesh_bevel",
"mesh_loop_cut",
"mesh_inset",
"mesh_boolean",
"mesh_merge_by_distance",
"mesh_subdivide",
"mesh_smooth",
"mesh_flatten",
"mesh_list_groups",
"mesh_get_vertex_data",
"mesh_randomize",
"mesh_shrink_fatten",
"mesh_create_vertex_group",
"mesh_assign_to_group",
"mesh_remove_from_group",
"mesh_bisect",
"mesh_edge_slide",
"mesh_vert_slide",
"mesh_triangulate",
"mesh_remesh_voxel",
"mesh_transform_selected",
"mesh_bridge_edge_loops",
"mesh_duplicate_selected",
"mesh_spin",
"mesh_screw",
"mesh_add_vertex",
"mesh_add_edge_face",
"mesh_edge_crease",
"mesh_bevel_weight",
"mesh_mark_sharp",
"mesh_dissolve",
"mesh_tris_to_quads",
"mesh_normals_make_consistent",
"mesh_decimate",
"mesh_knife_project",
"mesh_rip",
"mesh_split",
"mesh_edge_split",
"mesh_symmetrize",
"mesh_grid_fill",
"mesh_poke_faces",
"mesh_beautify_fill",
"mesh_mirror",
"curve_create",
"curve_to_mesh",
"text_create",
"text_edit",
"text_to_mesh",
"export_glb",
"export_fbx",
"export_obj",
"sculpt_auto",
"sculpt_brush_smooth",
"sculpt_brush_grab",
"sculpt_brush_crease",
"sculpt_brush_clay",
"sculpt_brush_inflate",
"sculpt_brush_blob",
"sculpt_brush_snake_hook",
"sculpt_brush_draw",
"sculpt_brush_pinch",
"sculpt_enable_dyntopo",
"sculpt_disable_dyntopo",
"sculpt_dyntopo_flood_fill",
"metaball_create",
"metaball_add_element",
"metaball_to_mesh",
"skin_create_skeleton",
"skin_set_radius",
"lattice_create",
"lattice_bind",
"lattice_edit_point",
"mesh_set_proportional_edit",
"system_set_mode",
"system_undo",
"system_redo",
"system_save_file",
"system_new_file",
"system_snapshot",
"bake_normal_map",
"bake_ao",
"bake_combined",
"bake_diffuse",
"import_obj",
"import_fbx",
"import_glb",
"import_image_as_plane",
"extraction_deep_topology",
"extraction_component_separate",
"extraction_detect_symmetry",
"extraction_edge_loop_analysis",
"extraction_face_group_analysis",
"extraction_render_angles",
"armature_create",
"armature_add_bone",
"armature_bind",
"armature_pose_bone",
"armature_weight_paint_assign",
"workflow_catalog",
"router_set_goal",
"router_get_status",
"router_clear_goal"
]
β οΈ Important Network Configuration:
- macOS/Windows: Use
host.docker.internal(as shown in the first config). The--network hostoption does NOT work on Docker Desktop for Mac/Windows. - Linux: Use
--network hostwith127.0.0.1(as shown in the second config). - Troubleshooting: If the MCP server starts but cannot connect to Blender (timeout errors), ensure Blender is running with the addon enabled and that port
8765is not blocked.
Viewport Output Modes & Temp Directory Mapping
The scene_get_viewport tool supports multiple output modes via the output_mode argument:
IMAGE(default): returns a FastMCPImageresource (best for Cline / clients with native image support).BASE64: returns the raw base64-encoded JPEG string for direct Vision-module consumption.FILE: writes the image to a temp directory and returns a message with host-visible file paths.MARKDOWN: writes the image and returns rich markdown with an inlinedata:URL plus host-visible paths.
When running in Docker, map the internal temp directory to a host folder and configure env vars:
# Example volume & env mapping
docker run -i --rm \
-v /host/tmp/blender-ai-mcp:/tmp/blender-ai-mcp \
-e BLENDER_RPC_HOST=host.docker.internal \
-e BLENDER_AI_TMP_INTERNAL_DIR=/tmp/blender-ai-mcp \
-e BLENDER_AI_TMP_EXTERNAL_DIR=/host/tmp/blender-ai-mcp \
ghcr.io/patrykiti/blender-ai-mcp:latest
π Star History
π€ Contributing
We welcome contributions! Please read CONTRIBUTING.md to understand our Clean Architecture standards before submitting a Pull Request.
π§© Community & Support
- Support: SUPPORT.md
- Security: SECURITY.md
- Code of Conduct: CODE_OF_CONDUCT.md
π¨βπ» Author
Patryk CiechaΕski
- GitHub: PatrykIti
License
This project is licensed under the Business Source License 1.1 (BSL 1.1)
with a custom Additional Use Grant authored by Patryk CiechaΕski (PatrykIti).
The license automatically converts to Apache 2.0 on 2029-12-01.
For the full license text, see: LICENSE
Change License text (Apache 2.0): LICENSE-APACHE-2.0.txt
Related Servers
Anki MCP Server
Connects to a local Anki instance to review and create flashcards. Requires the Anki desktop app and Anki-Connect add-on.
Logseq
Control and interact with a local Logseq graph for knowledge management and note-taking.
Kibela
An MCP server for integrating with the Kibela API, allowing LLMs to access and manage content on the knowledge-sharing platform.
Cal.com Calendar
Integrates with the Cal.com Calendar API for appointment scheduling.
Browser Use MCP Server
Automate browser actions using natural language commands. Powered by Playwright and supports multiple LLM providers.
PowerPoint Translator
Translate PowerPoint files using AWS Bedrock. Requires AWS credentials to be configured.
Penpot MCP Server
Integrates AI language models with the Penpot design platform to automate design workflows.
Confluence MCP
An MCP server that enables AI assistants to interact with Confluence content through a standardized interface.
U301 URL Shortener
Create short URLs using the U301 URL Shortener service.
Ortto MCP Server
Orttoβs new MCP Server lets you connect your favorite AI assistant to Ortto. Once connected, your assistant can securely access customer data, audiences, and campaign insights from Orttoβs CDP and marketing automation platform.