# blenderwright [Health: Active]

**Category:** 📐 Architecture & Design  
**Repository:** https://github.com/HoldMyBeer-gg/blenderwright  
**GitHub Stars:** 178  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/blenderwright

## Description
MCP server for Blender. 191 tools for modelling, materials, rendering and more, driven by Claude, Cursor, Codex, Ollama, llama.cpp, or any MCP client.

## Tools
Capabilities this server exposes over MCP:

- **get_scene_info** — Get full scene information including object tree, hierarchy, counts, frame range, fps, and render engine.

    Returns a dict with scene name, object list with hierarchy, object type counts,
    frame range (start, end, current), fps, and active render engine.
    
- **set_scene_property** — Set a scene property such as frame_start, frame_end, frame_current, fps, unit_system, or render_engine.

    Args:
        property: The scene property to set. Must be one of: frame_start, frame_end,
                  frame_current, frame_step, fps, unit_system, render_engine, use_gravity, gravity.
        value: The value to set the property to. Type depends on the property.

    Returns:
        Confirmation dict with the property name and new value.
    
- **set_units** — Set the scene's units, for real-world sizes (e.g. a 3D print in millimetres).

    Only the settings given are changed. Unit names depend on the system:
    METRIC lengths are KILOMETERS, METERS, CENTIMETERS, MILLIMETERS, MICROMETERS;
    IMPERIAL lengths are MILES, FEET, INCHES, THOU. ADAPTIVE picks per value.

    Args:
        system: NONE, METRIC or IMPERIAL. NONE takes no units.
        scale_length: Blender units to scene units, e.g. 0.001 so 1 unit reads 1 mm.
        length_unit: Display unit for lengths.
        mass_unit: METRIC: TONNES, KILOGRAMS, GRAMS, MILLIGRAMS; IMPERIAL: TONNES,
            CENTUM_WEIGHTS, STONES, POUNDS, OUNCES.
        time_unit: DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS.
        temperature_unit: KELVIN plus CELSIUS (METRIC) or FAHRENHEIT (IMPERIAL).
        rotation: DEGREES or RADIANS.
        use_separate: Show compound values like 1 m 20 cm.

    Returns:
        Every unit setting after the change.
    
- **list_scenes** — List all scenes in the current Blender file.

    Returns a list of dicts, each containing the scene name and object count.
    
- **create_scene** — Create a new scene.

    Args:
        name: Name for the new scene.

    Returns:
        Confirmation dict with the created scene name.
    
- **delete_scene** — Delete a scene by name.

    Args:
        scene_name: Name of the scene to delete. Cannot delete the last remaining scene.

    Returns:
        Confirmation dict.
    
- **suggest_extensions** — Suggest helpful Blender extensions for a planned task.

    Analyzes the task description and recommends free Blender extensions
    that could improve the workflow. Already-installed extensions are excluded.

    Args:
        task_description: Description of the planned task. If empty, returns
            all extensions not currently installed.

    Returns:
        Dict with 'suggestions' list of recommended extensions and
        'installed' list of already-installed extension IDs.
    
- **create_object** — Create a primitive object in the scene.

    Args:
        type: Primitive type. One of: CUBE, SPHERE, UV_SPHERE, ICO_SPHERE, CYLINDER,
              CONE, TORUS, PLANE, CIRCLE, MONKEY, EMPTY.
        name: Optional name for the object. Auto-generated if empty.
        location: XYZ position as a 3-element list/tuple. Defaults to origin.
        rotation: XYZ Euler rotation in radians as a 3-element list/tuple.
        scale: XYZ scale as a 3-element list/tuple. Defaults to (1,1,1). Use
            positive values; a negative component on a symmetric primitive is
            applied as the equivalent rotation and noted in the result.

    Returns:
        Dict with the created object's name, type, location, dimensions, and
        world-space bounds (min and max corner). Place the next part from the
        bounds: a nose cone sits at bounds.max z plus half its own height.
    
- **create_polygon_prism** — Create an N-sided regular prism (polygon-based cylinder).

    Useful for hex sockets, octagonal columns, triangular prisms, or any
    straight-sided geometry where a 32-sided round cylinder is the wrong
    primitive. For a hex socket cutter on an M3 button-head screw, use
    sides=6.

    Args:
        sides: Number of sides for the polygon base. Range: 3-64.
        radius: Circumscribed radius (center to vertex). Must be > 0.
        depth: Height of the prism along its Z axis. Must be > 0.
        name: Optional name for the object. Auto-generated if empty.
        location: XYZ position as a 3-element list/tuple. Defaults to origin.
        rotation: XYZ Euler rotation in radians as a 3-element list/tuple.
        scale: XYZ scale as a 3-element list/tuple. Defaults to (1,1,1).

    Returns:
        Dict with the created object's name, type, location, and sides.
    
- **create_threaded_shaft** — Create a cylindrical shaft with helical external threads.

    Produces a single mesh object: a threaded rod at the given diameter and
    length, with helical thread ridges following the specified pitch. Suitable
    for boolean-union onto a screw-head or direct use as a threaded fastener.

    Thread geometry: a 60-degree V profile swept along a Z-axis helix via
    the Screw modifier.

    Args:
        diameter: Major diameter of the shaft (outer thread peaks). Must be > 0.
        length: Axial length of the shaft (under-head length, like real
            fastener spec). Must be > 0.
        pitch: Distance between thread peaks along the axis. Must be > 0 and
            <= length.
        thread_depth: Radial depth of the thread (major radius - minor radius).
            If 0 (default), auto-computed as pitch * 0.54.
        segments: Rotational resolution of the helix (steps per revolution).
            Range: 3-256. Higher = smoother helix, more geometry.
        thread_runout: Smooth (unthreaded) region at the top of the shaft.
            Defaults to 0 (full-length threads), which gives the strongest print
            because threads under the head form a continuous stress path.
            Leaving a smooth runout creates a thin-walled neck at minor_r that
            snaps under torque in FDM prints. Pass a positive value only if
            a head's deep hex socket would otherwise reach thread peaks.
        name: Optional name for the object. Auto-generated if empty.
        location: XYZ position of the shaft base as a 3-element list/tuple.

    Returns:
        Dict with the created object's name, diameter, length, pitch, and the
        number of thread iterations actually generated.
    
- **delete_object** — Delete an object from the scene by name.

    Args:
        object_name: Name of the object to delete.

    Returns:
        Confirmation dict.
    
- **duplicate_object** — Duplicate an object.

    Args:
        object_name: Name of the object to duplicate.
        linked: If True, create a linked duplicate (shares mesh data). Defaults to False.

    Returns:
        Dict with the new object's name.
    
- **rename_object** — Rename an object.

    Args:
        old_name: Current name of the object.
        new_name: New name for the object.

    Returns:
        Dict with old and new names.
    
- **select_objects** — Select whole objects in the scene by name.

    This is object-level selection, the kind that join_objects and
    delete_object act on. To select vertices, edges or faces inside one
    mesh, use select_by_index, select_by_axis or the other select_* tools
    in the Selection group.

    Args:
        names: List of object names to select.
        deselect_others: If True, deselect all other objects first. Defaults to True.

    Returns:
        Dict with list of selected object names.
    
- **get_object_info** — Get detailed information about an object.

    Args:
        object_name: Name of the object.

    Returns:
        Dict with type, location (as set), world_location (where it really
        is after parents, constraints and simulation), rotation, scale,
        dimensions, modifiers, materials, parent, children, and visibility.
    
- **list_objects** — List all objects in the scene, optionally filtered by type.

    Args:
        type_filter: Filter by object type (e.g., MESH, LIGHT, CAMERA, EMPTY).
                     Empty string returns all objects.

    Returns:
        List of dicts with object name, type, and location.
    
- **set_object_visibility** — Set object visibility in viewport and/or render.

    Args:
        object_name: Name of the object.
        visible: Whether the object should be visible.
        viewport: Apply visibility change to viewport. Defaults to True.
        render: Apply visibility change to render. Defaults to True.

    Returns:
        Confirmation dict with visibility state.
    
- **parent_objects** — Set parent-child relationship between two objects.

    Args:
        child: Name of the child object.
        parent: Name of the parent object.

    Returns:
        Confirmation dict.
    
- **join_objects** — Join multiple mesh objects into one (keeps all geometry as-is).

    This merges objects into a single datablock without modifying geometry.
    The meshes remain separate inside the object (no boolean merge).

    TIP: If you want to truly fuse overlapping meshes into one solid shape,
    use booltool_auto_union instead: it performs a boolean union that merges
    the geometry and removes internal faces.

    Args:
        names: List of object names to join. The first name becomes the active object.

    Returns:
        Dict with the resulting object's name, the names that no longer
        exist, and a note saying so.
    
- **convert_object** — Convert an object to a different type.

    Args:
        object_name: Name of the object to convert.
        target: Target type. One of: MESH, CURVE, SURFACE, META, FONT,
                CURVES, POINTCLOUD, GPENCIL.

    Returns:
        Confirmation dict.
    
- **shade_auto_smooth** — Apply angle-based auto-smooth shading to an object.

    Smooths faces only where the angle between adjacent face normals is
    below the given threshold, giving clean results on hard-surface models.

    Args:
        object_name: Name of the mesh object.
        angle: Auto-smooth angle threshold in radians (0.0 to pi). Defaults
               to ~30 degrees (0.523599 rad).

    Returns:
        Confirmation dict.
    
- **make_single_user** — Make an object's data single-user (unlink shared datablocks).

    Args:
        object_name: Name of the object.
        object: Make the object single-user. Defaults to True.
        data: Make the object data (e.g., mesh) single-user. Defaults to True.

    Returns:
        Confirmation dict.
    
- **create_metaball** — Create a metaball: soft elements that melt into one smooth surface.

    Good for organic blobs, liquid drops and quick character blocking. Turn
    it into an editable mesh with convert_object(target="MESH").

    Args:
        name: Object name.
        elements: Up to 500 of {"type": BALL | CAPSULE | ELLIPSOID | CUBE | PLANE,
            "location": [x, y, z] (relative to the object), "radius": influence
            (default 1), "stiffness": 0-10 how firm (default 2), "size": [x, y, z]
            half-extents for the non-BALL types, "negative": true to carve the
            shape away instead}. Elements closer than their radii merge.
            Default: one ball.
        location: Object position, [x, y, z].
        resolution: Surface detail in the viewport, 0.05 (fine) to 2 (coarse).
        threshold: Where the surface sits in the field, 0.01 to 5. Lower is fatter.

    Returns:
        Dict with the object name and element count.
    
- **set_location** — Set the position of an object.

    Args:
        object_name: Name of the object.
        location: XYZ position as a 3-element list/tuple.

    Returns:
        Dict with the object name and new location.
    
- **set_rotation** — Set the rotation of an object.

    Args:
        object_name: Name of the object.
        rotation: Rotation values. For EULER mode, XYZ angles in radians (3 elements).
                  For QUATERNION mode, WXYZ values (4 elements).
        mode: Rotation mode, either EULER or QUATERNION. Defaults to EULER.

    Returns:
        Dict with the object name and new rotation.
    
- **set_scale** — Set the scale of an object.

    Args:
        object_name: Name of the object.
        scale: XYZ scale as a 3-element list/tuple.

    Returns:
        Dict with the object name and new scale.
    
- **apply_transforms** — Apply (freeze) transforms on an object, making current transforms the new basis.

    Args:
        object_name: Name of the object.
        location: Apply location transform. Defaults to True.
        rotation: Apply rotation transform. Defaults to True.
        scale: Apply scale transform. Defaults to True.

    Returns:
        Confirmation dict.
    
- **set_origin** — Set the origin point of an object.

    Args:
        object_name: Name of the object.
        type: Origin type. One of: GEOMETRY (origin to geometry center),
              CURSOR (origin to 3D cursor), CENTER_OF_MASS (origin to center of mass),
              CENTER_OF_VOLUME (origin to center of volume). Defaults to GEOMETRY.

    Returns:
        Confirmation dict with new origin location.
    
- **snap_to_grid** — Snap an object's location to the nearest grid point.

    Args:
        object_name: Name of the object.
        grid_size: Size of the grid cells. Defaults to 1.0.

    Returns:
        Dict with the object name and snapped location.
    
- **add_modifier** — Add a modifier to a mesh object (non-destructive workflow).

    TIP: For BOOLEAN type, consider using booltool_auto_union/difference/intersect/slice
    instead: they apply the boolean immediately and handle cutter cleanup automatically.
    Only use add_modifier with BOOLEAN when you want a non-destructive modifier stack.

    Args:
        object_name: Name of the object to add the modifier to.
        modifier_type: Type of modifier. Must be one of: SUBSURF, MIRROR, ARRAY, BEVEL,
            BOOLEAN, SOLIDIFY, DECIMATE, REMESH, WIREFRAME, SHRINKWRAP, SMOOTH,
            EDGE_SPLIT, TRIANGULATE, WEIGHTED_NORMAL, SIMPLE_DEFORM, LATTICE, CURVE,
            CAST, WAVE, DISPLACE, SCREW, SKIN, MASK, WELD, CORRECTIVE_SMOOTH,
            LAPLACIAN_SMOOTH, SURFACE_DEFORM, MESH_DEFORM, HOOK.
        name: Optional custom name for the modifier.

    Returns:
        Confirmation dict with modifier details.
    
- **remove_modifier** — Remove a modifier from an object.

    Args:
        object_name: Name of the object.
        modifier_name: Name of the modifier to remove.

    Returns:
        Confirmation dict.
    
- **apply_modifier** — Apply a modifier to an object, making its effect permanent.

    Args:
        object_name: Name of the object.
        modifier_name: Name of the modifier to apply.

    Returns:
        Confirmation dict.
    
- **set_modifier_property** — Set a property on a modifier (e.g., levels, count, offset, angle).

    Args:
        object_name: Name of the object.
        modifier_name: Name of the modifier.
        property: The modifier property to set (e.g., 'levels', 'count', 'width',
            'segments', 'angle', 'offset', 'ratio', 'iterations', or an object
            setting such as 'target' or 'object').
        value: The value to set. Object, collection, texture and image settings
            take the name of an existing one.

    Returns:
        Confirmation dict with updated property.
    
- **boolean_operation** — Perform a boolean operation between two objects using a modifier.

    NOTE: For destructive booleans, prefer the booltool_auto_* tools instead
    (booltool_auto_union, booltool_auto_difference, booltool_auto_intersect,
    booltool_auto_slice). They handle selection and cutter cleanup automatically.
    Use this tool only when you need a non-destructive boolean modifier workflow.

    Args:
        object_name: Name of the object to apply the boolean to.
        target_name: Name of the target/cutter object.
        operation: Boolean operation type. One of: UNION, DIFFERENCE, INTERSECT.

    Returns:
        Confirmation dict with operation details.
    
- **subdivide_mesh** — Subdivide a mesh.

    Args:
        object_name: Name of the mesh object to subdivide.
        cuts: Number of cuts per edge. Range: 1-100.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **extrude_faces** — Extrude all faces of a mesh along their normals.

    Args:
        object_name: Name of the mesh object.
        offset: Extrusion distance along face normals.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **bevel_edges** — Bevel all edges of a mesh.

    Args:
        object_name: Name of the mesh object.
        width: Bevel width.
        segments: Number of bevel segments. Range: 1-100.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **loop_cut** — Add loop cuts to a mesh object.

    Args:
        object_name: Name of the mesh object.
        cuts: Number of loop cuts. Range: 1-100.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **set_smooth_shading** — Set smooth or flat shading on an object.

    TIP: For production use, prefer shade_auto_smooth which provides angle-based
    auto-smooth shading: it gives better results on hard-surface models by only
    smoothing faces within the angle threshold.

    Args:
        object_name: Name of the mesh object.
        smooth: True for smooth shading, False for flat shading.

    Returns:
        Confirmation dict.
    
- **merge_vertices** — Merge vertices by distance.

    Args:
        object_name: Name of the mesh object.
        threshold: Maximum distance between vertices to merge. Range: 0.0-10.0.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict with number of removed vertices.
    
- **separate_mesh** — Separate a mesh into parts.

    Args:
        object_name: Name of the mesh object.
        type: Separation method. One of: SELECTED, MATERIAL, LOOSE.


    Returns:
        Confirmation dict.
    
- **bridge_edge_loops** — Bridge two edge loops to create connecting geometry.

    Select two edge loops on a mesh before calling this. The operation creates
    faces connecting the two loops, useful for connecting separate mesh parts,
    creating holes between surfaces, or building tube-like geometry.

    Args:
        object_name: Name of the mesh object with selected edge loops.
        segments: Number of segments in the bridge. Range: 1-1000.
        profile_shape_factor: Shape of the bridge profile. Range: -1.0 to 1.0.
            0.0 is straight, positive values bulge outward, negative inward.

    Returns:
        Confirmation dict with bridge details.
    
- **create_material** — Create an empty material: a bare Principled BSDF at default values.

    Use this only when you will wire the node tree yourself with
    add_shader_node and connect_shader_nodes. For a plain surface with a
    colour, metallic and roughness set in one call, use
    create_principled_material. For wood, marble, fire and other patterned
    surfaces, use create_procedural_material.

    Args:
        name: Name for the new material.

    Returns:
        Confirmation dict with the created material name.
    
- **assign_material** — Assign a material to an object.

    An object with no material, or a single one (like the default cube's
    "Material"), takes the new material on every face. An object that
    already has several materials keeps them and gains an extra slot that
    no face uses yet.

    Args:
        object_name: Name of the target object.
        material_name: Name of the material to assign.

    Returns:
        Dict with the slot used and the action: "assigned", "replaced" (with
        the replaced material's name), "added_slot" or "already_assigned".
    
- **set_material_color** — Set the base color of a material's Principled BSDF node.

    Args:
        material_name: Name of the material.
        color: RGBA color as a list of 4 floats (0.0-1.0). e.g. [1.0, 0.0, 0.0, 1.0] for red.

    Returns:
        Confirmation dict.
    
- **set_material_property** — Set a property on a material's Principled BSDF node.

    Args:
        material_name: Name of the material.
        property: Property to set. One of: metallic, roughness, specular_ior_level,
                  emission_strength, alpha, transmission_weight, ior, coat_weight,
                  coat_roughness, sheen_weight, sheen_roughness, anisotropic,
                  anisotropic_rotation, subsurface_weight, emission_color.
        value: The value to set. Float for most properties, list for color properties.

    Returns:
        Confirmation dict.
    
- **create_principled_material** — Create a plain-surface material with colour, metallic, roughness and more set in one call.

    The usual choice for painted, metal, glass or plastic surfaces of a
    single colour. For a patterned surface (wood, marble, fire, veins) use
    create_procedural_material instead. create_material makes the same
    Principled BSDF with nothing set, for when you will build the node tree
    by hand.

    Args:
        name: Name for the new material.
        color: Base color as RGBA list, default [0.8, 0.8, 0.8, 1.0].
        metallic: Metallic value 0.0-1.0, default 0.0.
        roughness: Roughness value 0.0-1.0, default 0.5.
        specular: Specular IOR level 0.0-1.0, default 0.5.
        emission_strength: Emission strength, default 0.0.
        emission_color: Emission color as RGBA list, default [1.0, 1.0, 1.0, 1.0].
        alpha: Alpha value 0.0-1.0, default 1.0.
        transmission: Transmission weight 0.0-1.0, default 0.0.
        ior: Index of refraction, default 1.45.

    Returns:
        Confirmation dict with material name and all set properties.
    
- **add_texture_node** — Add an image texture node to a material and connect it to the Principled BSDF Base Color.

    Args:
        material_name: Name of the material.
        image_path: Absolute path to the image file. Must exist on disk.
        label: Label for the texture node, default "Image Texture".

    Returns:
        Confirmation dict.
    
- **set_material_blend_mode** — Set the blend mode of a material (EEVEE).

    Args:
        material_name: Name of the material.
        mode: Blend mode. One of: OPAQUE, CLIP, HASHED, BLEND.

    Returns:
        Confirmation dict.
    
- **list_materials** — List all materials in the current Blender file.

    Returns:
        List of dicts with material name and user count.
    
- **delete_material** — Delete a material by name.

    Args:
        material_name: Name of the material to delete.

    Returns:
        Confirmation dict.
    
- **duplicate_material** — Duplicate a material with a new name.

    Args:
        material_name: Name of the material to duplicate.
        new_name: Name for the duplicated material.

    Returns:
        Confirmation dict with the new material name.
    
- **add_shader_node** — Add a shader node to a material's node tree.

    Args:
        material_name: Name of the material.
        node_type: Blender shader node type (e.g. ShaderNodeBsdfPrincipled).
        location: Node location as [x, y], default [0, 0].

    Returns:
        Dict with material, node_name, and node_type.
    
- **connect_shader_nodes** — Connect two shader nodes in a material's node tree.

    Args:
        material_name: Name of the material.
        from_node: Name of the source node.
        from_socket: Name of the output socket on the source node.
        to_node: Name of the destination node.
        to_socket: Name of the input socket on the destination node.

    Returns:
        Confirmation dict.
    
- **disconnect_shader_nodes** — Disconnect all links from a specific socket on a shader node.

    Args:
        material_name: Name of the material.
        node_name: Name of the node.
        socket_name: Name of the socket to disconnect.
        is_input: If True, disconnect an input socket; otherwise an output socket.

    Returns:
        Confirmation dict.
    
- **remove_shader_node** — Remove a shader node from a material's node tree.

    Args:
        material_name: Name of the material.
        node_name: Name of the node to remove.

    Returns:
        Confirmation dict.
    
- **get_node_tree** — Get the full node tree of a material (all nodes and links).

    Args:
        material_name: Name of the material.

    Returns:
        Dict with nodes (name, type, location, input and output names, the
        values of unlinked inputs, and the node's own settings) and links.
    
- **set_shader_node_input** — Set the default value of an unconnected input socket on a shader node.

    This is how you dial in a procedural texture: Noise 'Scale' and 'Detail',
    Mapping 'Scale' and 'Rotation', a Principled BSDF 'Roughness', and so on.
    A socket that has a link into it ignores its default value, so disconnect
    it first if you want the default to take effect.

    Args:
        material_name: Name of the material.
        node_name: Name of the node.
        socket: Socket name, or a zero-based index. Use the index when names
            are ambiguous: a Math node has two inputs both called 'Value'.
        value: A number, a boolean, or a 2-4 component list for vectors and
            colors (colors are RGBA).

    Returns:
        Dict with the node, socket, and the value that was applied.
    
- **set_shader_node_property** — Set a node-level property (not a socket) on a shader node.

    These are the dropdowns and checkboxes on the node body rather than its
    input sockets: Math 'operation', Mix 'blend_type', Voronoi 'feature'
    (use 'DISTANCE_TO_EDGE' for vein and crack patterns), Wave 'wave_type'
    and 'bands_direction', Noise 'noise_dimensions'.

    Args:
        material_name: Name of the material.
        node_name: Name of the node.
        property: Property name. Must be one of the allowed node properties.
        value: String enum identifier, number, or boolean.

    Returns:
        Dict with the node, property, and the value that was applied.
    
- **add_color_ramp_element** — Add a colour stop to a ColorRamp (ShaderNodeValToRGB) node.

    A new ramp starts with two stops, black at 0.0 and white at 1.0. Add
    stops to shape a gradient: fire needs dark red, orange, yellow, white
    bunched toward the top; rust needs a hard break between metal and oxide.

    Args:
        material_name: Name of the material.
        node_name: Name of the ColorRamp node.
        position: Stop position along the ramp, 0.0 to 1.0.
        color: RGB or RGBA color, components 0.0 to 1.0. RGB gains alpha 1.0.

    Returns:
        Dict with the new element's index, position, and color.
    
- **remove_color_ramp_element** — Remove a colour stop from a ColorRamp node.

    Blender requires at least one stop to remain; removing the last one fails.

    Args:
        material_name: Name of the material.
        node_name: Name of the ColorRamp node.
        index: Zero-based index of the stop to remove.

    Returns:
        Dict with the removed index and the remaining element count.
    
- **set_color_ramp_element** — Move or recolor an existing ColorRamp stop.

    At least one of position or color must be given. Moving a stop past a
    neighbour reorders the ramp, so indices may shift after this call. Read
    the ramp back with get_color_ramp if you need certainty.

    Args:
        material_name: Name of the material.
        node_name: Name of the ColorRamp node.
        index: Zero-based index of the stop to edit.
        position: New position, 0.0 to 1.0. Omit to leave unchanged.
        color: New RGB or RGBA color. Omit to leave unchanged.

    Returns:
        Dict with the element's resulting position and color.
    
- **set_color_ramp_interpolation** — Set how a ColorRamp blends between its stops.

    'CONSTANT' gives hard-edged bands with no blending, which is what turns a
    noise or voronoi texture into discrete regions: scale plates, cracked mud,
    stylised cel shading. 'EASE' and 'B_SPLINE' give softer falloff than
    'LINEAR'. Set color_mode to 'HSV' to sweep through hues between two stops
    rather than blending through grey.

    Args:
        material_name: Name of the material.
        node_name: Name of the ColorRamp node.
        interpolation: One of EASE, CARDINAL, LINEAR, B_SPLINE, CONSTANT.
        color_mode: Optional. One of RGB, HSV, HSL. Omit to leave unchanged.

    Returns:
        Dict with the applied interpolation and color mode.
    
- **get_color_ramp** — Read every stop on a ColorRamp node.

    Use this before editing to learn the current indices and positions, since
    add and move operations reorder stops.

    Args:
        material_name: Name of the material.
        node_name: Name of the ColorRamp node.

    Returns:
        Dict with elements (index, position, color), interpolation, color_mode.
    
- **create_procedural_material** — Create a patterned material (wood, marble, fire, veins) as a full node graph in one call.

    For a single flat colour use create_principled_material instead; for an
    empty material you will wire by hand use create_material.

    Prefer this over hand-wiring texture nodes. It creates the full graph (
    coordinates, mapping, the pattern's texture nodes, a tuned colour ramp,
    and the Principled BSDF) and returns the node names so you can adjust
    anything afterwards with set_shader_node_input or the colour ramp tools.

    Procedural beats image textures here: no files, no UV unwrap needed, and
    it stays sharp at any camera distance.

    Call list_procedural_patterns() to see what each pattern looks like.

    Args:
        name: Name for the new material.
        pattern: One of the supported patterns, e.g. 'fire', 'wood', 'veins'.
        scale: Feature size. Lower is bigger and broader, higher is finer and
            busier. 5.0 is a sensible default; try 1-3 for large forms and
            20+ for fine detail.
        detail: Fractal octaves, 0-15. Higher adds finer sub-detail at the
            cost of render time. Applies to noise, cloud, wood, marble,
            plasma and fire. The cellular patterns (voronoi, veins, scales,
            sparks), stripes, weave and gradient have no detail socket and
            ignore it.
        distortion: Warps the pattern. Small values (0.5-2.0) make wood and
            marble look organic rather than machine-perfect. Applies to
            noise, cloud, stripes, wood, marble, plasma and fire. The
            cellular patterns, weave and gradient ignore it.
        roughness: Surface roughness 0-1 for the Principled BSDF.
        metallic: Metallic 0-1 for the Principled BSDF.
        colors: Optional list of RGB or RGBA colours for the ramp, in order.
            Omit to use the pattern's own tuned palette.
        banded: Use CONSTANT ramp interpolation, giving hard-edged bands
            instead of smooth blending. Turns noise into discrete regions:
            scale plates, cracked mud, cel shading.
        connect_to_bsdf: Wire the result into the Principled BSDF base colour
            so the material renders immediately. Set False to leave the
            pattern subtree unconnected for manual wiring.

    Returns:
        Dict with the material name, the created node names, and
        ignored_params listing any arguments this pattern could not use.
    
- **create_raster_texture** — Generate an image texture for patterns shader nodes cannot express.

    Use this only for patterns that place discrete marks. Shader nodes
    evaluate a function per point and have no way to say "draw a glyph here,
    then another over there", so runes need real pixels. Everything else
    should go through create_procedural_material, which stays sharp at any
    resolution.

    The image is packed into the blend file. No file is written to disk.

    Args:
        name: Name for the generated image datablock.
        pattern: A raster pattern. Currently 'runes'.
        size: Pixel width and height, up to 2048. Cost grows with the square.
        count: How many marks to stamp. 0 leaves a blank field.
        seed: Change for a different arrangement; the same seed always
            reproduces the same image.
        foreground: RGB or RGBA colour of the marks.
        background: RGB or RGBA colour behind them.

    Returns:
        Dict with the image name, size, and mark count.
    
- **list_procedural_patterns** — List every procedural pattern with a description of what it looks like.

    Read this before calling create_procedural_material so you pick a pattern
    that matches the surface you are trying to make.

    Returns:
        Dict with the sorted pattern names and a description of each.
    
- **create_light** — Create a new light in the scene.

    Args:
        type: Light type. One of: POINT, SUN, SPOT, AREA.
        name: Optional name for the light.
        location: XYZ location as [x, y, z], default [0, 0, 0].
        energy: Light energy/power, default 1000.
        color: RGB color as [r, g, b], default [1.0, 1.0, 1.0].

    Returns:
        Confirmation dict with light name and properties.
    
- **set_light_property** — Set a property on a light object.

    Args:
        object_name: Name of the light object.
        property: Property to set. One of: energy, color, shadow_soft_size, spot_size,
                  spot_blend, area_size, area_size_y, use_shadow, angle,
                  specular_factor, diffuse_factor, volume_factor.
        value: The value to set. Type depends on the property.

    Returns:
        Confirmation dict.
    
- **set_world_background** — Set the world background to a solid colour or an HDRI environment.

    An HDRI lights the whole scene and gives metal and glass something to
    reflect; without one, metals look dull. Give exactly one of color,
    hdri_path or builtin_hdri.

    Args:
        color: RGB colour [r, g, b] for a plain background.
        hdri_path: Absolute path to an HDRI image (.hdr, .exr, ...).
        builtin_hdri: One of the HDRIs that ship with Blender: city,
            courtyard, forest, interior, night, studio, sunrise, sunset.
        strength: Background strength, 0 to 1000, default 1.0.
        rotation: HDRI turn around the vertical axis in radians, to move
            where the light comes from. -6.283 to 6.283.

    Returns:
        Confirmation dict.
    
- **set_world_sky** — Light the scene with a physically based procedural sky and sun.

    Realistic daylight for any time of day with no image file. Low sun
    elevation gives golden hour; negative gives dusk. Pair with AgX colour
    management (set_color_management) for natural results.

    Args:
        sky_type: MULTIPLE_SCATTERING (most realistic, new in 5.0),
            SINGLE_SCATTERING, PREETHAM or HOSEK_WILKIE.
        sun_elevation: Sun height above the horizon in radians, -1.571 to
            1.571. 0.26 (15 degrees) is mid-morning; 0.05 golden hour.
        sun_rotation: Sun direction around the vertical axis in radians.
        sun_intensity: Sun brightness multiplier, 0 to 1000.
        sun_disc: Show the sun itself in the sky.
        altitude: Viewer height in metres, 0 to 100000.
        air_density: Air molecules, 0 to 10. Higher is bluer.
        aerosol_density: Dust and haze, 0 to 10. Higher is hazier and warmer.
        ozone_density: Ozone, 0 to 10. Affects the blue at dusk.
        strength: Overall sky brightness, 0 to 1000.

    Returns:
        Dict with the sky settings applied.
    
- **create_light_rig** — Create a pre-built lighting rig (multiple lights arranged for common setups).

    Args:
        type: Rig type. One of: THREE_POINT, STUDIO, RIM, OUTDOOR.
        target: Optional name of the object the rig should point at.
        intensity: Overall intensity of the lights, default 1000.

    Returns:
        Confirmation dict with names of all created lights.
    
- **list_lights** — List all light objects in the scene.

    Returns:
        List of dicts with light name, type, energy, color, and location.
    
- **delete_light** — Delete a light object from the scene.

    Args:
        object_name: Name of the light object to delete.

    Returns:
        Confirmation dict.
    
- **set_shadow_settings** — Configure shadow settings for a light.

    Args:
        object_name: Name of the light object.
        use_shadow: Whether to enable shadows, default True.
        shadow_soft_size: Soft shadow radius, default 0.25.

    Returns:
        Confirmation dict.
    
- **set_light_linking** — Limit which objects a light lights, or which objects block its shadows.

    Classic uses: a rim light that touches only the hero, or a fill light
    that skips the background. Replaces the light's list each call; an
    empty list removes the link so the light affects everything again.

    Args:
        light_name: The light (or emissive object).
        objects: Objects in the link list, at most 1000.
        role: RECEIVERS (objects the light lights) or BLOCKERS (objects that
            cast its shadows).
        mode: INCLUDE (only these) or EXCLUDE (everything except these).

    Returns:
        Dict with the light, the link collection and its objects.
    
- **create_camera** — Create a new camera in the scene.

    Args:
        name: Name for the camera, default "Camera".
        location: XYZ location as [x, y, z], default [0, 0, 0].
        rotation: XYZ Euler rotation in radians as [x, y, z], default [0, 0, 0].
        lens: Focal length in mm, default 50.

    Returns:
        Confirmation dict with camera name and properties.
    
- **set_camera_property** — Set a property on a camera.

    Args:
        object_name: Name of the camera object.
        property: Property to set. One of: lens, clip_start, clip_end, sensor_width,
                  sensor_height, dof.use_dof, dof.focus_distance, dof.aperture_fstop,
                  ortho_scale, shift_x, shift_y, type, sensor_fit.
        value: The value to set.

    Returns:
        Confirmation dict.
    
- **set_active_camera** — Set the active scene camera.

    Args:
        object_name: Name of the camera object to make active.

    Returns:
        Confirmation dict.
    
- **point_camera_at** — Point a camera at an object or a specific location using a Track To constraint.

    Args:
        camera_name: Name of the camera object.
        target: Name of an existing object to point at, as a string. For
            coordinates use `location` instead. Mutually exclusive with location.
        location: XYZ location to point at as [x, y, z]. Mutually exclusive with target.

    Returns:
        Confirmation dict.
    
- **capture_viewport** — Render the viewport to a file or return as base64.

    Args:
        filepath: Optional absolute path for output image. If empty, returns base64-encoded image.
        width: Render width in pixels, default 1920.
        height: Render height in pixels, default 1080.

    Returns:
        Dict with filepath or base64 image data.
    
- **set_camera_from_view** — Match the active camera to the current 3D viewport view.

    Returns:
        Confirmation dict with the camera's new location and rotation.
    
- **insert_keyframe** — Insert a keyframe on an object property at a specific frame.

    Args:
        object_name: Name of the object.
        data_path: Property to keyframe. Must be one of: location, rotation_euler,
            rotation_quaternion, scale, or indexed variants like location[0].
        frame: Frame number to insert the keyframe at.
        value: Optional value to set before inserting the keyframe: a number
            for an indexed path like location[2], a list for a whole vector.

    Returns:
        Confirmation dict with keyframe details.
    
- **delete_keyframe** — Remove a keyframe from an object property at a specific frame.

    Args:
        object_name: Name of the object.
        data_path: Property data path (e.g., location, rotation_euler, scale).
        frame: Frame number of the keyframe to remove.

    Returns:
        Confirmation dict.
    
- **set_frame** — Set the current frame in the timeline.

    Args:
        frame: Frame number to set as current.

    Returns:
        Confirmation dict with the new current frame.
    
- **set_frame_range** — Set the start and end frames of the scene timeline.

    Args:
        start: Start frame number.
        end: End frame number. Must be greater than start.

    Returns:
        Confirmation dict with the new frame range.
    
- **set_interpolation** — Set the interpolation type for keyframes on a property.

    Args:
        object_name: Name of the object.
        data_path: Property data path.
        interpolation: Interpolation type. One of: CONSTANT, LINEAR, BEZIER, SINE,
            QUAD, CUBIC, QUART, QUINT, EXPO, CIRC, BACK, BOUNCE, ELASTIC.

    Returns:
        Confirmation dict.
    
- **create_animation_path** — Make an object follow a path (curve) using a Follow Path constraint.

    Args:
        object_name: Name of the object to animate along the path.
        path_object: Name of the curve object to use as the path.

    Returns:
        Confirmation dict with constraint details.
    
- **list_keyframes** — List all keyframes on an object.

    Args:
        object_name: Name of the object.

    Returns:
        List of dicts with data_path, frame, and value for each keyframe.
    
- **clear_animation** — Remove all animation data from an object.

    Args:
        object_name: Name of the object.

    Returns:
        Confirmation dict.
    
- **add_driver** — Drive a property from other properties or the frame: a door that opens
    as a handle turns, a wheel that spins as a car moves, a light that dims
    with distance.

    Expressions use Blender's simple subset, evaluated without Python:
    numbers, + - * / % //, comparisons, and/or/not, "a if c else b",
    parentheses, the variables below, frame, pi, and sin cos tan asin acos
    atan atan2 sqrt abs fabs floor ceil trunc round int min max radians
    degrees exp log pow fmod lerp clamp smoothstep. No ** (use pow).

    Args:
        object_name: Object that owns the driven property.
        data_path: Property to drive, e.g. "location", "rotation_euler",
            "data.energy" (a light's power), 'modifiers["Bend"].angle',
            'data.shape_keys.key_blocks["Smile"].value'. Paths into the
            object's data or shape keys are driven on that data.
        expression: SCRIPTED drivers only, e.g. "lx * 2" or "sin(frame / 10)".
        index: Component of a vector property (0, 1, 2 for X, Y, Z), or -1 for
            a single value.
        driver_type: SCRIPTED (use the expression), or AVERAGE, SUM, MIN, MAX
            of the variables.
        variables: Up to 32, each {"name", "type", "object", ...}:
            TRANSFORMS: "transform_type" LOC_X..SCALE_AVG, optional
                "transform_space" WORLD_SPACE (default), LOCAL_SPACE or
                TRANSFORM_SPACE.
            SINGLE_PROP: "data_path" on the object, e.g. "data.energy".
            LOC_DIFF / ROTATION_DIFF: distance or angle between "object" and
                "object_2".

    Returns:
        Dict with the driven path, index, expression and variables.
    
- **remove_driver** — Remove a driver so the property goes back to its own value.

    Args:
        object_name: Object that owns the driven property.
        data_path: The driven property, as given to add_driver.
        index: Component, or -1 for all components of the property.

    Returns:
        Dict with how many drivers were removed.
    
- **list_drivers** — List the drivers on an object with their expressions and variables.

    Args:
        object_name: Object to inspect.

    Returns:
        Dict with each driver's path, index, type, expression, variables and
        whether Blender considers it valid.
    
- **keyframe_property** — Keyframe any animatable property: material colours, light power, world
    strength, modifier settings, camera lens and more.

    Optionally sets the value first, so "turn red at frame 24" is one call.
    For location, rotation and scale, insert_keyframe is simpler.

    Args:
        data_path: Property path from the target, e.g.
            'active_material.node_tree.nodes["Principled BSDF"].inputs["Base Color"].default_value',
            "data.energy" (light power), "data.lens" (camera),
            'modifiers["Bend"].angle',
            'node_tree.nodes["Background"].inputs["Strength"].default_value'
            (with target WORLD).
        frame: Frame to key.
        value: Value to set before keying: a number, true/false, or a list for
            colours and vectors. Omit to key the current value.
        object_name: The object the path starts from (target OBJECT).
        target: OBJECT, WORLD (the scene's world) or SCENE.
        index: One component of a vector or colour (0, 1, 2, 3), or -1 for all.

    Returns:
        Dict with the data block keyed, its path, the frame and the value.
    
- **manage_action** — Work with an object's actions (its saved animations).

    Args:
        object_name: Animated object.
        operation: LIST (the file's actions and which one the object plays),
            NEW (start an empty action named action_name and assign it),
            ASSIGN (play an existing action; several objects can share one),
            UNASSIGN (stop playing the active action, keep it in the file),
            PUSH_DOWN (move the active action into an NLA strip so another
            action can be layered on top).
        action_name: Needed for NEW and ASSIGN.

    Returns:
        Dict with the object's active action and slot, and the file's actions.
    
- **add_nla_strip** — Place an action on the NLA timeline as a strip: repeat a walk cycle,
    sequence clips, or layer a wave on top of a walk.

    Args:
        object_name: Object to animate.
        action_name: Action to place.
        frame_start: Frame the strip starts.
        track_name: NLA track to put it on; created if missing. Empty adds a
            new track on top.
        blend_type: How it mixes with the tracks below: REPLACE, COMBINE
            (adds rotations properly, best for layering), ADD, SUBTRACT,
            MULTIPLY.
        repeat: Times to play the action, 0.1 to 1000.
        scale: Playback stretch, 0.01 to 100 (2 is half speed).
        extrapolation: After (and before) the strip: NOTHING, HOLD or
            HOLD_FORWARD.
        blend_in: Frames to fade in, 0 or more.
        blend_out: Frames to fade out, 0 or more.
        influence: Fixed strength 0.0 to 1.0; leave unset for full.

    Returns:
        Dict with the track, strip, and its frame range.
    
- **list_nla** — List an object's NLA tracks and strips, top to bottom.

    Args:
        object_name: Animated object.

    Returns:
        Dict with each track and its strips (action, frames, blend, repeat).
    
- **add_fcurve_modifier** — Add a modifier to animation curves of the object's active action.

    Args:
        object_name: Animated object.
        data_path: Animated property, e.g. "location", "rotation_euler".
        modifier: CYCLES (repeat the keys forever: settings mode_before /
            mode_after REPEAT, REPEAT_OFFSET for walking forward, MIRROR),
            NOISE (organic jitter: strength, scale, phase, offset, depth),
            STEPPED (stop-motion look: frame_step, frame_offset),
            SMOOTH (Gaussian smoothing: sigma, filter_width).
        index: One component (0, 1, 2) or -1 for every component.
        settings: Modifier settings by name, plain values.

    Returns:
        Dict with how many curves got the modifier.
    
- **set_render_engine** — Set the render engine.

    Args:
        engine: Render engine to use. One of: BLENDER_EEVEE, CYCLES, BLENDER_WORKBENCH.

    Returns:
        Confirmation dict with the active render engine.
    
- **set_render_resolution** — Set the render resolution.

    Args:
        width: Render width in pixels. Range: 1-8192.
        height: Render height in pixels. Range: 1-8192.
        percentage: Resolution percentage scale. Range: 1-100.

    Returns:
        Confirmation dict with the new resolution settings.
    
- **set_render_samples** — Set the number of render samples.

    Args:
        samples: Number of samples. Range: 1-10000.

    Returns:
        Confirmation dict with the new sample count.
    
- **set_output_format** — Set the render output format and optionally the output file path.

    Args:
        format: Output format. One of: PNG, JPEG, OPEN_EXR, TIFF, BMP.
        filepath: Optional output file path. Must be an absolute path.

    Returns:
        Confirmation dict with the new output settings.
    
- **render_image** — Render the current scene to an image file.

    Args:
        filepath: Output file path for the rendered image. Must be an absolute path
            with a valid image extension (.png, .jpg, .exr, .tiff, .bmp) in a
            directory that exists. Empty means render.png in the system temp
            directory.

    Returns:
        Confirmation dict with the output file path.
    
- **render_animation** — Render the animation sequence to image files.

    Args:
        filepath: Output file path prefix for the rendered frames. Each frame will be
            saved with a frame number suffix. The directory must exist. Empty
            means render_ in the system temp directory.
        format: Output format. One of: PNG, JPEG, OPEN_EXR, TIFF, BMP.

    Returns:
        Confirmation dict with output details.
    
- **set_eevee_light_path** — Set EEVEE light intensity controls (Blender 5.1+).

    Scales how strongly direct and indirect lighting contribute. Only applies
    when the render engine is EEVEE.

    Args:
        direct_intensity: Multiplier for light arriving straight from a lamp.
            Range 0.0-10.0, 1.0 is unchanged. Leave unset to keep the current
            value.
        indirect_intensity: Multiplier for bounced light. Range 0.0-10.0, 1.0
            is unchanged. Leave unset to keep the current value.

    Returns:
        Dict with both intensities after the change.
    
- **create_curve** — Create a new curve object.

    Args:
        type: Curve type - BEZIER, NURBS, or PATH.
        name: Optional name for the curve object.
        location: 3D location as (x, y, z).

    Returns:
        Dict with created curve name and type.
    
- **add_curve_point** — Add a control point to an existing curve.

    Args:
        curve_name: Name of the curve object to add a point to.
        location: 3D location for the new point as (x, y, z).
        handle_type: Handle type - AUTO, VECTOR, ALIGNED, or FREE.

    Returns:
        Dict with curve name and new point count.
    
- **set_curve_property** — Set a property on a curve object.

    Args:
        curve_name: Name of the curve object.
        property: Property to set - resolution_u, fill_mode, bevel_depth,
                  bevel_resolution, extrude, twist_mode, or use_fill_caps.
        value: Value to set. Type depends on property.

    Returns:
        Confirmation dict with property name and new value.
    
- **convert_curve_to_mesh** — Convert a curve object to a mesh object.

    Args:
        curve_name: Name of the curve object to convert.

    Returns:
        Dict with the converted object name.
    
- **create_text** — Create a 3D text object.

    Args:
        text: The text string to display.
        name: Optional name for the text object.
        location: 3D location as (x, y, z).
        size: Font size.
        font: Optional path to a font file. Uses default Blender font if empty.

    Returns:
        Dict with created text object name.
    
- **switch_curve_direction** — Switch the direction of a curve's splines.

    Args:
        curve_name: Name of the curve object.

    Returns:
        Dict with confirmation of direction switch.
    
- **set_handle_type** — Set the handle type for all control points of a curve.

    Args:
        curve_name: Name of the curve object.
        handle_type: Handle type - AUTO, VECTOR, ALIGNED, or FREE_ALIGN.

    Returns:
        Dict with confirmation of handle type change.
    
- **toggle_cyclic** — Toggle the cyclic (closed loop) state of a curve.

    Args:
        curve_name: Name of the curve object.

    Returns:
        Dict with confirmation of cyclic toggle.
    
- **subdivide_curve** — Subdivide a curve by adding control points between existing ones.

    Args:
        curve_name: Name of the curve object.
        number_cuts: Number of cuts to make (1-100).

    Returns:
        Dict with confirmation of subdivision.
    
- **smooth_curve** — Smooth the control points of a curve.

    Args:
        curve_name: Name of the curve object.

    Returns:
        Dict with confirmation of smoothing.
    
- **enter_sculpt_mode** — Enter sculpt mode for a mesh object.

    Args:
        object_name: Name of the mesh object to sculpt.

    Returns:
        Confirmation dict with object name and mode.
    
- **exit_sculpt_mode** — Exit sculpt mode and return to object mode.

    Returns:
        Confirmation dict with current mode.
    
- **set_sculpt_brush** — Set the active sculpt brush.

    Args:
        brush_type: Brush type - DRAW, CLAY, CLAY_STRIPS, INFLATE, GRAB, SMOOTH,
                    FLATTEN, FILL, SCRAPE, PINCH, CREASE, BLOB, MASK,
                    MULTIRES_DISPLACEMENT_SMEAR.

    Returns:
        Confirmation dict with active brush type.
    
- **set_brush_property** — Set a property on the active sculpt brush.

    Args:
        property: Property to set - size, strength, auto_smooth_factor, or use_frontface.
        value: Value to set. size is int (1-500), strength is float (0.0-1.0),
               auto_smooth_factor is float (0.0-1.0), use_frontface is bool.

    Returns:
        Confirmation dict with property name and new value.
    
- **remesh** — Remesh an object to create a clean topology.

    Args:
        object_name: Name of the mesh object to remesh.
        voxel_size: Voxel size for remeshing (smaller = more detail). Only used in VOXEL mode.
        mode: Remesh mode - VOXEL, SHARP, SMOOTH, or BLOCKS.

    Returns:
        Dict with object name and new vertex count.
    
- **add_multires_modifier** — Add a Multiresolution modifier for sculpting detail.

    Args:
        object_name: Name of the mesh object.
        levels: Number of subdivision levels to add (1-6).

    Returns:
        Dict with object name and modifier info.
    
- **set_sculpt_symmetry** — Set sculpt symmetry axes.

    Enables symmetrical sculpting across the specified axes. X-axis symmetry
    is the most common for character modeling.

    Args:
        use_x: Enable X-axis symmetry. Defaults to True.
        use_y: Enable Y-axis symmetry. Defaults to False.
        use_z: Enable Z-axis symmetry. Defaults to False.

    Returns:
        Confirmation dict with symmetry settings.
    
- **enable_dyntopo** — Enable dynamic topology (dyntopo) for adaptive sculpting resolution.

    Dyntopo adds and removes mesh detail dynamically as you sculpt,
    allowing unlimited detail where needed without uniform subdivision.

    Args:
        object_name: Name of the mesh object (must be in sculpt mode or will enter it).
        detail_size: Detail level (smaller = more detail). Range: 0.1-500.0.
        detail_mode: Detail mode. One of: RELATIVE, CONSTANT, BRUSH, MANUAL.

    Returns:
        Confirmation dict with dyntopo settings.
    
- **set_sculpt_mask** — Mask part of a mesh so sculpt brushes and filters leave it alone.

    1.0 is fully protected, 0.0 is free to sculpt. Works in any mode.

    Args:
        object_name: Mesh object.
        value: Mask strength, 0.0 to 1.0.
        vertex_indices: Vertices to set; the rest keep their mask. Omit (and
            vertex_group) to set the whole mesh.
        vertex_group: Mask from a vertex group: each member gets value times
            its weight, other vertices are unmasked.
        invert: Flip the current mask (other arguments ignored).
        clear: Remove the mask entirely.

    Returns:
        Dict with how many vertices are masked (above 0) and the vertex count.
    
- **set_face_sets** — Split a mesh into face sets: colored regions for sculpting one part at a time.

    In sculpt mode, face sets can be hidden or isolated, and brushes and
    automasking can stay within one set.

    Args:
        object_name: Mesh object.
        mode: LOOSE_PARTS (one set per separate piece), MATERIALS (one set per
            material slot), ASSIGN (face_indices into face_set), CLEAR.
        face_indices: ASSIGN only: the faces to change.
        face_set: ASSIGN only: set number, 1 or more.

    Returns:
        Dict with the number of distinct face sets.
    
- **smart_uv_project** — Apply Smart UV Project to a mesh object.

    Automatically unwraps the mesh using angle-based projection.

    Args:
        object_name: Name of the mesh object.
        angle_limit: Angle limit in degrees for splitting faces (0.0-89.0).
        island_margin: Margin between UV islands (0.0-1.0).
        area_weight: Weight given to face area for island arrangement (0.0-1.0).

    Returns:
        Confirmation dict with object name and UV map info.
    
- **uv_unwrap** — Unwrap a mesh object's UVs using standard unwrap.

    Requires seams to be marked for best results.

    Args:
        object_name: Name of the mesh object.
        method: Unwrap method - ANGLE_BASED, CONFORMAL, or MINIMUM_STRETCH
            (the SLIM unwrapper; least distortion, slower).

    Returns:
        Confirmation dict with object name.
    
- **set_uv_projection** — Apply a projection-based UV mapping to a mesh object.

    Args:
        object_name: Name of the mesh object.
        projection: Projection type - CUBE, CYLINDER, or SPHERE.

    Returns:
        Confirmation dict with object name and projection type.
    
- **pack_uv_islands** — Pack UV islands to fit efficiently within the UV space.

    Args:
        object_name: Name of the mesh object.
        margin: Margin between packed islands (0.0-1.0).
        rotate: Allow islands to rotate for a tighter fit.
        rotate_method: ANY, CARDINAL (90 degree steps), AXIS_ALIGNED,
            AXIS_ALIGNED_X or AXIS_ALIGNED_Y.
        scale: Scale islands to fill the space. Turn off after
            set_texel_density, or the pack undoes the density.

    Returns:
        Confirmation dict with object name.
    
- **uv_island_operation** — Tidy UV islands after unwrapping.

    Args:
        object_name: Mesh object with a UV map.
        operation: One of:
            AVERAGE_SCALE (give every island the same texel size relative to
                its 3D area, so textures don't look blurrier on some parts),
            MINIMIZE_STRETCH (relax UVs to reduce distortion: iterations),
            ALIGN_ROTATION (turn islands to line up with the axes),
            RANDOMIZE (jitter islands so tiled textures don't repeat
                visibly: rotation in radians, scale_variation, offset, seed),
            SEAMS_FROM_ISLANDS (mark seams along the current island borders),
            ARRANGE (lay islands out in rows, new in 5.0: margin),
            WELD (merge UV points closer than threshold).
        selection: "ALL" for the whole mesh, or "CURRENT" for the faces
            already selected.
        iterations: MINIMIZE_STRETCH passes, 1 to 1000.
        rotation: RANDOMIZE maximum rotation, 0 to 6.283 radians.
        scale_variation: RANDOMIZE scale range, 0.0 to 1.0.
        offset: RANDOMIZE maximum position change, 0.0 to 1.0.
        seed: RANDOMIZE seed, 0 or more.
        margin: ARRANGE spacing, 0.0 to 1.0.
        threshold: WELD distance, 0.0 to 1.0.

    Returns:
        Dict with the operation and the object.
    
- **manage_uv_map** — List, add, remove, rename UV maps, or choose which one is edited or rendered.

    A mesh holds up to 8 UV maps. Common use: ADD a "Lightmap" map, then
    smart_uv_project or pack_uv_islands on it for non-overlapping bake UVs,
    while textures keep using the first map. UV tools work on the active map;
    materials and export use the render map unless a UV Map node picks one.

    Args:
        object_name: Mesh object.
        action: LIST, ADD (becomes the active map), REMOVE, SET_ACTIVE (the
            map UV tools edit), SET_RENDER (the map renders and exports), RENAME.
        uv_map: The map to act on, or the new map's name for ADD.
        new_name: RENAME only: the new name.
        copy_active: ADD only: start from a copy of the active map's UVs
            instead of blank ones.

    Returns:
        Dict with every UV map (name, active, render).
    
- **get_texel_density** — Measure texel density: how many texture pixels cover one metre of surface.

    Matching density across assets keeps texture sharpness consistent; game
    art often targets 512 or 1024 px/m.

    Args:
        object_name: Mesh object with a UV map.
        texture_size: Texture width in pixels the UVs are meant for.

    Returns:
        Dict with density in px/m, surface area in m^2 (world scale), and the
        share of UV space used.
    
- **set_texel_density** — Scale an object's UVs to hit a target texel density.

    Islands keep their layout and scale about their shared centre, so they
    may spill outside the 0-1 square; pack afterwards with
    pack_uv_islands(scale=False) to bring them back without undoing this.

    Args:
        object_name: Mesh object with a UV map.
        density: Target pixels per metre, above 0 and up to 100000.
        texture_size: Texture width in pixels the UVs are meant for.

    Returns:
        Dict with the density before and after.
    
- **create_armature** — Create a new armature object.

    Args:
        name: Name for the armature. Defaults to "Armature".
        location: XYZ position for the armature. Defaults to origin.

    Returns:
        Dict with the created armature's name and location.
    
- **add_bone** — Add a bone to an armature. Enters edit mode automatically.

    Args:
        armature_name: Name of the armature object.
        bone_name: Name for the new bone.
        head: XYZ position of the bone head (root). Defaults to (0, 0, 0).
        tail: XYZ position of the bone tail (tip). Defaults to (0, 0, 1).
        parent_bone: Optional name of the parent bone for hierarchy.

    Returns:
        Dict with the created bone's name, head, and tail positions.
    
- **set_bone_property** — Set a property on a bone in an armature.

    Args:
        armature_name: Name of the armature object.
        bone_name: Name of the bone.
        property: Property to set. One of: roll, length, use_connect, use_deform,
                  envelope_distance, head_radius, tail_radius, use_inherit_rotation,
                  use_local_location.
        value: Value to set the property to.

    Returns:
        Confirmation dict with bone name, property, and new value.
    
- **add_constraint** — Add a constraint to an object or bone.

    Args:
        object_name: Name of the object (armature for bone constraints).
        bone_name: Name of the bone (empty string for object-level constraints).
        constraint_type: Constraint type. One of: IK, COPY_ROTATION, COPY_LOCATION,
                        COPY_SCALE, COPY_TRANSFORMS, TRACK_TO, DAMPED_TRACK,
                        LOCKED_TRACK, LIMIT_ROTATION, LIMIT_LOCATION, LIMIT_SCALE,
                        STRETCH_TO, FLOOR, CLAMP_TO, TRANSFORM, MAINTAIN_VOLUME,
                        CHILD_OF, PIVOT, ARMATURE, LIMIT_DISTANCE, SPLINE_IK,
                        ACTION, FOLLOW_PATH, SHRINKWRAP, GEOMETRY_ATTRIBUTE.
        properties: Optional dict of the constraint's own settings, e.g. target (an
                   object name), subtarget (a bone name), influence, chain_count,
                   owner_space. Only settings Blender declares on that constraint
                   type are accepted. For a full IK setup use setup_ik_chain.

    Returns:
        Dict with the created constraint's name and type.
    
- **parent_mesh_to_armature** — Parent a mesh object to an armature with automatic weights or other methods.

    Args:
        mesh_name: Name of the mesh object to parent.
        armature_name: Name of the armature object.
        type: Parenting method. One of: ARMATURE_AUTO (automatic weights),
              ARMATURE_NAME (by bone names), ARMATURE_ENVELOPE (by envelope).

    Returns:
        Confirmation dict.
    
- **set_pose** — Set the pose of a bone in an armature.

    Args:
        armature_name: Name of the armature object.
        bone_name: Name of the bone to pose.
        location: Optional XYZ location offset for the bone.
        rotation: Optional XYZ Euler rotation in radians.
        scale: Optional XYZ scale.

    Returns:
        Confirmation dict with the bone's new pose values.
    
- **manage_bone_collection** — Organise an armature's bones into collections and show or hide them.

    Typical rig layout: "Deform" (hidden), "Controls" (visible),
    "Mechanism" (hidden).

    Args:
        armature_name: Armature object.
        action: CREATE (optionally with bones and a parent collection), DELETE,
            ASSIGN or UNASSIGN bones, SHOW or HIDE the collection.
        collection_name: Bone collection to act on.
        bones: Bone names for CREATE, ASSIGN and UNASSIGN, at most 1000.
        parent: CREATE only: nest under this existing collection.

    Returns:
        Dict with the armature's collections, their bones and visibility.
    
- **setup_ik_chain** — Give a limb inverse kinematics: move the target and the chain follows.

    Put the IK on the last bone of the limb (forearm, shin). A pole target
    (an empty or bone in front of the knee or behind the elbow) keeps the
    joint bending the right way.

    Args:
        armature_name: Armature object.
        bone_name: Last bone of the chain (the IK sits on it).
        target_object: Object the chain reaches for (often the armature itself
            when target_bone names a control bone).
        target_bone: Bone in target_object to reach for, if any.
        chain_count: Bones in the chain counting up from bone_name, 0 to 255
            (0 means the whole chain to the root).
        pole_object: Object that sets the joint's bend direction, if any.
        pole_bone: Bone in pole_object, if any.
        pole_angle: Rotate the pole's effect, radians, -3.142 to 3.142;
            -1.571 (-90 degrees) is a common fix for a twisted limb.
        use_stretch: Let bones stretch to reach a target out of range.
        iterations: Solver iterations, 1 to 10000.

    Returns:
        Dict with the constraint and chain details.
    
- **add_rigid_body** — Add a rigid body physics simulation to an object.

    Args:
        object_name: Name of the object.
        type: Rigid body type - ACTIVE (affected by physics) or PASSIVE (static collider).
        mass: Mass of the object in kg.
        friction: Surface friction coefficient (0.0-1.0).
        restitution: Bounciness (0.0-1.0).

    Returns:
        Confirmation dict with rigid body settings.
    
- **add_cloth_sim** — Add a cloth physics simulation to an object.

    Args:
        object_name: Name of the mesh object.
        quality: Simulation quality steps (1-80).
        mass: Mass of the cloth in kg.

    Returns:
        Confirmation dict with cloth settings.
    
- **add_fluid_sim** — Add a fluid physics simulation to an object.

    Args:
        object_name: Name of the object.
        type: Fluid type - DOMAIN (container), FLOW (emitter), or EFFECTOR (obstacle).
        domain_type: Domain simulation type - GAS (smoke/fire) or LIQUID. Only used when type is DOMAIN.

    Returns:
        Confirmation dict with fluid settings.
    
- **add_particle_system** — Add a particle system to an object.

    Args:
        object_name: Name of the mesh object.
        count: Number of particles (max 1000000).
        lifetime: Particle lifetime in frames.
        emit_from: Emission source - VERT, FACE, or VOLUME.

    Returns:
        Confirmation dict with particle system settings.
    
- **set_physics_property** — Set a property on an existing physics simulation.

    Args:
        object_name: Name of the object with the physics simulation.
        physics_type: Physics type - RIGID_BODY, CLOTH, FLUID, or PARTICLE_SYSTEM.
        property: Property name to set (depends on physics type).
        value: Value to set.

    Returns:
        Confirmation dict with property name and new value.
    
- **bake_physics** — Bake a physics simulation for an object.

    Args:
        object_name: Name of the object with physics.
        physics_type: Optional physics type to bake: RIGID_BODY, CLOTH, FLUID,
            PARTICLE_SYSTEM or SOFT_BODY. If empty, bakes all physics on the object.

    Returns:
        Confirmation dict.
    
- **delete_particle_system** — Remove a particle system from an object.

    Args:
        object_name: Name of the object.
        particle_system_name: Name of the particle system to remove.
            If empty, removes the first particle system.

    Returns:
        Confirmation dict.
    
- **set_particle_velocity** — Set velocity settings for an object's particle system.

    Args:
        object_name: Name of the object with a particle system.
        normal: Velocity along face normals.
        tangent: Velocity along face tangents.
        object_align_factor: XYZ velocity factors relative to the object. 3-element vector.

    Returns:
        Confirmation dict.
    
- **set_particle_rendering** — Set rendering mode for an object's particle system.

    Args:
        object_name: Name of the object with a particle system.
        render_type: Render type. One of: NONE, PATH, OBJECT, COLLECTION.
        instance_object: Object to instance (when render_type is OBJECT).
        instance_collection: Collection to instance (when render_type is COLLECTION).

    Returns:
        Confirmation dict.
    
- **add_force_field** — Add a force field that pushes cloth, particles, soft and rigid bodies.

    Args:
        type: WIND (blows along its local Z), TURBULENCE (random gusts),
            VORTEX (spins around Z), FORCE (pushes outward, negative pulls in),
            MAGNET, HARMONIC (springs to the centre), CHARGE, LENNARDJ (keeps
            things apart), DRAG (slows everything down).
        name: Name for the field object; empty uses the type.
        location: Position [x, y, z].
        rotation: Euler rotation in radians; aims WIND and VORTEX.
        strength: -100000 to 100000. Negative reverses the push.
        flow: Air flow, 0 to 100; for WIND it carries particles along.
        noise: Randomness added to the force, 0 to 100.
        seed: Noise seed, 1 to 128.
        falloff_type: SPHERE, TUBE or PLANE: the shape the force fades over.
        falloff_power: How fast it fades with distance, 0 to 10.
        max_distance: Range beyond which there is no force; 0 for unlimited.

    Returns:
        Dict with the field object's name and settings.
    
- **add_collision** — Make an object solid to cloth, particles and soft bodies.

    Without it, a cloth falls straight through the floor.

    Args:
        object_name: Mesh object to collide with.
        thickness: Outer collision distance, 0.001 to 1.0. Raise it if cloth
            pokes through.
        damping: How much bounce is lost, 0.0 to 1.0.
        friction: Cloth friction against the surface, 0 to 80.
        stickiness: Particles stick to the surface, 0 to 10.
        permeability: Share of particles that pass through, 0.0 to 1.0.

    Returns:
        Dict with the collision settings.
    
- **add_soft_body** — Make an object soft and wobbly: jelly, cushions, bellies, antennae.

    Bake it with bake_physics. With goal on, vertices are pulled back to
    their shape (higher goal_strength is stiffer); with goal off the object
    sags and bounces freely, like a water balloon. Add collision to the floor.

    Args:
        object_name: Mesh object.
        mass: Vertex mass, 0.001 to 50.
        goal: Pull vertices back toward the original shape.
        goal_strength: How strongly, 0.0 to 1.0.
        pull: Edge stiffness when stretched, 0.0 to 0.999.
        push: Edge stiffness when squashed, 0.0 to 0.999.
        bend: Resistance to bending, 0 to 10.
        damping: Edge spring damping, 0 to 50.
        friction: Air friction, 0 to 50.
        self_collision: Stop the body passing through itself (slower).

    Returns:
        Dict with the soft body settings.
    
- **add_rigid_body_constraint** — Join two rigid bodies with a physics constraint (glue, hinge, slider, spring, motor).

    Both objects need add_rigid_body first. The constraint lives on a new
    empty, placed at the midpoint unless location is given; HINGE turns
    around the empty's Z axis, SLIDER and PISTON move along its X.

    Args:
        object1: First rigid body.
        object2: Second rigid body.
        type: FIXED (glued), POINT (ball joint), HINGE, SLIDER, PISTON,
            GENERIC (per-axis limits), GENERIC_SPRING, MOTOR.
        empty_name: Name of the new empty that holds the constraint.
        location: World position of the joint, [x, y, z].
        rotation: Joint orientation in radians, [x, y, z]; aims the hinge axis.
        breaking_threshold: Impulse that snaps the joint; omit for unbreakable.
            Good for destruction: glue pieces with FIXED and a threshold.
        disable_collisions: Stop the two bodies colliding with each other.
        settings: The constraint's own settings, e.g. {"use_limit_ang_z": true,
            "limit_ang_z_lower": -1.57, "limit_ang_z_upper": 0} for a door,
            spring_stiffness_x, motor_ang_target_velocity, use_motor_ang.

    Returns:
        Dict with the empty, the type and the two objects.
    
- **set_rigid_body_world** — Tune the rigid body simulation for the scene, creating it if needed.

    Raise substeps_per_frame and solver_iterations when fast or stacked
    objects jitter, pass through each other, or joints stretch.

    Args:
        enabled: Run the simulation at all.
        time_scale: Speed of the simulation, 0 to 100 (0.5 is slow motion).
        substeps_per_frame: Physics steps per frame, 1 to 1000 (default 10).
        solver_iterations: Constraint solver passes, 1 to 1000 (default 10).
        use_split_impulse: Reduce extra bounce when objects stack.

    Returns:
        Every rigid body world setting after the change.
    
- **create_geometry_nodes** — Create a Geometry Nodes modifier on an object.

    Args:
        object_name: Name of the object to add the modifier to.
        name: Name for the geometry nodes modifier. Defaults to "GeometryNodes".

    Returns:
        Dict with modifier name and node group name.
    
- **add_geometry_node** — Add a node to a geometry nodes modifier's node group.

    Args:
        modifier_name: Name of the geometry nodes modifier (used to find the node group).
        node_type: Blender node type identifier, e.g. GeometryNodeMeshCube,
                   GeometryNodeSetPosition, GeometryNodeTransform,
                   ShaderNodeMath, GeometryNodeJoinGeometry, etc.
        location: XY position for the node in the node editor. Defaults to (0, 0).

    Returns:
        Dict with the created node's name and type.
    
- **connect_geometry_nodes** — Connect two nodes in a geometry nodes modifier's node group.

    Args:
        modifier_name: Name of the geometry nodes modifier.
        from_node: Name of the source node.
        from_socket: Index of the output socket on the source node.
        to_node: Name of the destination node.
        to_socket: Index of the input socket on the destination node.

    Returns:
        Confirmation dict with connection details.
    
- **set_geometry_node_input** — Set an input value on a geometry nodes modifier.

    Args:
        object_name: Name of the object with the modifier.
        modifier_name: Name of the geometry nodes modifier.
        input_name: Name of the input socket to set (as shown in the modifier panel).
        value: The value to set. Type depends on the input (float, int, vector, etc.).

    Returns:
        Confirmation dict with the input name and new value.
    
- **list_geometry_node_inputs** — List all available inputs on a geometry nodes modifier.

    Args:
        object_name: Name of the object with the modifier.
        modifier_name: Name of the geometry nodes modifier.

    Returns:
        List of dicts with input name, type, and current value.
    
- **add_essentials_modifier** — Add one of Blender's ready-made node modifiers, with its inputs set.

    These are full node setups that would take dozens of add_geometry_node
    calls. Change inputs later with set_geometry_node_input.

    Args:
        object_name: Object to add the modifier to.
        modifier: One of:
            array (Shape Line/Circle/Curve, Count, Distance, Offset, Rotation,
                Scale: a richer Array than the classic modifier),
            scatter_on_surface (scatter an Object or Collection over a mesh:
                Object, Density Method Density/Amount, Amount, Density,
                Minimum Distance, Seed, Realize Instances),
            instance_on_elements (Instance On Points/Edges/Faces, Object,
                Collection, Align Rotation, Scale),
            randomize_transforms (jitter instances: Offset, Rotation, Scale,
                Seed),
            curve_to_tube (turn a curve into a pipe with caps and UVs: Scale,
                Profile Resolution, Caps, Shade Smooth),
            geometry_input (bring in another Object or Collection: Input
                Type, Object, Collection, As Instance, Replace Original),
            smooth_by_angle (Angle in radians, Ignore Sharpness),
            capture_rest_geometry (store rest positions for later effects).
        settings: Input name to value, e.g. {"Object": "Rock", "Amount": 200}.
            Object and Collection inputs take the name of an existing one;
            menus take the option name as shown in Blender.

    Returns:
        Dict with the modifier name and every input with its value.
    
- **build_geometry_nodes** — Build a whole geometry node graph on an object in one call.

    The graph is built in a new node group and only put on the modifier if
    every step works; on any error nothing changes. The group always gets a
    Geometry input and output, wired through nodes named "Group Input" and
    "Group Output". Read a graph back with get_geometry_node_tree.

    Args:
        object_name: Object to put the graph on (the modifier is created if needed).
        spec: {
            "inputs": [{"name", "type", "default"?, "min"?, "max"?}]  extra group
                inputs, shown on the modifier. type: FLOAT, INT, BOOLEAN, VECTOR,
                COLOR, ROTATION, STRING, OBJECT, COLLECTION, MATERIAL, GEOMETRY.
            "outputs": same shape, extra group outputs.
            "nodes": [{"name", "type", "location"?: [x, y],
                       "pair_with"?: zone output node name, on a zone's input node
                           (GeometryNodeSimulationInput, GeometryNodeRepeatInput,
                           GeometryNodeForeachGeometryElementInput),
                       "settings"?: {"operation": "SINE"},  node options
                       "inputs"?: {"Size X": 4, "Offset": [0, 0, 1]}}]  socket values;
                       a socket is a name, identifier (Value_001) or index;
                       object/collection/material sockets take a name.
            "links": [[from_node, from_socket, to_node, to_socket]]
        }
            Example: a wavy grid
            {"inputs": [{"name": "Size", "type": "FLOAT", "default": 4}],
             "nodes": [{"name": "grid", "type": "GeometryNodeMeshGrid",
                        "inputs": {"Vertices X": 40, "Vertices Y": 40}},
                       {"name": "pos", "type": "GeometryNodeInputPosition"},
                       {"name": "xyz", "type": "ShaderNodeSeparateXYZ"},
                       {"name": "sine", "type": "ShaderNodeMath",
                        "settings": {"operation": "SINE"}},
                       {"name": "up", "type": "ShaderNodeCombineXYZ"},
                       {"name": "move", "type": "GeometryNodeSetPosition"}],
             "links": [["Group Input", "Size", "grid", "Size X"],
                       ["Group Input", "Size", "grid", "Size Y"],
                       ["pos", 0, "xyz", 0], ["xyz", "X", "sine", 0],
                       ["sine", 0, "up", "Z"], ["grid", "Mesh", "move", "Geometry"],
                       ["up", 0, "move", "Offset"],
                       ["move", "Geometry", "Group Output", "Geometry"]]}
        modifier_name: Geometry nodes modifier to use or create.

    Returns:
        Dict with the modifier, the node group, and the node and link counts.
    
- **get_geometry_node_tree** — Read a geometry nodes modifier's graph: group interface, nodes with their
    settings and unlinked input values, and links.

    Args:
        object_name: Object with the modifier.
        modifier_name: Geometry nodes modifier.

    Returns:
        Dict with interface, nodes and links, in the shape build_geometry_nodes takes.
    
- **create_collection** — Create a new collection, optionally nested under a parent collection.

    Args:
        name: Name for the new collection.
        parent: Optional name of parent collection to nest under.
                Empty string uses the scene's root collection.

    Returns:
        Dict with the created collection's name and parent.
    
- **move_to_collection** — Move objects to a collection, unlinking them from their current collections.

    Args:
        object_names: List of object names to move.
        collection_name: Name of the destination collection.

    Returns:
        Dict with the moved objects and destination collection.
    
- **set_collection_visibility** — Set collection visibility in viewport and/or render.

    Args:
        collection_name: Name of the collection.
        visible: Whether the collection should be visible.
        viewport: Apply visibility change to viewport. Defaults to True.
        render: Apply visibility change to render. Defaults to True.

    Returns:
        Confirmation dict with visibility state.
    
- **delete_collection** — Delete a collection.

    Args:
        collection_name: Name of the collection to delete.
        delete_objects: If True, also delete all objects in the collection.
                       If False, objects are unlinked but kept in the scene.

    Returns:
        Confirmation dict.
    
- **create_collection_instance** — Place a collection as a lightweight instance (an empty that shows it).

    Instances share the collection's data, so a hundred trees cost little
    more than one, and editing the collection updates every copy. Works with
    local and linked collections.

    Args:
        collection_name: Collection to instance.
        name: Name for the instance object; empty uses the collection name.
        location: World position [x, y, z].
        rotation: Euler rotation [x, y, z] in radians.
        scale: Scale [x, y, z]; components must not be zero.

    Returns:
        Dict with the instance object's name and its collection.
    
- **make_instances_real** — Turn a collection instance into real, separately editable objects.

    Args:
        object_name: The instance object (from create_collection_instance or
            a linked collection).
        keep_hierarchy: Keep the instanced objects' parent links.

    Returns:
        Dict with the names of the new objects.
    
- **manage_view_layer** — List, add, remove, rename or configure view layers (separate render layers).

    Each view layer renders the scene with its own collection settings
    (see set_layer_collection) and passes, e.g. a foreground layer and a
    background layer composited together, or a clay layer. Pass, light
    group and AOV tools act on the active view layer: SET_ACTIVE first.

    Args:
        action: LIST; ADD (view_layer is the new name); REMOVE; RENAME (to
            new_name); SET_ACTIVE (the layer other tools change); SET (the
            overrides and use_for_render below).
        view_layer: The layer to act on.
        new_name: RENAME only.
        material_override: SET only: render every object with this material
            (a clay render); "" clears it.
        world_override: SET only: world used for this layer; "" clears it.
        use_for_render: SET only: whether this layer renders at all.

    Returns:
        Dict with every view layer (name, active, use_for_render, overrides).
    
- **set_layer_collection** — Set how a collection takes part in one view layer.

    Args:
        collection_name: Collection, at any depth.
        view_layer: View layer to change; omit for the active one.
        exclude: Leave the collection out of this layer entirely.
        holdout: Render it as a transparent cut-out (the objects mask what is
            behind them), for compositing layers back together.
        indirect_only: Cycles: it shows only in reflections, shadows and bounce
            light, not directly to the camera.

    Returns:
        Dict with the collection, the layer and its exclude/holdout/indirect_only.
    
- **import_file** — Import a 3D file into Blender.

    Supports FBX, OBJ, GLTF/GLB, USD, STL, PLY, Alembic (ABC), and SVG formats.
    Auto-detects format from file extension if type is empty.

    Args:
        filepath: Absolute path to the file to import. Must exist.
        type: Optional format override. One of: FBX, OBJ, GLTF, USD, STL, PLY,
              ABC, SVG. Auto-detected from extension if empty.

    Returns:
        Dict with imported file path and format.
    
- **export_file** — Export scene or selected objects to a 3D file.

    Supports FBX, OBJ, GLTF/GLB, USD, STL, PLY, and Alembic (ABC) formats.

    Args:
        filepath: Absolute path for the export file.
        type: Optional format override. Auto-detected from extension if empty.
        selected_only: If True, export only selected objects. Defaults to False.
        options: The exporter's own settings by name (true/false, numbers or
            choices; never text or paths). Common ones:
            glTF: export_draco_mesh_compression_enable, ..._level (0-10),
                export_image_format (AUTO, JPEG, WEBP, NONE), export_apply
                (apply modifiers), export_animations, export_yup.
            FBX: apply_unit_scale, global_scale, axis_forward, axis_up,
                use_mesh_modifiers, add_leaf_bones, bake_anim.
            OBJ: export_triangulated_mesh, apply_modifiers, export_materials,
                forward_axis, up_axis, global_scale.
            USD: export_materials, export_textures_mode, export_animation.
            STL: ascii_format, global_scale, apply_modifiers.
            An unknown name is refused with the exporter's full list.

    Returns:
        Dict with exported file path and format.
    
- **save_file** — Save the current Blender file.

    If filepath is empty, saves to the current file path (overwrite).
    If filepath is provided, performs a "Save As" to the given path.

    Args:
        filepath: Optional absolute path to save as. Must have .blend extension.
                  Empty string saves to current file.

    Returns:
        Dict with the saved file path.
    
- **open_file** — Open a .blend file.

    Args:
        filepath: Absolute path to the .blend file. Must exist.

    Returns:
        Dict with the opened file path.
    
- **list_recent_files** — List recently opened files from Blender preferences.

    Returns:
        List of file path strings.
    
- **list_blend_contents** — List what another .blend file contains without opening it.

    Use before link_or_append to find the names to bring in. Scripts in the
    file are never run.

    Args:
        filepath: Absolute path to an existing .blend file.

    Returns:
        Dict of data type (objects, collections, materials, node_groups,
        worlds, meshes) to the names in the file.
    
- **link_or_append** — Bring objects, collections, materials and more in from another .blend file.

    Append copies the data into this file so it can be edited. Link keeps a
    live reference: edits to the source file show up here, but the data is
    read-only. A linked collection is placed as an instance; appended objects
    and collections go into the scene. Scripts in the file are never run.

    Args:
        filepath: Absolute path to an existing .blend file.
        data_type: OBJECT, COLLECTION, MATERIAL, NODE_GROUP, WORLD or MESH.
        names: Names to bring in (see list_blend_contents), at most 100.
        link: True to link instead of append.

    Returns:
        Dict with each requested name and the name it has here (appends may
        gain a .001 suffix), plus any instance created for a linked collection.
    
- **pack_resources** — Pack every external image, sound, font and volume into the .blend file.

    Makes the file self-contained so it can be moved or shared without
    missing textures.

    Args:
        autopack: Also pack new external files automatically on every save.

    Returns:
        Dict with the packed items (type, name) and whether autopack is on.
    
- **unpack_resources** — Write packed files out to folders next to the saved .blend (textures/, sounds/, ...).

    Files only ever go beside the .blend, never to paths stored in the file.
    The .blend must be saved first.

    Args:
        overwrite: Replace files already there; by default an existing file is reused.

    Returns:
        Dict with each unpacked item (type, name, filepath relative to the .blend).
    
- **manage_external_paths** — Check and fix the external files (textures, sounds, libraries) a .blend uses.

    Args:
        action: LIST every external path and whether the file exists;
            MAKE_RELATIVE or MAKE_ABSOLUTE to rewrite them (relative paths
            survive moving the project folder; the .blend must be saved);
            FIND_MISSING to search a folder and relink files that moved.
        directory: FIND_MISSING only: absolute folder to search, recursively.

    Returns:
        Dict with each external file (type, name, path, exists) and the
        missing count, after the action.
    
- **list_asset_libraries** — List the asset libraries this Blender can use: Essentials (bundled with
    Blender) and the local libraries set in Preferences. Online libraries are
    never listed or fetched.

    Returns:
        Dict with each library's name and folder.
    
- **list_assets** — List the assets in a library, by file, for place_asset.

    Args:
        library: Library name from list_asset_libraries.
        asset_type: Only this type: OBJECT, COLLECTION, MATERIAL, NODE_GROUP,
            WORLD or MESH. Empty for all.

    Returns:
        Dict with assets (file relative to the library, type, name), and
        truncated if the library has more files than one call reads.
    
- **place_asset** — Bring an asset from a library into the scene (append, or link to keep it
    in sync with the library). Find it with list_assets first.

    Args:
        library: Library name from list_asset_libraries.
        file: The asset's .blend file, relative to the library, as list_assets
            gives it.
        asset_type: OBJECT, COLLECTION, MATERIAL, NODE_GROUP, WORLD or MESH.
        asset_name: The asset's name.
        link: Link instead of append. Linked assets update with the library
            but can't be edited here.

    Returns:
        Dict with the name it got in this file, and any collection instance.
    
- **manage_linked_data** — Work with data linked from other .blend files (link_or_append, place_asset).

    Linked data is read-only here. MAKE_LOCAL copies it into this file and
    cuts the link; OVERRIDE keeps the link but makes it editable, so library
    updates still come through for anything not changed here.

    Args:
        action: LIST libraries, linked data and overrides; MAKE_LOCAL;
            OVERRIDE (OBJECT or COLLECTION); RELOAD a library from disk.
        data_name: MAKE_LOCAL and OVERRIDE: the linked data-block's name.
        data_type: OBJECT, COLLECTION, MATERIAL, NODE_GROUP, WORLD or MESH.
        library: Library name from LIST: required for RELOAD, and picks the
            library when two linked data-blocks share a name.

    Returns:
        Dict with what changed, or for LIST the libraries, linked data and overrides.
    
- **set_viewport_shading** — Set the viewport shading mode.

    Args:
        mode: Shading mode. One of: WIREFRAME, SOLID, MATERIAL, RENDERED.

    Returns:
        Confirmation dict with the new shading mode.
    
- **set_viewport_overlay** — Toggle a viewport overlay setting.

    Args:
        overlay: Overlay property name. One of: show_wireframes, show_face_orientation,
                 show_floor, show_axis_x, show_axis_y, show_axis_z, show_cursor,
                 show_object_origins, show_relationship_lines, show_stats.
        enabled: Whether the overlay should be enabled.

    Returns:
        Confirmation dict with the overlay name and state.
    
- **focus_on_object** — Frame/focus the viewport on a specific object.

    Selects the object and uses View Selected to center the viewport on it.

    Args:
        object_name: Name of the object to focus on.

    Returns:
        Confirmation dict.
    
- **execute_blender_code** — Run Python inside Blender. OFF BY DEFAULT; prefer the structured tools.

    The user must tick "Allow raw Python" in the blenderwright N-panel
    (View3D > Sidebar > blenderwright) for the current Blender session.
    Until they do, this tool returns an error saying so; relay that to the
    user and do not retry. Never ask the user to enable it just to do
    something a structured tool already covers.

    The code runs in a restricted namespace that blocks obvious mistakes
    (import os/subprocess/socket, exec/eval/open/compile). That is a guard
    against accidents, not a security boundary: the code runs in-process
    with full bpy. Every snippet is echoed to Blender's system console and
    listed in the panel so the user can see what ran.

    Args:
        code: Python code to execute. bpy is available but must be imported.

    Returns:
        Dict with 'output' (captured stdout) and 'success' boolean.
    
- **get_viewport_screenshot** — Capture a screenshot of the current Blender 3D viewport.

    Args:
        max_size: Maximum size in pixels for the largest dimension (default: 1000).
        mode: Capture mode - 'fast' for instant viewport capture using OpenGL
            (default), 'full' for a complete render through the active render
            engine.

    Returns:
        Dict with base64-encoded PNG image data, width, height, format, and mode.
    
- **select_all_geometry** — Select, deselect or invert all vertices, edges and faces on one mesh.

    Acts inside a mesh. To select whole objects in the scene, use
    select_objects.

    Args:
        object_name: Name of the mesh object.
        action: One of: SELECT, DESELECT, INVERT, TOGGLE.

    Returns:
        Dict with the counts selected afterwards.
    
- **select_by_index** — Select specific vertices, edges or faces of one mesh by index.

    The deterministic way to select: no operator, no viewport, no guessing.
    analyze_mesh_quality reports sample indices for each defect it finds, so
    this is how to act on them. To select whole objects in the scene, use
    select_objects.

    Args:
        object_name: Name of the mesh object.
        element: One of: VERTEX, EDGE, FACE.
        indices: Indices to select. Must be non-negative and within the mesh.
        extend: Add to the current selection instead of replacing it.

    Returns:
        Dict with how many elements were selected and the mesh's totals.
    
- **select_by_axis** — Select the vertices, edges and faces on one side of a mesh along an axis.

    The usual way to say "the top", "the front" or "the left half" of one
    object. To select whole objects in the scene, use select_objects.

    Args:
        object_name: Name of the mesh object.
        axis: One of: X, Y, Z.
        sign: POS for the positive half, NEG for the negative half, split at
            the middle of the object's bounding box (the middle counts for
            both); ALIGN for geometry lying on that middle plane.
        extend: Add to the current selection instead of replacing it.

    Returns:
        Dict with how many elements were selected.
    
- **select_similar** — Grow the current mesh selection to vertices, edges or faces that resemble it.

    Requires something to already be selected: it compares against that.
    Works inside one mesh; it does not pick objects (see select_objects).

    Args:
        object_name: Name of the mesh object.
        type: What to compare. Face options: FACE_MATERIAL, FACE_AREA,
            FACE_SIDES, FACE_PERIMETER, FACE_NORMAL, FACE_COPLANAR,
            FACE_SMOOTH, FACE_FREESTYLE. Edge options: EDGE_LENGTH, EDGE_DIR,
            EDGE_FACES, EDGE_FACE_ANGLE, EDGE_CREASE, EDGE_BEVEL, EDGE_SEAM,
            EDGE_SHARP, EDGE_FREESTYLE. Vertex options: VERT_NORMAL,
            VERT_FACES, VERT_GROUPS, VERT_EDGES, VERT_CREASE.
        threshold: How close a match must be, 0.0 to 1.0.

    Returns:
        Dict with how many elements were selected.
    
- **select_faces_by_sides** — Select faces of one mesh by how many sides they have.

    The direct way to find ngons (GREATER than 4) or triangles (EQUAL to 3),
    which is what topology cleanup usually needs. Works inside one mesh; to
    select whole objects use select_objects.

    Args:
        object_name: Name of the mesh object.
        number: Number of sides to compare against. A face has at least 3.
        comparison: One of: LESS, EQUAL, GREATER, NOTEQUAL.
        extend: Add to the current selection instead of replacing it.

    Returns:
        Dict with how many faces were selected.
    
- **get_selection** — Report what is currently selected on a mesh.

    Without this a caller cannot see the result of its own selection, and the
    mesh tools that act on the current selection would be operating blind.

    Args:
        object_name: Name of the mesh object.

    Returns:
        Dict with selected and total counts per element type, and the first
        50 selected indices of each, so a caller can confirm before acting.
    
- **booltool_auto_union** — Auto boolean union: merge two mesh objects into one, destructively.

    The target object is consumed and joined into the main object.
    This is useful for permanently joining meshes so parts don't
    float away from their bodies.

    This is the default choice for a union. Use boolean_operation instead
    only when the cutter must stay editable as a modifier.

    Uses Bool Tool extension if installed, otherwise falls back to native
    boolean modifier (a warning will be included in the response).

    Args:
        object_name: Name of the main object to keep.
        target_name: Name of the object to merge into the main object.

    Returns:
        Confirmation dict with operation details. May include a 'warning'
        field if Bool Tool is not available and native fallback was used.
    
- **booltool_auto_difference** — Auto boolean difference: subtract the target object from the main object.

    The target object is used as a cutter and removed after the operation.

    This is the default choice for a cut. Use boolean_operation instead
    only when the cutter must stay editable as a modifier.

    Uses Bool Tool extension if installed, otherwise falls back to native
    boolean modifier (a warning will be included in the response).

    Args:
        object_name: Name of the object to cut from.
        target_name: Name of the cutter object (will be removed).

    Returns:
        Confirmation dict with operation details. May include a 'warning'
        field if Bool Tool is not available and native fallback was used.
    
- **booltool_auto_intersect** — Auto boolean intersect: keep only the overlapping volume of two objects.

    The target object is removed after the operation.

    This is the default choice for an intersection. Use boolean_operation
    instead only when the cutter must stay editable as a modifier.

    Uses Bool Tool extension if installed, otherwise falls back to native
    boolean modifier (a warning will be included in the response).

    Args:
        object_name: Name of the main object.
        target_name: Name of the intersecting object (will be removed).

    Returns:
        Confirmation dict with operation details. May include a 'warning'
        field if Bool Tool is not available and native fallback was used.
    
- **booltool_auto_slice** — Auto boolean slice: split the main object using the target as a cutter.

    Creates two separate pieces from the intersection. The target object
    is removed after the operation.

    Slice has no modifier equivalent: boolean_operation offers UNION,
    DIFFERENCE and INTERSECT only.

    Uses Bool Tool extension if installed, otherwise falls back to native
    boolean modifier (a warning will be included in the response).

    Args:
        object_name: Name of the object to slice.
        target_name: Name of the cutter object (will be removed).

    Returns:
        Confirmation dict with operation details. May include a 'warning'
        field if Bool Tool is not available and native fallback was used.
    
- **inset_faces** — Inset all faces of a mesh, creating a border/frame around each face.

    Core hard-surface modeling operation for adding detail, panel lines, or
    preparing faces for extrusion.

    On a closed mesh, selection="ALL" does nothing: a region with no boundary
    has nothing to inset from, and Blender reports success having changed
    nothing. Measured on a default cube in 5.1, the vertex, edge and face
    counts are identical afterwards. Select the faces you mean and pass
    selection="CURRENT".

    Args:
        object_name: Name of the mesh object.
        thickness: Inset thickness (border width). Range: 0.0-10.0.
        depth: Inset depth (positive=outward, negative=inward). Range: -10.0 to 10.0.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **fill_faces** — Fill selected edges with a face.

    Creates faces from a closed edge loop. Useful for closing gaps in meshes
    or capping open ends.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **grid_fill** — Fill a closed edge loop with a grid of quads.

    Creates a clean quad grid between edge loops. Better than fill_faces
    for maintaining good topology.

    Args:
        object_name: Name of the mesh object.
        span: Number of grid columns. Range: 1-1000.
        offset: Offset for the grid alignment. Range: 0-1000.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **mark_seam** — Mark or clear UV seams on all edges of a mesh.

    UV seams guide the UV unwrapping process. Edges marked as seams define
    where the mesh is "cut" when unwrapped to 2D.

    Args:
        object_name: Name of the mesh object.
        clear: If True, clear seams instead of marking them.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **mark_sharp** — Mark or clear sharp edges on a mesh.

    Sharp edges control auto-smooth shading. Edges marked as sharp will have
    a hard edge in the shading even with smooth shading enabled.

    Args:
        object_name: Name of the mesh object.
        clear: If True, clear sharp marks instead of setting them.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **recalculate_normals** — Recalculate face normals to be consistent (all pointing outward or inward).

    Fixes meshes with flipped or inconsistent normals that cause shading artifacts.

    Args:
        object_name: Name of the mesh object.
        inside: If True, normals point inward instead of outward.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **flip_normals** — Flip the direction of all face normals on a mesh.

    Reverses inside/outside of all faces. Use recalculate_normals instead
    if normals are inconsistent rather than uniformly wrong.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **quads_to_tris** — Convert all quad faces to triangles.

    Useful for game engine export or when triangulated geometry is required.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **tris_to_quads** — Convert adjacent triangle pairs to quad faces where possible.

    Improves topology for subdivision and deformation. Not all triangles
    can be merged: only adjacent pairs with compatible angles.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **dissolve_faces** — Dissolve all faces, merging them into surrounding geometry.

    Removes faces while keeping the surrounding mesh structure intact.
    Cleaner than deleting faces which leaves holes.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **dissolve_edges** — Dissolve all edges, merging adjacent faces.

    Simplifies topology by removing unnecessary edge loops while
    preserving the overall shape.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **dissolve_verts** — Dissolve all vertices, merging connected edges and faces.

    Removes vertices while preserving surrounding geometry.

    Args:
        object_name: Name of the mesh object.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **knife_project** — Project a cutter object's outline onto a mesh to cut it.

    The cutter object (curve or mesh) is projected from the viewport onto
    the target mesh, cutting new edges into it.

    Args:
        object_name: Name of the mesh to cut into.
        cutter_name: Name of the cutter object (curve or mesh) to project.


    Returns:
        Confirmation dict.
    
- **spin_mesh** — Spin (lathe) mesh geometry around an axis.

    Creates rotational geometry by duplicating and rotating the selected
    geometry around a center point. Great for creating round shapes like
    vases, columns, or wheels.

    Args:
        object_name: Name of the mesh object.
        angle: Total spin angle in radians. Range: -6.283 to 6.283 (full circle).
        steps: Number of steps in the spin. Range: 1-1000.
        axis: Spin axis as XYZ vector. Defaults to Z-up (0, 0, 1).
        center: Center point for the spin as XYZ. Defaults to origin.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **set_edge_crease** — Set edge crease value on all edges for subdivision surface control.

    Crease values control how sharp edges remain when a Subdivision Surface
    modifier is applied. 0 = fully smooth, 1 = fully sharp.

    Args:
        object_name: Name of the mesh object.
        value: Crease value. Range: -1.0 to 1.0.

        selection: "ALL" to act on the whole mesh, or "CURRENT" to act only
            on what is already selected. Use the select_* tools to choose
            first. Defaults to "ALL".

    Returns:
        Confirmation dict.
    
- **select_linked** — Grow the current mesh selection to everything connected to it.

    Expands selection to include all connected vertices, edges, and faces.
    Useful for isolating mesh islands or selecting connected components.
    Needs a starting selection: set one with select_by_index or
    select_by_axis first. Works inside one mesh; to select whole objects
    use select_objects.

    Args:
        object_name: Name of the mesh object.

    Returns:
        Confirmation dict.
    
- **symmetrize_mesh** — Make a mesh symmetrical by copying one half onto the other.

    Fixes a model that drifted out of symmetry, or builds the second half of
    a half-modelled object. Works in the object's local axes.

    Args:
        object_name: Mesh object.
        direction: Which half is copied where. NEGATIVE_X copies the -X side
            onto +X; POSITIVE_X the reverse; likewise for Y and Z.
        threshold: Distance within which vertices on the centre line merge,
            0.0 to 1.0.
        selection: "ALL" for the whole mesh, or "CURRENT" for the part already
            selected with the select_* tools.

    Returns:
        Dict with the direction and the vertex count afterwards.
    
- **bisect_mesh** — Slice a mesh with a plane, optionally deleting one side and capping the cut.

    Cuts a new edge loop where the plane crosses, which is also a clean way
    to halve a model before adding a Mirror modifier.

    Args:
        object_name: Mesh object.
        plane_point: A point on the cutting plane, in world space.
        plane_normal: The plane's direction, in world space; it need not be
            unit length but must not be zero. [0, 0, 1] is a horizontal cut.
        clear_inner: Delete everything behind the plane (against the normal).
        clear_outer: Delete everything in front of the plane (along the normal).
        fill: Cap the cut with a face. Only useful when one side is cleared.
        selection: "ALL" for the whole mesh, or "CURRENT" for the part already
            selected.

    Returns:
        Dict with the vertex count afterwards.
    
- **loop_tools** — Reshape selected loops: make them round, even or flat.

    Blender 5.2's built-in versions of the LoopTools add-on. Select a loop or
    region first with the select_* tools.

    Args:
        object_name: Mesh object.
        operation: CIRCLE (shape the selection into a circle: round holes
            for bolts and pipes), SPACE (space vertices evenly along the loop),
            or FLATTEN (press the selection onto a best-fit plane).
        factor: How far to move toward the result, 0.0 to 1.0.
        radius: CIRCLE only: a fixed radius instead of the best fit, above 0.
        selection: "CURRENT" (default) for what is selected, or "ALL".

    Returns:
        Dict with the operation and the object.
    
- **edit_mesh_operation** — Run one of the common edit-mode operations on a mesh.

    Args:
        object_name: Mesh object.
        operation: One of:
            SMOOTH_VERTICES (relax lumpy geometry: factor, repeat),
            POKE (a new vertex in the middle of each face, fanned into
                triangles: offset pushes it along the normal),
            EDGE_SPLIT (separate faces along their edges, for hard edges),
            WIREFRAME (turn every edge into a strut: thickness),
            SOLIDIFY (give faces thickness, e.g. a plane into a slab: thickness).
        selection: ALL, or CURRENT for the part chosen with the select_* tools.
        factor: SMOOTH_VERTICES strength, 0.0 to 1.0.
        repeat: SMOOTH_VERTICES passes, 1 to 100.
        offset: POKE distance along the face normal, -100 to 100.
        thickness: WIREFRAME and SOLIDIFY thickness, 0.0001 to 1000.

    Returns:
        Dict with the operation and the mesh's vertex and face counts after it.
    
- **analyze_mesh_quality** — Analyze mesh topology quality and return a structured defect report.

    Checks for non-manifold edges, loose vertices, zero-area faces,
    duplicate vertices, and wire edges. Returns counts and sample indices
    (capped at 50 per category) for each defect type.

    Args:
        object_name: Name of the mesh object to analyze.

    Returns:
        Dict with vertex/edge/face counts, defect counts and sample indices,
        and an issues_found boolean.
    
- **repair_mesh** — Repair the defects analyze_mesh_quality reports.

    Pairs with analyze_mesh_quality: run that first, then call this with the
    repairs the report calls for. Removing loose geometry and dissolving
    degenerate faces cannot change a well-formed mesh, so both are on by
    default. Filling holes creates new geometry and is opt-in.

    Args:
        object_name: Name of the mesh object to repair.
        remove_loose: Delete loose vertices and wire edges, the ones reported
            as loose_vertex_count and wire_edge_count.
        dissolve_degenerate: Dissolve zero-area faces and zero-length edges,
            reported as zero_area_face_count.
        fill_holes: Close boundary loops, which reduces non_manifold_edge_count
            but invents geometry to do it.

    Returns:
        Dict with the counts before and after, so the effect is visible.
    
- **decimate_mesh** — Reduce a mesh's polygon count, collapsing edges to hit a target.

    The counterpart to subdivision: an agent that has stacked Subdivision
    modifiers has otherwise no way back down, and a dense mesh slows every
    later operation.

    Args:
        object_name: Name of the mesh object to simplify.
        ratio: Fraction of faces to keep, between 0 and 1. 0.5 halves the
            face count. 1.0 keeps everything and is refused as a no-op.

    Returns:
        Dict with the face count before and after.
    
- **create_annotation** — Create a new annotation data block.

    Annotations are viewport overlays used for drawing marks, notes, and guides.
    Unlike Grease Pencil objects, annotations are not positioned in 3D space.

    Args:
        name: Optional name for the annotation. Auto-generated if empty.

    Returns:
        Dict with the created annotation's name.
    
- **add_annotation_layer** — Add a layer to an annotation.

    Layers organize annotation strokes. Each layer can have its own blend mode,
    opacity, and color.

    Args:
        annotation_name: Name of the annotation data block.
        layer_name: Name for the new layer.

    Returns:
        Confirmation dict with annotation and layer names.
    
- **remove_annotation_layer** — Remove a layer from an annotation.

    Args:
        annotation_name: Name of the annotation data block.
        layer_name: Name of the layer to remove.

    Returns:
        Confirmation dict.
    
- **add_annotation_stroke** — Add a stroke to an annotation layer.

    Creates a new stroke with the given points on the specified layer.
    Annotation points in 5.2 are a position only: no pressure or strength.

    Args:
        annotation_name: Name of the annotation data block.
        layer_name: Name of the layer to add the stroke to.
        points: List of XYZ coordinates, e.g. [[0,0,0], [1,1,0], [2,0,0]].
            Maximum 10000 points.

    Returns:
        Confirmation dict with point count.
    
- **set_annotation_stroke_property** — Set a property on an annotation stroke.

    Args:
        annotation_name: Name of the annotation data block.
        layer_name: Name of the layer containing the stroke.
        stroke_index: Index of the stroke in the layer (0-based).
        property: display_mode, the only stroke setting in 5.2.
        value: 3DSPACE (in the scene), 2DSPACE (stuck to the view) or 2DIMAGE.

    Returns:
        Confirmation dict.
    
- **create_grease_pencil** — Create a Grease Pencil object to draw 2D strokes in 3D space.

    Draw into it with add_gp_stroke; colour strokes with create_gp_material.
    For notes on the viewport use the annotation tools instead.

    Args:
        name: Object name.
        location: Position [x, y, z].
        layer_name: Name of its first layer.

    Returns:
        Dict with the object, layer and frame created.
    
- **create_gp_material** — Create a Grease Pencil material: the stroke colour.

    Fills are not offered: in Blender 5.2, strokes built from a script do not
    render their fill.

    Args:
        name: Material name.
        color: Stroke RGBA, components 0.0 to 1.0.

    Returns:
        Dict with the material and its colour.
    
- **add_gp_stroke** — Draw one stroke in a Grease Pencil object.

    Points are in the object's local space. cyclic closes the outline.

    Args:
        object_name: Grease Pencil object (from create_grease_pencil).
        points: 2 to 10000 points, each [x, y, z].
        layer: Layer to draw on; empty uses the active layer, a new name
            creates it.
        frame: Keyframe to draw into (drawings per frame make 2D animation).
        radius: Stroke radius in metres, one value or one per point
            (0.0001 to 10). Varying it tapers the line.
        cyclic: Close the stroke back to its first point.
        material: Grease Pencil material (create_gp_material); empty uses the
            object's first material.

    Returns:
        Dict with the layer, frame and stroke count on that frame.
    
- **add_lineart** — Add Line Art: inked outlines generated from 3D geometry, as seen by the
    active camera. Gives renders a comic, technical or toon look.

    Args:
        source: SCENE (everything), COLLECTION or OBJECT.
        source_name: The collection or object when source is not SCENE.
        name: Name for the Line Art object.
        thickness: Line radius in metres, 0.0001 to 1.0.
        color: Line RGBA, components 0.0 to 1.0.
        crease_angle: Edges sharper than this get lines, radians 0 to 3.1416
            (2.443 is 140 degrees; lower draws more lines).
        use_intersection: Draw lines where objects intersect.

    Returns:
        Dict with the Line Art object and its source.
    
- **sweep_profile_along_path** — Sweep a closed profile along a 3D path to make a solid tube, pipe, cable or rope.

    Use this for anything that follows a route: hoses, handrails, wires, vines,
    tentacles, roads. It orients the profile with parallel transport, so the
    tube never creases or folds where the path turns vertical, and it reports
    whether any bend is too tight for the profile to fit around.

    Args:
        path_points: Centreline as a list of [x, y, z] points, in order. At
            least 2, at most 2000. Consecutive points must differ.
        profile: Cross-section shape - CIRCLE, SQUARE, HEXAGON, or TRIANGLE.
        radius: Distance from the centreline to the furthest point of the
            profile, in Blender units. Must be positive.
        sides: Number of sides for a CIRCLE profile (3-1024). Ignored by the
            fixed-sided profiles.
        resolution: Samples generated between each pair of path points, which
            smooths the path with a centripetal Catmull-Rom spline. 0 uses the
            points exactly as given. 8-16 gives a smooth curve.
        twist: Total rotation of the profile about the path from start to end,
            in radians. Spreads evenly along the path.
        caps: Close both ends. Leave True for a printable solid.
        name: Name for the created object.

    Returns:
        Dict with the object name, vertex and face counts, and a validity
        report: min_clearance_ratio (path curvature radius over profile radius
        at the tightest point), tightest_point, and self_intersects. A ratio
        below 1.0 means rings overlap inside the bend, so the result is
        watertight but is not a solid.
    
- **analyze_sweep_path** — Check whether a path can carry a profile of a given radius, without building it.

    Where a path's radius of curvature falls below the profile radius, the
    swept rings pass through each other on the inside of the bend. The result
    still reports as watertight and manifold with no degenerate faces, so no
    ordinary mesh check catches it. Call this before sweeping, or to find
    where an existing path needs widening.

    Args:
        path_points: Centreline as a list of [x, y, z] points, in order.
        radius: Outer radius of the profile you intend to sweep.
        resolution: Samples between path points, matching what you will pass
            to sweep_profile_along_path so the check covers the same curve.

    Returns:
        Dict with min_clearance_ratio (curvature radius over profile radius at
        the tightest station; below 1.0 self-intersects), tightest_index,
        tightest_point, self_intersects, and counts of stations below 1.0 and
        below 1.5. Aim for 1.5 or more for a clean surface.
    
- **check_3d_printability** — Check whether a mesh will 3D print, using Blender's 3D Print Toolbox.

    Catches three defects a mesh can carry while still passing
    analyze_mesh_quality, because each one leaves the mesh manifold,
    watertight and free of degenerate faces:

    - Bad contiguous edges: a shell whose normals agree with each other but
      collectively face inward. Recalculating normals reports nothing to fix,
      and the slicer rejects the file as having reversed faces.
    - Intersect faces: the surface passing through itself.
    - Thin faces: walls thinner than the nozzle, which slice away to nothing.

    It also reports shell count, zero-area faces and edges, non-flat faces,
    sharp edges and overhanging faces. Index lists are capped at 50 samples
    and can be fed straight to select_by_index to see the problem in Blender.

    Requires the 3D Print Toolbox extension, which ships with Blender but is
    off by default. If it is disabled this returns an error saying how to
    enable it; suggest_extensions also reports whether it is on.

    Args:
        object_name: Name of the mesh object to check.
        checks: Which checks to run - any of SOLID (non-manifold and bad
            contiguous edges), INTERSECT, DEGENERATE (zero faces and edges),
            THICKNESS, SHARP, OVERHANG, NONPLANAR. Omit or pass an empty list
            to run everything, which also reports shell count. Counts are only
            returned for checks that actually ran.
        overhang_angle: Overhang threshold in RADIANS. Faces steeper than this
            need support. 0.785 (45 degrees) is the usual FDM limit. Leave
            unset to keep the toolbox's current setting.
        min_thickness: Minimum wall thickness in Blender units. Set it to your
            nozzle width. Leave unset to keep the current setting.
        sharp_angle: Sharp-edge threshold in RADIANS.
        nonplanar_angle: Non-flat face threshold in RADIANS.
        zero_threshold: Area below which a face counts as zero-area.

    Returns:
        Dict with a count (and sample indices) per check that ran, plus
        checks_run, issues_found, and print_blocking: the defects that stop a
        print, as opposed to overhangs and sharp edges which are advisory.
    
- **add_image_sequence_strip** — Add rendered frames to the sequencer as one image strip.

    Give the first frame of a numbered sequence, such as the output of
    render_animation. Every file in the same folder that shares its prefix and
    extension is added in numeric order, one image per timeline frame.

    Args:
        first_frame: Path to the first image, e.g. /renders/f_0001.png.
        name: Optional name for the strip.
        channel: Sequencer channel, 1-128. Higher channels draw on top.
        frame_start: Timeline frame where the strip begins.

    Returns:
        Dict with the strip name, image count, and the frames it covers.
    
- **add_sound_strip** — Add an audio file to the sequencer as a sound strip.

    Args:
        filepath: Path to the audio file (.wav, .mp3, .flac, .ogg,
            .m4a, .aac, .opus).
        name: Optional name for the strip.
        channel: Sequencer channel, 1-128.
        frame_start: Timeline frame where the sound becomes audible.
        start_offset: Seconds to skip at the start of the audio file, so a
            clip can begin partway in.
        volume: Volume multiplier, 0-100. 1.0 leaves the audio unchanged.

    Returns:
        Dict with the strip name and the frames it covers.
    
- **list_strips** — List every strip in the sequencer.

    Returns:
        List of dicts with name, type, channel, and first and last frame.
    
- **remove_strip** — Remove a strip from the sequencer by name.

    Args:
        strip_name: Name of the strip to remove.

    Returns:
        Confirmation dict.
    
- **render_video** — Render the scene's frame range to a single video file, with sound.

    Sequencer strips are used when there are any, so frames already rendered
    with render_animation can be assembled with a sound strip in seconds.
    With an empty sequencer the 3D scene is rendered. Playback speed follows
    the scene fps.

    Args:
        filepath: Output path, in a directory that exists. Empty means the
            system temp directory. The extension must match the
            container: .mp4 for MPEG4, .mkv for MKV, .webm for WEBM.
        container: Video container. One of: MPEG4, MKV, WEBM.
        quality: Encoder quality preset, from LOWEST to LOSSLESS.
        audio_codec: Audio codec, or NONE for a silent video. WEBM accepts
            only OPUS or NONE.

    Returns:
        Dict with the output path, frame range, and fps.
    
- **add_sequencer_strip** — Add a text, solid colour or movie strip to the video sequencer.

    Higher channels draw on top. Style text or move any strip afterwards with
    set_strip_property; fade it with add_strip_fade.

    Args:
        kind: TEXT (a title), COLOR (a solid background) or MOVIE (a video file).
        name: Strip name; defaults to the kind or the file name.
        channel: 1 to 128.
        frame_start: First frame.
        length: Frames, for TEXT and COLOR (a MOVIE takes the file's length).
        text: TEXT only: the words, up to 2000 characters.
        font_size: TEXT only, 1 to 2000.
        color: TEXT: RGB(A) of the letters; COLOR: RGB of the fill. 0.0 to 1.0.
        filepath: MOVIE only: absolute path to .mp4, .mov, .mkv, .webm, .avi or .m4v.

    Returns:
        Dict with the strip's name, type, channel and frame range.
    
- **set_strip_property** — Change a sequencer strip: its own settings, position and crop.

    Args:
        strip_name: The strip.
        settings: The strip's settings by name, e.g. {"blend_alpha": 0.5,
            "channel": 3, "frame_start": 10, "blend_type": "ADD"}; text strips
            also take text, font_size, use_shadow, use_outline, use_box,
            wrap_width and alignment_x (LEFT, CENTER, RIGHT).
        transform: offset_x / offset_y (pixels), scale_x / scale_y, rotation (radians).
        crop: min_x, max_x, min_y, max_y in pixels.

    Returns:
        Dict with the strip's name, type, channel and frame range.
    
- **add_strip_fade** — Fade a strip in from black and/or out to black (sound strips fade their volume).

    Args:
        strip_name: The strip.
        fade_in: Frames to fade in over, from the strip's start.
        fade_out: Frames to fade out over, ending at the strip's end.

    Returns:
        Dict with the strip and the frames keyed.
    
- **setup_compositor** — Make sure the scene has a compositor: Render Layers into the output.

    add_compositor_effect calls this itself, so it is only needed to start
    over. Effects then stack between the render and the output.

    Args:
        reset: Throw away the current compositor tree and start clean.

    Returns:
        Dict with the tree name and the effect chain, render to output.
    
- **add_compositor_effect** — Add a post-processing effect at the end of the compositor chain.

    Effects apply to every render in order, so add glare before film grain.

    Args:
        effect: One of:
            glare (inputs: Type Bloom/Fog Glow/Streaks/Ghosts/Simple Star/
                Sun Beams, Quality High/Medium/Low, Threshold, Strength, Size,
                Saturation, Tint, Streaks, Streaks Angle),
            lens_distortion (Type Radial/Horizontal, Distortion -1..1,
                Dispersion, Fit),
            color_balance (Type Lift/Gamma/Gain or
                "Offset/Power/Slope (ASC-CDL)" or White Point, Factor, Lift,
                Gamma, Gain as RGBA lists, Temperature, Tint),
            denoise (Prefilter, Quality, HDR), blur (Size [x, y] in pixels,
                Type Gaussian...), exposure (Exposure), brightness_contrast
                (Brightness, Contrast), hue_saturation (Hue, Saturation, Value,
                Factor), kuwahara (painterly), pixelate, posterize,
                anti_aliasing,
            vignette (Factor, Feather, Corner Roundness, Scale [x, y]),
            film_grain (Preset, ISO 50..3200, Animated, Softness),
            chromatic_aberration (Factor, Type, Samples), sepia (Tone,
                Saturation, Contrast), split_toning (Highlights, Shadows as
                RGBA, Balance), sensor_noise (Luminance Noise, Chroma Noise),
            unsharp_mask (Radius, Factor), tune_image (Contrast, Color
            Boost, Clarity, Sharpen).
        settings: Input name to value, e.g. {"Type": "Fog Glow",
            "Strength": 0.6}. Names are the node's input labels.

    Returns:
        Dict with the new node's name (use it to edit or remove the effect)
        and its input names.
    
- **set_compositor_effect** — Change the settings of an effect already in the compositor.

    Args:
        node_name: The node name returned by add_compositor_effect or
            list_compositor, e.g. "Glare".
        settings: Input name to value, as for add_compositor_effect.

    Returns:
        Dict with the node name and its inputs after the change.
    
- **remove_compositor_effect** — Remove an effect and reconnect the chain around it.

    Args:
        node_name: The node name from add_compositor_effect or list_compositor.

    Returns:
        Dict with the removed name and the remaining chain.
    
- **list_compositor** — List the compositor chain from render to output with each effect's settings.

    Returns:
        Dict with the tree name and the chain of effects in order.
    
- **set_color_management** — Set how the scene's light becomes final pixel colours.

    AgX (the default) handles bright highlights gracefully; Standard is for
    flat graphics and UI shots; Khronos PBR Neutral keeps product colours
    true. A look adds contrast on top. Leave anything unset to keep it.

    Args:
        view_transform: One of: AgX, Standard, Filmic, Filmic Log,
            Khronos PBR Neutral, ACES 1.3, ACES 2.0, False Color, Raw.
        look: Contrast look, short name. AgX and False Color offer Punchy,
            Greyscale, Base Contrast and Very Low to Very High Contrast; most
            others offer Very Low to Very High Contrast; ACES offers
            Reference Gamut Compression. "None" clears it. Applies to the
            view transform being set, or the current one.
        exposure: Brightness in stops. Range -10.0 to 10.0; 0 is unchanged.
        gamma: Extra gamma. Range 0.0 to 5.0; 1.0 is unchanged.
        display_device: One of: sRGB, Display P3, Rec.1886, Rec.2020,
            Rec.2100-PQ, Rec.2100-HLG.
        white_balance_temperature: Kelvin, 1800 to 100000. Lower warms the
            image, higher cools it. Setting it turns white balance on.
        working_space: Color space the file renders and mixes colours in:
            Linear Rec.709 (default), Linear Rec.2020 or ACEScg (wide gamut,
            for VFX pipelines).
        convert_colors: With working_space: convert existing colours so they
            look the same; false keeps the raw numbers.

    Returns:
        Dict with the full colour management state after the change.
    
- **set_film** — Set film options: transparent background and pixel filter.

    Args:
        transparent: Render the world background as transparent, for
            compositing or product cut-outs. Needs PNG or EXR output to keep
            the alpha.
        transparent_glass: Cycles only. Let the background show through glass
            and other transmissive surfaces when transparent is on.
        filter_width: Cycles pixel filter width in pixels, 0.01 to 10.0.
            1.5 is Blender's default; lower is sharper, higher is softer.

    Returns:
        Dict with the film settings after the change.
    
- **set_denoising** — Configure Cycles denoising for final renders and the viewport.

    Denoising lets a render use far fewer samples: 128 denoised samples often
    beat 2048 raw ones. Leave anything unset to keep it.

    Args:
        enabled: Denoise final renders.
        denoiser: OPENIMAGEDENOISE (any machine) or OPTIX (NVIDIA GPUs only).
        quality: HIGH, BALANCED or FAST.
        prefilter: How the albedo and normal guides are cleaned: ACCURATE
            (sharpest detail), FAST, or NONE.
        input_passes: Guides the denoiser uses: RGB, RGB_ALBEDO, or
            RGB_ALBEDO_NORMAL (best edges).
        use_gpu: Run the denoiser on the GPU when one is available.
        viewport: Denoise the rendered viewport preview too.

    Returns:
        Dict with the denoising settings after the change.
    
- **set_cycles_sampling** — Tune how Cycles spends samples. Set the sample count with set_render_samples.

    Leave anything unset to keep it.

    Args:
        adaptive: Stop sampling pixels once they are clean enough.
        noise_threshold: Adaptive cut-off, 0.0 to 1.0. 0.01 is Blender's
            default; 0.05 renders faster and noisier, 0.001 slower and cleaner.
        min_samples: Samples every pixel gets before adaptive stopping,
            0 to 4096. 0 lets Blender choose.
        time_limit: Seconds per frame before stopping, 0 to 86400. 0 means no limit.
        clamp_direct: Cap on direct light per sample, 0 to 1000000. 0 means no
            clamp. Lowers fireflies at the cost of some energy.
        clamp_indirect: Cap on bounced light per sample, 0 to 1000000. 10 is
            Blender's default; lower removes fireflies.
        path_guiding: Learn where light comes from; helps interiors lit
            through small openings. CPU only.
        seed: Noise pattern seed, 0 or more.
        animated_seed: Change the seed every frame so noise does not stick
            to the screen in animations.

    Returns:
        Dict with the sampling settings after the change.
    
- **set_light_paths** — Set Cycles light bounce limits and caustics.

    Fewer bounces render faster; glass and liquids need enough transmission
    bounces or they turn black. Each bounce count is 0 to 1024. Leave
    anything unset to keep it.

    Args:
        total: Overall bounce cap (Blender default 12).
        diffuse: Bounces off matte surfaces (default 4).
        glossy: Bounces off shiny surfaces (default 4).
        transmission: Bounces through glass and liquid (default 12).
        volume: Bounces inside smoke and fog (default 0).
        transparent: Layers of alpha-transparent surfaces such as leaves
            (default 8).
        caustics_reflective: Allow light focused by mirrors.
        caustics_refractive: Allow light focused by glass; turning it off
            removes much glass noise.
        filter_glossy: Blur sharp reflections to cut noise, 0.0 to 10.0.

    Returns:
        Dict with the light path settings after the change.
    
- **set_motion_blur** — Set render motion blur for moving objects and cameras.

    Args:
        enabled: Turn motion blur on or off.
        shutter: Shutter time in frames, 0.0 to 2.0. 0.5 is a film-like
            180 degree shutter.
        position: Where the shutter opens around the frame: START, CENTER or END.
        eevee_steps: EEVEE only. Blur passes, 1 to 64. More gives smoother
            curved motion.

    Returns:
        Dict with the motion blur settings after the change.
    
- **set_render_passes** — Turn render passes on or off for the active view layer.

    Passes are extra images saved with a multilayer EXR or used in the
    compositor: depth for fog and focus, mist, normals, cryptomatte masks
    for picking objects later.

    Args:
        passes: Pass names: combined, z (alias depth), mist, normal,
            position, vector, uv, object_index, material_index,
            ambient_occlusion (alias ao), shadow, emit (alias emission),
            environment, diffuse_direct, diffuse_indirect, diffuse_color,
            glossy_direct, glossy_indirect, glossy_color,
            transmission_direct, transmission_indirect, transmission_color,
            subsurface_direct, subsurface_indirect, subsurface_color,
            cryptomatte_object, cryptomatte_material, cryptomatte_asset,
            shadow_catcher (Cycles), volume_direct, volume_indirect (Cycles),
            transparent (EEVEE), grease_pencil.
        enabled: True to turn them on, False to turn them off.

    Returns:
        Dict with the view layer name and the passes changed.
    
- **set_light_group** — Put lights (or emissive objects, or the world) into a light group.

    Each light group renders as its own pass (Cycles), so light balance can
    be changed in the compositor without re-rendering: the Render Layers
    node gets a Combined_<group> output. The group is created if needed.

    Args:
        group: Light group name. Blender turns dots into underscores; the
            result gives the name actually used.
        objects: Lights or emissive objects to move into the group.
        world: Also put the world (sky/HDRI light) into the group.
        remove: Delete the group and take every member out of it.

    Returns:
        Dict with the group name used and every light group with its members.
    
- **manage_aov** — List, add or remove shader AOVs: custom render passes written by materials.

    In a material, an Output AOV node (ShaderNodeOutputAOV, its aov_name set to
    this name) writes a color or value into the pass. Use for masks and IDs
    in compositing. The Render Layers node gets an output with the AOV name.

    Args:
        action: LIST, ADD or REMOVE.
        name: AOV name, for ADD and REMOVE.
        type: ADD only: COLOR or VALUE.

    Returns:
        Dict with every AOV (name, type).
    
- **set_freestyle** — Draw ink lines over the render: outlines, toon, technical-drawing looks.

    Applies to the active view layer's line set (created if needed).

    Args:
        enabled: Turn line rendering on or off.
        thickness: Line width in pixels, 0.1 to 10000.
        color: RGB of the lines, 0.0 to 1.0.
        edges: Which edges get lines: SILHOUETTE (object outline against
            others), BORDER (open mesh edges), CREASE (sharp folds, see
            crease_angle), CONTOUR, EXTERNAL_CONTOUR (outer outline only),
            MATERIAL_BOUNDARY, RIDGE_VALLEY, SUGGESTIVE_CONTOUR, EDGE_MARK
            (edges marked for Freestyle). Replaces the current choice.
        crease_angle: Degrees, 0 to 180: edges sharper than this count as creases.
        as_render_pass: Put the lines in their own pass instead of on the image.

    Returns:
        Dict with the Freestyle state after the change.
    
- **set_object_ray_visibility** — Choose which rays see an object: hide it from the camera but keep its
    shadow, keep it out of reflections, or turn it into a shadow catcher.

    Leave anything unset to keep it.

    Args:
        object_name: Object to change.
        camera: Seen directly by the camera.
        diffuse: Lights matte surfaces by bounced light.
        glossy: Shows in reflections.
        transmission: Shows through glass.
        volume_scatter: Affects smoke and fog.
        shadow: Casts shadows.
        holdout: Cut a transparent hole where the object is, for compositing.
        shadow_catcher: Cycles only. Show only the shadows other objects cast
            on it, for placing renders into photos (pair with set_film
            transparent).

    Returns:
        Dict with every visibility flag after the change.
    
- **set_eevee_quality** — Tune EEVEE's reflections, global illumination, shadows and volumes.

    Leave anything unset to keep it.

    Args:
        raytracing: Screen-space ray traced reflections and refraction.
        ray_tracing_method: PROBE (fast, uses light probes) or SCREEN
            (accurate for what is on screen).
        fast_gi: Approximate bounced light.
        fast_gi_method: GLOBAL_ILLUMINATION or AMBIENT_OCCLUSION_ONLY.
        shadow_pool_size: Shadow memory in MB: 16 to 2048 in powers of two,
            plus 1536 (new in 5.2). Raise it if shadows go blocky.
        shadow_rays: Soft shadow rays per light, 1 to 4.
        shadow_steps: Soft shadow steps, 1 to 16.
        volumetric_samples: Fog and smoke slices, 1 to 256.
        volumetric_tile_size: Volume detail in pixels: 1, 2, 4, 8 or 16
            (smaller is sharper and slower).
        volumetric_shadows: Volumes cast shadows on themselves.
        clamp_direct: Cap on direct light per sample, 0 for none.
        clamp_indirect: Cap on bounced light per sample, 0 for none.

    Returns:
        Dict with the EEVEE settings after the change.
    
- **set_render_performance** — Speed up heavy renders or fit them in memory.

    Leave anything unset to keep it.

    Args:
        simplify: Turn on Simplify, which max_subdivision and the texture
            settings need.
        max_subdivision: Cap subdivision levels at render, 0 to 6.
        texture_limit: Cycles: largest texture size at render, OFF or 128 to
            8192.
        texture_resolution: Cycles: scale all textures, 0.0 to 1.0 (new in 5.2).
        persistent_data: Cycles: keep scene data between frames of an
            animation for faster re-renders, at the cost of memory.
        auto_tile: Cycles: render in tiles to save memory.
        tile_size: Cycles tile size in pixels, 8 to 8192.
        anisotropic_filter: Texture filtering for angled surfaces: 0, 2, 4, 8
            or 16.

    Returns:
        Dict with the performance settings after the change.
    
- **assign_vertex_group** — Put vertices into a vertex group with a weight, creating the group if needed.

    Vertex groups drive armature skinning, and limit modifiers (Displace,
    Solidify, Mask) and shape keys to part of a mesh.

    Args:
        object_name: Mesh object.
        group_name: Vertex group; created if it does not exist.
        vertex_indices: Vertices to change. Omit to use the whole mesh, or
            the edit-mode selection with selection="CURRENT".
        weight: 0.0 to 1.0.
        mode: REPLACE sets the weight, ADD and SUBTRACT change it, REMOVE
            takes the vertices out of the group.
        selection: When vertex_indices is omitted: ALL vertices, or CURRENT
            for the ones selected in edit mode (use the select_* tools first).

    Returns:
        Dict with the group name, its index and how many vertices changed.
    
- **list_vertex_groups** — List an object's vertex groups with vertex counts and weight ranges.

    Args:
        object_name: Mesh object.

    Returns:
        Dict with each group's name, index, vertex count, min and max weight.
    
- **remove_vertex_group** — Delete a vertex group and every weight in it.

    Args:
        object_name: Mesh object.
        group_name: Vertex group to delete.

    Returns:
        Dict with the removed group and the groups left.
    
- **vertex_group_operation** — Clean up or reshape the weights in a vertex group.

    Args:
        object_name: Mesh object.
        group_name: Vertex group to work on.
        operation: One of:
            NORMALIZE (scale so the highest weight is 1),
            NORMALIZE_ALL (make each vertex's weights across all groups sum
                to 1, as armatures expect),
            INVERT (weight becomes 1 - weight), CLEAN (drop weights at or
            below threshold), SMOOTH (blur weights with neighbours: factor,
            repeat), LEVELS (weight * gain + offset), LIMIT_TOTAL (keep at
            most max_groups groups per vertex, as game engines need),
            MIRROR (mirror the weights across X), QUANTIZE (snap weights to
            steps levels).
        factor: SMOOTH strength, 0.0 to 1.0.
        repeat: SMOOTH passes, 1 to 200.
        threshold: CLEAN cut-off, 0.0 to 1.0.
        offset: LEVELS offset, -1.0 to 1.0.
        gain: LEVELS gain, 0.0 to 10.0.
        max_groups: LIMIT_TOTAL groups per vertex, 1 to 32.
        steps: QUANTIZE levels, 1 to 1000.

    Returns:
        Dict with the group's vertex count and weight range afterwards.
    
- **add_shape_key** — Add a shape key (blend shape). The first call also creates the Basis.

    Shape keys store alternative vertex positions blended by a 0-1 value:
    facial expressions, morphs, corrective shapes. Shape it with
    move_shape_key_vertices, blend with set_shape_key, animate with
    keyframe_shape_key. A new key starts at value 1.0 (fully on), so edits
    show straight away; set it to 0 to hide it.

    Args:
        object_name: Mesh object.
        key_name: Name for the new shape key.
        from_mix: Start from the current blend of all keys instead of the Basis.

    Returns:
        Dict with the new key and every key on the object.
    
- **set_shape_key** — Set how strongly a shape key applies, and its options.

    Args:
        object_name: Mesh object.
        key_name: Shape key.
        value: Blend amount, normally 0.0 to 1.0, within the slider range.
        slider_min: Lowest allowed value, -10.0 to 10.0 (0.0 by default).
            Negative values let a "smile" key also frown.
        slider_max: Highest allowed value, -10.0 to 10.0 (1.0 by default).
        mute: Switch the key off without losing its value.
        vertex_group: Limit the key to this vertex group's weights; "" clears it.
        relative_key: Key this one is measured against (the Basis by default).

    Returns:
        Dict with the key's settings after the change.
    
- **move_shape_key_vertices** — Move vertices inside a shape key, building the blend shape.

    The offset is in the object's local space. With a vertex group, each
    vertex moves by offset times its weight, which gives soft falloff:
    weight the cheeks, then move them out to puff them.

    Args:
        object_name: Mesh object.
        key_name: Shape key to edit (not the Basis).
        offset: [x, y, z] distance to move, each -1000 to 1000.
        vertex_indices: Vertices to move. Leave out to use vertex_group, or
            neither to move the whole mesh.
        vertex_group: Move by this group's weights instead of by index.

    Returns:
        Dict with the number of vertices moved.
    
- **list_shape_keys** — List an object's shape keys with values, ranges and options.

    Args:
        object_name: Mesh object.

    Returns:
        Dict with the reference key and each key's settings.
    
- **remove_shape_key** — Delete a shape key.

    Args:
        object_name: Mesh object.
        key_name: Shape key to delete.

    Returns:
        Dict with the removed key and the keys left.
    
- **keyframe_shape_key** — Keyframe a shape key's value so the blend shape animates.

    Args:
        object_name: Mesh object.
        key_name: Shape key.
        frame: Frame number.
        value: Value to set before keying; omit to key the current value.

    Returns:
        Dict with the key, frame and keyed value.
    
- **paint_color_attribute** — Fill a color attribute (vertex colors) on a mesh, creating it if needed.

    The attribute becomes the active and render color. Read it in a material
    with a ShaderNodeVertexColor node whose layer_name is the attribute name.
    Game engines and glTF export pick it up as vertex color.

    Args:
        object_name: Mesh object.
        color: Linear RGB or RGBA, each 0.0 to 1.0.
        attribute_name: Color attribute; created if it does not exist.
        domain: CORNER (per face corner, allows hard color edges) or POINT
            (per vertex). Used only when creating the attribute.
        data_type: BYTE_COLOR (8-bit) or FLOAT_COLOR. Used only when creating.
        vertex_indices: Vertices to paint. Omit to paint the whole mesh, or
            the edit-mode selection with selection="CURRENT".
        selection: When vertex_indices is omitted: ALL, or CURRENT for the
            vertices selected in edit mode (use the select_* tools first).

    Returns:
        Dict with the attribute, its domain and type, whether it was created,
        how many elements were painted, and all color attribute names.
    
- **remove_color_attribute** — Delete a color attribute from a mesh.

    Args:
        object_name: Mesh object.
        attribute_name: Color attribute to remove.

    Returns:
        Dict with the removed name and the color attributes left.
    
- **create_lattice** — Wrap an object in a lattice cage and deform it through the cage.

    The lattice is fitted to the object's bounding box and a Lattice modifier
    is added. Then bend, taper or bulge the whole shape with
    move_lattice_points instead of editing vertices.

    Args:
        object_name: Object to deform (mesh, curve, text...).
        resolution: Points along [u, v, w] (the object's X, Y, Z), 2 to 64 each.
            More points give more local control. Default [2, 2, 2].
        interpolation: KEY_LINEAR (default) follows the points exactly: scale
            them to 0.5 and the shape halves. KEY_BSPLINE is smoother but only
            approximates the points (the same move gives about 0.67).
            KEY_CATMULL_ROM and KEY_CARDINAL sit between.
        lattice_name: Name for the lattice object; defaults to "<object> Lattice".

    Returns:
        Dict with the lattice name, its point count and the modifier name.
    
- **move_lattice_points** — Move or scale lattice points to deform everything the lattice is bound to.

    Pick points by side (axis and sign, split at the middle of the lattice) or
    by index; with neither, every point moves. Scaling is about the lattice
    centre, per axis: scale [0.2, 0.2, 1] on the top tapers it to a point.

    Args:
        lattice_name: Lattice object from create_lattice.
        offset: [x, y, z] in world units added to the chosen points.
        scale: [x, y, z] factors, 0.01 to 100, about the lattice centre.
        axis: X, Y or Z: choose the points on one side of the lattice.
        sign: POS, NEG, or ALIGN (the middle plane) with axis.
        point_indices: Choose points by index instead (u fastest, then v, then w).
        reset: Put every point back where it started (others ignored).

    Returns:
        Dict with how many points moved and the lattice's point count.
    
- **bake_texture** — Bake a texture map from an object's materials (or a high-poly source) into an image.

    The object needs UVs (smart_uv_project) and a material. Cycles is used
    for the bake and the render engine is put back afterwards.

    Args:
        object_name: Object whose UVs receive the bake (the low-poly one).
        bake_type: DIFFUSE (base colour, see diffuse_color_only), NORMAL,
            AO, ROUGHNESS, EMIT, COMBINED (fully lit), GLOSSY,
            TRANSMISSION, SHADOW, ENVIRONMENT, POSITION or UV.
        filepath: Image to write: .png, .exr, .tif or .jpg, in an existing
            directory. Use .exr or .png for normal maps.
        resolution: Square image size in pixels, 64 to 8192.
        source_object: High-poly object to bake from onto object_name
            (selected to active). Leave empty to bake the object onto itself.
        cage_extrusion: How far rays start outside the low-poly surface when
            baking from a source, 0.0 to 10.0. Raise it if the bake has holes.
        max_ray_distance: Furthest a ray may travel to hit the source, 0 for
            no limit, up to 10.0.
        margin: Pixels to bleed past UV island edges, 0 to 64, so mipmaps
            don't show seams.
        samples: Cycles samples for the bake, 1 to 4096. AO and COMBINED
            need more; DIFFUSE and NORMAL are clean at 1 to 16.
        diffuse_color_only: For DIFFUSE, bake the flat base colour (albedo)
            rather than lit colour. Game engines want this.
        normal_space: For NORMAL: TANGENT (game engines, normal map nodes)
            or OBJECT.

    Returns:
        Dict with the file written, its size and the image name in Blender.
    

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "blenderwright": {
    "command": "uvx",
    "args": ["blenderwright"]
  }
}
```

## Documentation

## What blenderwright does

blenderwright lets an MCP-compatible AI assistant operate Blender for 3D production tasks. Its tools cover modeling, mesh editing, materials, shader nodes, lighting, cameras, animation, rendering, sculpting, UV mapping, physics, geometry nodes, rigging, curves, path-based sweeps, 3D-print checks, annotations, collections, file operations, viewport control, and mesh inspection.

The server includes 276 tools organized across 32 Blender-related modules. It also provides 13 expert prompts covering topics such as topology, real-world scale, lighting, studio setups, character basemeshes, physically based materials, and self-critique workflows.

## How it works

The MCP process communicates with an enabled blenderwright addon inside Blender. MCP messages travel over standard input and output, while the server reaches the addon through a TCP connection on `127.0.0.1`. The addon runs a background TCP server and queues Blender operations for execution on Blender's main thread.

Start Blender's addon server from the blenderwright panel in the 3D Viewport, then run the MCP server with `uvx blenderwright` or the installed `blenderwright` command. The default addon port is 9876, and the port can be changed in the N-panel.

Viewport screenshots provide a fast visual feedback loop using OpenGL rendering. Automatic critique prompts can direct an AI assistant to review its result. During a Blender render, commands are queued until rendering is handled, and the addon includes recovery behavior for stale render guards.

## Setup and configuration

Install the MCP package with either of these approaches:

- Run `uvx blenderwright` without a separate package installation.
- Install it with `pip install blenderwright`, then run `blenderwright`.

Install the Blender addon from the latest release ZIP through **Edit > Preferences > Get Extensions > Install from Disk...**, then enable blenderwright. Blender 5.2 LTS is required; Blender 5.1 and earlier are unsupported.

In Blender, open the 3D Viewport's N-panel, select the blenderwright tab, choose a port if needed, and click **Start Server**. An option can start the server automatically when Blender opens. The addon has no Python packages to install inside Blender and uses the Python standard library plus `bpy`.

Claude Code can register the server with `claude mcp add blenderwright -- uvx blenderwright`. Claude Desktop uses an MCP configuration entry with `uvx` as the command and `blenderwright` as its argument. Other stdio-compatible MCP clients can run the same command, with configuration paths and formats determined by each client.

## Tools and capabilities

- Create and edit meshes, scenes, materials, shader-node graphs, cameras, lights, and animations.
- Render still images and animation sequences, including workflows that configure scenes before rendering.
- Inspect mesh quality through reports on non-manifold edges, loose vertices, zero-area faces, duplicate vertices, and wire edges.
- Generate viewport screenshots for visual inspection and iterative correction.
- Suggest Bool Tool, LoopTools, and Node Wrangler when a task would benefit from an available extension.
- Use `execute_blender_code` only after enabling **Allow raw Python** in the Blender N-panel for the current session.

Raw Python execution is disabled by default. When enabled, snippets are shown in Blender's console and panel, and a restricted namespace blocks obvious operations such as `os`, `subprocess`, `exec`, and `open`. This restriction is intended to reduce accidental misuse, not to provide a security boundary.

## Limitations and notes

The Blender addon targets Blender 5.2 LTS and will not install on older supported versions. Blender must be fully restarted after updates; reloading scripts can leave an old socket and handler active. Communication runs locally on `127.0.0.1`, and the project states that it collects no usage telemetry or analytics. The addon server must be running in Blender before an MCP client can use the tools.

_Full upstream README: https://allmcps.com/mcp/blenderwright/readme_

