blender-ai-mcp
Health Uyari
- License — License: NOASSERTION
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 9 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
This MCP server acts as a secure translation layer, enabling Large Language Models to control Blender for 3D modeling workflows via curated, sandboxed tools rather than executing raw, arbitrary Python scripts.
Security Assessment
The overall risk is rated as Low. The architecture is designed with safety in mind, acting as a buffer between the AI and Blender's internal state machine to prevent arbitrary code execution crashes. An automated code scan of 12 files found no dangerous patterns, no hardcoded secrets, and no requests for dangerous system permissions. The primary communication method relies on standard JSON-RPC over local TCP sockets. Because it interacts with an external application via sockets, you should be aware of the local network communication, though it does not pose a severe threat.
Quality Assessment
The project is actively maintained, with its last push occurring today. It utilizes a modern, clean architecture (FastMCP server paired with a Blender Addon) and includes CI/CD pipelines alongside Docker support. The community visibility is currently low, marked by only 9 GitHub stars, which reflects its early-stage or niche status rather than a lack of quality. The repository declares a BUSL-1.1 license in the documentation, though the automated check returned a "NOASSERTION" status. You should verify the license terms before using it in commercial production environments.
Verdict
Safe to use, though verify the BUSL-1.1 license terms for commercial applications.
Production-shaped MCP server for Blender with goal-first routing, curated tools, deterministic verification, and vision-assisted 3D modeling workflows.
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.
Watch demo video🚀 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.
📋 Example E2E Test Output (click to expand)tests/e2e/tools/extraction/test_face_group_analysis.py ....
tests/e2e/tools/extraction/test_render_angles.py ....
tests/e2e/tools/import_tool/test_import_tools.py .........
tests/e2e/tools/knife_cut/test_knife_cut_tools.py .........
tests/e2e/tools/lattice/test_lattice_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/mesh/test_mesh_symmetry_fill.py ............................
tests/e2e/tools/scene/test_camera_focus.py ....
tests/e2e/tools/scene/test_camera_orbit.py ......
tests/e2e/tools/scene/test_hide_object.py ...
tests/e2e/tools/scene/test_isolate_object.py ...
tests/e2e/tools/scene/test_rename_object.py ..
tests/e2e/tools/scene/test_scene_inspect_material_slots.py ....
tests/e2e/tools/scene/test_show_all_objects.py ...
tests/e2e/tools/scene/test_snapshot_tools.py ...
tests/e2e/tools/sculpt/test_sculpt_tools.py .............
tests/e2e/tools/system/test_system_tools.py ............
tests/e2e/tools/text/test_text_tools.py ....................
tests/e2e/tools/uv/test_uv_tools.py ................
============================= 352 passed in 46.21s ==============================
🗺️ 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 | ✅ |
Note: scene_get_constraints is now internal to scene_inspect(action="constraints").
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 | ✅ |
Note: modeling_get_modifier_data is now internal to scene_inspect(action="modifier_data").
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 | ✅ |
lattice_get_points |
Get lattice point positions | ✅ |
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 | ✅ |
Note: Mesh introspection actions are consolidated under mesh_inspect (internal mesh_get_*).
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 | ✅ |
curve_get_data |
Get curve splines and settings | ✅ |
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 | ✅ |
armature_get_data |
Get armature bones and hierarchy | ✅ |
🤖 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 |
| Confidence Adaptation | HIGH/MEDIUM/LOW confidence → full/filtered/core workflow |
| Parametric Variables | $variable syntax with defaults and modifiers for dynamic params |
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: import external workflow YAML/JSON
workflow_catalog(action="import", filepath="/path/to/workflow.yaml")
workflow_catalog(action="import", content="<yaml or json>", content_type="yaml")
workflow_catalog(action="import_init", content_type="json", source_name="chair.json", total_chunks=2)
workflow_catalog(action="import_append", session_id="...", chunk_data="...", chunk_index=0)
workflow_catalog(action="import_append", session_id="...", chunk_data="...", chunk_index=1)
workflow_catalog(action="import_finalize", session_id="...", overwrite=true)
- if status == "needs_input": repeat with overwrite=true or overwrite=false
2) Optional: preview likely workflow matches
workflow_catalog(action="search", query="<your prompt>", top_k=5, threshold=0.0)
3) Set the goal (mandatory)
router_set_goal(goal="<your prompt including modifiers>")
4) 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
# 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
Mega Tools (LLM Context Optimization)Unified "mega tools" that consolidate multiple related operations to reduce LLM context usage.
Mega tools are wrappers only; action-level handlers live as internal functions backed by Blender addon RPC.
Standalone MCP tools are exposed only where explicitly listed.
Router can still execute internal actions via handler mappings and per-tool JSON metadata.
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, constraints, modifier_data | -5 | ✅ |
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 | ✅ |
mesh_inspect |
vertices, edges, faces, uvs, normals, attributes, shape_keys, group_weights, summary | -7 | ✅ |
Total: 28 tools → 6 mega tools (-22 definitions for LLM context).
mesh_inspect.summary sources (recommended): scene_inspect(topology), uv_list_maps, mesh_get_shape_keys, mesh_get_loop_normals, mesh_list_groups, modeling_list_modifiers.
🚀 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.
Cline / Claude Code —cline_mcp_settings.json (macOS/Windows)
{
"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_inspect",
"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_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",
"curve_get_data",
"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",
"lattice_get_points",
"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",
"armature_get_data",
"workflow_catalog",
"router_set_goal",
"router_get_status",
"router_clear_goal"
]
}
}
}
Cline / Claude Code — cline_mcp_settings.json (Linux)
{
"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_inspect",
"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_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",
"curve_get_data",
"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",
"lattice_get_points",
"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",
"armature_get_data",
"workflow_catalog",
"router_set_goal",
"router_get_status",
"router_clear_goal"
]
}
}
}
GitHub Copilot CLI
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"
}
}
}
}
Codex CLI — ~/.codex/config.toml
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_inspect",
"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_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",
"curve_get_data",
"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",
"lattice_get_points",
"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",
"armature_get_data",
"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.
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
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi