Adapt Blender¶
Adapt Blender — mvp.adapt_blender
Cluster: Creative & Media | Type: component | MCP Tools: 69
Overview¶
Blender 3D automation block that drives the Blender binary through a subprocess Python API, generating bpy scripts on the fly for primitive creation, modifiers, materials, animation keyframes, rendering, and export. When Blender is not installed it falls back to a pure-Python OBJ text generator for cube, sphere, plane, and cylinder primitives so the block remains useful in headless environments. Supports persistent sessions so multiple operations can accumulate state inside a single .blend file.
Production Review Outcome¶
adapt_blender has real utility for basic OBJ fallback generation and for users who have Blender installed and configured. It should not be treated as broadly production-ready in a launch workflow, because most 3D, rendering, session, animation, material, and export operations require a local Blender binary plus a working Blender runtime environment.
For first-user and launch-plan use, position this component as beta:
- Works without Blender for simple OBJ primitive generation: cube, sphere, plane, and cylinder.
- Requires Blender for rendering, materials, modifiers, animation, session persistence, file import, and non-OBJ exports.
- Returns structured
BLENDER_ERRORfailures when Blender is unavailable for operations that cannot fall back. - Useful for technically capable users or controlled demos where Blender installation is verified first.
- Avoid using this component as evidence that G6 provides production-grade 3D rendering out of the box.
When to use:
- Programmatically constructing and rendering 3D scenes from agent-generated geometry descriptions
- Exporting meshes to OBJ, STL, glTF, or FBX for downstream pipelines
- Building animated sequences with keyframe data driven by solver or goal-engine output
- Creating persistent sessions to accumulate scene objects across multiple agent steps
- Pulling free CC0 HDRIs, textures, and models from Poly Haven (
polyhaven_*ops) to dress agent-built scenes without manual asset hunting - Fast OpenGL
viewport_previewfor agent visual feedback (~1–2 s vs ~10–60 s for full Cycles/EEVEE render)
Network use is opt-out via allow_network=False; cached assets still serve in offline mode. Downloads are restricted to *.polyhaven.org / *.polyhaven.com hosts with a 200 MB per-asset cap.
Use without Blender only for:
create_primitivewithcube,sphere,plane, orcylinder- Basic OBJ text output from the Python fallback backend
Example:
from mvp.adapt_blender import AdaptBlenderBlock, BlenderInput
block = AdaptBlenderBlock(name="blender")
result = block.infer(BlenderInput(
op="create_primitive",
primitive="sphere",
name="MySphere",
scale=[1.5, 1.5, 1.5],
location=[0.0, 0.0, 0.0],
))
# result.value.objects → ["MySphere"]; result.value.vertices → sphere vertex count
Works well with: adapt_generative_art, adapt_image, adapt_comfyui
Public API¶
AdaptBlenderBlock(AIBlock[BlenderInput, BlenderOutput, None])¶
Blender 3D automation block.
| Field | Type | Default |
|---|---|---|
name | str | 'adapt_blender' |
resource_bounds | ResourceBounds \| None | None |
usage | ResourceUsage | field(default_factory=ResourceUsage) |
sessions_dir | str \| None | None |
Methods:
infer(data: BlenderInput) -> Result[BlenderOutput]¶
PolyhavenCache¶
Filesystem + manifest cache for Poly Haven downloads.
Constructor:
| Parameter | Type | Default |
|---|---|---|
cache_root | Path \| None | None |
db_path | str \| None | None |
Methods:
hdri_path(slug: str, resolution: str, ext: str) -> Path¶
texture_map_path(slug: str, map_type: str, resolution: str, ext: str) -> Path¶
model_path(slug: str, resolution: str, ext: str) -> Path¶
lookup(slug: str, asset_type: str, resolution: str) -> dict[str, Any] | None¶
Return manifest row if it exists AND the file is still on disk.
record(slug: str, asset_type: str, resolution: str, local_path: str, sha256: str, bytes_: int) -> None¶
list_all() -> list[dict[str, Any]]¶
BlenderInput(BaseModel)¶
Input to AdaptBlenderBlock.
| Field | Type | Default |
|---|---|---|
op | str | 'create_primitive' |
primitive | str | '' |
name | str | '' |
location | list[float] | [0.0, 0.0, 0.0] |
scale | list[float] | [1.0, 1.0, 1.0] |
rotation | list[float] | [0.0, 0.0, 0.0] |
material_color | str | '' |
modifier_type | str | '' |
modifier_params | dict | {} |
keyframe_data | dict | {} |
render_engine | str | 'EEVEE' |
render_resolution | list[int] | [1920, 1080] |
output_path | str | '' |
export_format | str | 'obj' |
script | str | '' |
scene_name | str | '' |
camera_location | list[float] | [0.0, 0.0, 10.0] |
camera_target | list[float] | [0.0, 0.0, 0.0] |
light_type | str | 'SUN' |
light_energy | float | 1.0 |
preset_name | str | '' |
timeout_seconds | int | 120 |
session_id | str | '' |
clear_scene | bool | True |
import_path | str | '' |
import_format | str | '' |
object_names | list[str] | [] |
material_roughness | float | -1.0 |
material_metallic | float | -1.0 |
material_emission | str | '' |
material_emission_strength | float | 0.0 |
material_transmission | float | 0.0 |
material_ior | float | 1.45 |
material_alpha | float | 1.0 |
light_location | list[float] | [0.0, 0.0, 5.0] |
light_rotation | list[float] | [0.0, 0.0, 0.0] |
light_color | str | '' |
light_radius | float | 0.0 |
light_params | dict | {} |
frame_start | int | 1 |
frame_end | int | 250 |
fps | int | 24 |
frame_current | int | 1 |
render_output_format | str | 'PNG' |
render_samples | int | 0 |
render_denoising | bool | False |
render_transparent_bg | bool | False |
boolean_operation | str | '' |
boolean_target | str | '' |
parent_name | str | '' |
child_name | str | '' |
collection_name | str | '' |
select_pattern | str | '' |
select_type | str | '' |
bone_name | str | '' |
bone_head | list[float] | [0.0, 0.0, 0.0] |
bone_tail | list[float] | [0.0, 0.0, 1.0] |
bone_parent_name | str | '' |
armature_name | str | '' |
bones | list[dict] | [] |
pose_rotation | list[float] | [0.0, 0.0, 0.0] |
pose_location | list[float] | [0.0, 0.0, 0.0] |
shape_key_name | str | '' |
shape_key_value | float | 0.0 |
driver_target | str | '' |
driver_property | str | '' |
driver_expression | str | '' |
constraint_type | str | '' |
constraint_params | dict | {} |
physics_type | str | '' |
physics_params | dict | {} |
bake_start | int | 1 |
bake_end | int | 250 |
polyhaven_slug | str | '' |
polyhaven_resolution | str | '2k' |
polyhaven_texture_maps | list[str] | ['Diffuse', 'nor_gl', 'Rough'] |
allow_network | bool | True |
preview_resolution | list[int] | [512, 512] |
native | BackendNativeOpRequest \| None | None |
scene_graph | SceneGraph \| None | None |
material_node_graph | MaterialNodeGraph \| None | None |
geometry_node_graph | GeometryNodeGraph \| None | None |
asset_operation | AssetOperation \| None | None |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
BlenderOutput(BaseModel)¶
Output from AdaptBlenderBlock.
| Field | Type | Default |
|---|---|---|
op | str | required |
output_path | str | '' |
output_base64 | str | '' |
objects | list[str] | [] |
format | str | '' |
vertices | int | 0 |
faces | int | 0 |
metadata | dict | {} |
backend | str | '' |
script_used | str | '' |
session_id | str | '' |
degraded | bool | False |
degradation_reason | str \| None | None |
available_with | str | '' |
warnings | list[dict[str, Any]] | [] |
completion_state | str | 'qualified-draft' |
warning_card | dict[str, Any] \| None | None |
evidence | dict[str, Any] | {} |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
error_code | str | '' |
error_message | str | '' |
BlenderSession¶
Represents a single Blender session backed by a .blend file on disk.
| Field | Type | Default |
|---|---|---|
session_id | str | required |
session_dir | str | required |
blend_path | str | required |
Methods:
exists() -> bool¶
True if the .blend file has been written (session has been initialised).
SessionManager¶
Manages session directories under a configurable root.
Constructor:
| Parameter | Type | Default |
|---|---|---|
sessions_dir | str \| None | None |
Methods:
new_session(session_id: str | None = None) -> BlenderSession¶
Create a new session directory and return a BlenderSession for it.
get_session(session_id: str) -> BlenderSession | None¶
Return a BlenderSession if the session directory exists, else None.
delete_session(session_id: str) -> bool¶
Delete the session directory. Returns True if deleted, False if not found.
list_sessions() -> list[str]¶
Return sorted session IDs (directory names) under the sessions root.
AdaptBlenderMCPBlock(AIBlock[MCPBlenderInput, MCPBlenderOutput, dict])¶
Full-featured Blender 3D block with SQLite persistence.
| Field | Type | Default |
|---|---|---|
name | str | 'adapt_blender_mcp' |
state | dict \| None | None |
db_path | str | ':memory:' |
sessions_dir | str \| None | None |
resource_bounds | ResourceBounds \| None | None |
usage | ResourceUsage | field(default_factory=ResourceUsage) |
Methods:
infer(data: MCPBlenderInput) -> Result[MCPBlenderOutput]¶
MCPBlenderRecord(BaseModel)¶
| Field | Type | Default |
|---|---|---|
id | str | required |
record_type | str | required |
key | str | required |
value | str | required |
tags | list[str] | [] |
timestamp | str | required |
metadata | dict[str, Any] | {} |
MCPBlenderInput(BaseModel)¶
| Field | Type | Default |
|---|---|---|
op | Literal['discover_capabilities', 'capabilities', 'create_primitive', 'apply_modifier', 'set_material', 'animate_keyframe', 'render', 'export_obj', 'export_stl', 'export_gltf', 'export_fbx', 'list_objects', 'get_metadata', 'run_script', 'set_camera', 'set_lighting', 'merge_scenes', 'duplicate', 'array_modifier', 'import_file', 'transform_object', 'delete_object', 'add_named_light', 'render_animation', 'set_scene_range', 'boolean_op', 'select_objects', 'parent_objects', 'join_objects', 'create_collection', 'move_to_collection', 'create_armature', 'add_bone', 'parent_to_armature', 'pose_bone', 'add_shape_key', 'set_shape_key_value', 'add_driver', 'add_constraint', 'set_physics', 'bake_animation', 'scene_save', 'scene_load', 'scene_list', 'scene_delete', 'preset_list', 'preset_apply', 'stats', 'get_info', 'session_new', 'session_get', 'session_delete', 'session_list', 'run_workflow', 'viewport_preview', 'polyhaven_hdri', 'polyhaven_texture', 'polyhaven_model', 'polyhaven_cache_list', 'recommend_technique', 'list_patterns', 'backend_native_op', 'native_op', 'build_scene_graph', 'build_material_nodes', 'build_geometry_nodes', 'asset_import', 'asset_export', 'render_export'] | required |
primitive | str | '' |
name | str | '' |
location | list[float] | [0.0, 0.0, 0.0] |
scale | list[float] | [1.0, 1.0, 1.0] |
rotation | list[float] | [0.0, 0.0, 0.0] |
material_color | str | '' |
modifier_type | str | '' |
modifier_params | dict | {} |
keyframe_data | dict | {} |
render_engine | str | 'EEVEE' |
render_resolution | list[int] | [1920, 1080] |
output_path | str | '' |
export_format | str | 'obj' |
script | str | '' |
scene_name | str | '' |
camera_location | list[float] | [0.0, 0.0, 10.0] |
camera_target | list[float] | [0.0, 0.0, 0.0] |
light_type | str | 'SUN' |
light_energy | float | 1.0 |
preset_name | str | '' |
timeout_seconds | int | 120 |
import_path | str | '' |
import_format | str | '' |
object_names | list[str] | [] |
clear_scene | bool | True |
material_roughness | float | -1.0 |
material_metallic | float | -1.0 |
material_emission | str | '' |
material_emission_strength | float | 0.0 |
material_transmission | float | 0.0 |
material_ior | float | 1.45 |
material_alpha | float | 1.0 |
light_location | list[float] | [0.0, 0.0, 5.0] |
light_rotation | list[float] | [0.0, 0.0, 0.0] |
light_color | str | '' |
light_radius | float | 0.0 |
light_params | dict | {} |
frame_start | int | 1 |
frame_end | int | 250 |
fps | int | 24 |
frame_current | int | 1 |
render_output_format | str | 'PNG' |
render_samples | int | 0 |
render_denoising | bool | False |
render_transparent_bg | bool | False |
boolean_operation | str | '' |
boolean_target | str | '' |
parent_name | str | '' |
child_name | str | '' |
collection_name | str | '' |
select_pattern | str | '' |
select_type | str | '' |
bone_name | str | '' |
bone_head | list[float] | [0.0, 0.0, 0.0] |
bone_tail | list[float] | [0.0, 0.0, 1.0] |
bone_parent_name | str | '' |
armature_name | str | '' |
bones | list[dict] | [] |
pose_rotation | list[float] | [0.0, 0.0, 0.0] |
pose_location | list[float] | [0.0, 0.0, 0.0] |
shape_key_name | str | '' |
shape_key_value | float | 0.0 |
driver_target | str | '' |
driver_property | str | '' |
driver_expression | str | '' |
constraint_type | str | '' |
constraint_params | dict | {} |
physics_type | str | '' |
physics_params | dict | {} |
bake_start | int | 1 |
bake_end | int | 250 |
scene_data_json | str | '' |
description | str | '' |
tags | list[str] | [] |
query | str | '' |
limit | int | 50 |
top_k | int | 5 |
session_id | str | '' |
workflow_ops_json | str | '' |
polyhaven_slug | str | '' |
polyhaven_resolution | str | '2k' |
polyhaven_texture_maps | list[str] | ['Diffuse', 'nor_gl', 'Rough'] |
allow_network | bool | True |
preview_resolution | list[int] | [512, 512] |
native | dict[str, Any] \| None | None |
scene_graph | dict[str, Any] \| None | None |
material_node_graph | dict[str, Any] \| None | None |
geometry_node_graph | dict[str, Any] \| None | None |
asset_operation | dict[str, Any] \| None | None |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
brief | str | '' |
context | str | '' |
MCPBlenderOutput(BaseModel)¶
| Field | Type | Default |
|---|---|---|
op | str | required |
key | str | '' |
value | str | '' |
found | bool | False |
count | int | 0 |
records | list[MCPBlenderRecord] | [] |
retrieved | list[str] | [] |
scores | list[float] | [] |
summary | str | '' |
message | str | '' |
output_path | str | '' |
output_base64 | str | '' |
objects | list[str] | [] |
format | str | '' |
vertices | int | 0 |
faces | int | 0 |
backend | str | '' |
script_used | str | '' |
metadata | dict[str, Any] | {} |
session_id | str | '' |
sessions | list[str] | [] |
degraded | bool | False |
degradation_reason | str \| None | None |
available_with | str | '' |
warnings | list[dict[str, Any]] | [] |
completion_state | str | 'qualified-draft' |
warning_card | dict[str, Any] \| None | None |
evidence | dict[str, Any] | {} |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
error_code | str | '' |
error_message | str | '' |
recommendation | dict[str, Any] | {} |
llm_used | bool | False |
BlenderStore¶
Sync SQLite blender store with 2 tables: scenes and presets.
Constructor:
| Parameter | Type | Default |
|---|---|---|
db_path | str | ':memory:' |
Methods:
save_scene(name: str, description: str, scene_data: str, tags: list[str], blend_path: str = '') -> str¶
Save or update a named scene.
load_scene(name: str) -> dict[str, Any] | None¶
Load a scene by name.
list_scenes(limit: int = 50) -> list[dict[str, Any]]¶
List all saved scenes.
delete_scene(name: str) -> bool¶
Delete a scene by name.
list_presets(limit: int = 50) -> list[dict[str, Any]]¶
List all presets (built-in + user).
get_preset(name: str) -> dict[str, Any] | None¶
Get a preset by name.
save_preset(name: str, description: str, script: str, tags: list[str]) -> str¶
Save or update a user preset.
polyhaven_lookup(slug: str, asset_type: str, resolution: str) -> dict[str, Any] | None¶
Return manifest row for a cached Poly Haven asset, or None.
polyhaven_insert(slug: str, asset_type: str, resolution: str, local_path: str, sha256: str, bytes_: int, downloaded_at: int) -> None¶
Upsert a Poly Haven download manifest row.
polyhaven_list(limit: int = 200) -> list[dict[str, Any]]¶
count_all() -> dict[str, int]¶
Functions¶
parse_stdout(stdout: str) -> dict[str, Any]¶
Parse structured tag lines written by bpy scripts to stdout.
validate_modifier_type(modifier_type: str) -> str | None¶
normalise_modifier_type(modifier_type: str) -> str¶
validate_primitive(primitive: str) -> str | None¶
validate_hex_color(color: str) -> str | None¶
normalise_render_engine(engine: str) -> str¶
validate_import_format(fmt: str) -> str | None¶
validate_file_path(path: str) -> str | None¶
validate_polyhaven_slug(slug: str) -> str | None¶
normalise_polyhaven_resolution(res: str) -> str¶
Return one of {1k,2k,4k,8k}; defaults to '2k' for unknown/empty input.
MCP Tools¶
| Operation | Source |
|---|---|
discover_capabilities | blender_mcp |
capabilities | blender_mcp |
create_primitive | blender_mcp |
apply_modifier | blender_mcp |
set_material | blender_mcp |
animate_keyframe | blender_mcp |
render | blender_mcp |
export_obj | blender_mcp |
export_stl | blender_mcp |
export_gltf | blender_mcp |
export_fbx | blender_mcp |
list_objects | blender_mcp |
get_metadata | blender_mcp |
run_script | blender_mcp |
set_camera | blender_mcp |
set_lighting | blender_mcp |
merge_scenes | blender_mcp |
duplicate | blender_mcp |
array_modifier | blender_mcp |
import_file | blender_mcp |
transform_object | blender_mcp |
delete_object | blender_mcp |
add_named_light | blender_mcp |
render_animation | blender_mcp |
set_scene_range | blender_mcp |
boolean_op | blender_mcp |
select_objects | blender_mcp |
parent_objects | blender_mcp |
join_objects | blender_mcp |
create_collection | blender_mcp |
move_to_collection | blender_mcp |
create_armature | blender_mcp |
add_bone | blender_mcp |
parent_to_armature | blender_mcp |
pose_bone | blender_mcp |
add_shape_key | blender_mcp |
set_shape_key_value | blender_mcp |
add_driver | blender_mcp |
add_constraint | blender_mcp |
set_physics | blender_mcp |
bake_animation | blender_mcp |
scene_save | blender_mcp |
scene_load | blender_mcp |
scene_list | blender_mcp |
scene_delete | blender_mcp |
preset_list | blender_mcp |
preset_apply | blender_mcp |
stats | blender_mcp |
get_info | blender_mcp |
session_new | blender_mcp |
session_get | blender_mcp |
session_delete | blender_mcp |
session_list | blender_mcp |
run_workflow | blender_mcp |
viewport_preview | blender_mcp |
polyhaven_hdri | blender_mcp |
polyhaven_texture | blender_mcp |
polyhaven_model | blender_mcp |
polyhaven_cache_list | blender_mcp |
recommend_technique | blender_mcp |
list_patterns | blender_mcp |
backend_native_op | blender_mcp |
native_op | blender_mcp |
build_scene_graph | blender_mcp |
build_material_nodes | blender_mcp |
build_geometry_nodes | blender_mcp |
asset_import | blender_mcp |
asset_export | blender_mcp |
render_export | blender_mcp |