blender-mcp

Connect to and control Blender via the official Blender MCP Server. Supports two modes: full MCP Server + mcporter (recommended) and direct TCP Socket (lightweight). Covers 20 built-in tools plus arbitrary bpy code execution.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "blender-mcp" with this command: npx skills add taosiuman/blender-skill

Blender MCP Server Connection Skill

Connect to and control a running Blender instance via the official Blender MCP Server.

Version requirement: Blender 5.1+ (mandatory)


Architecture Overview

┌─────────────┐     TCP Socket      ┌──────────────────     MCP Protocol     ┌──────────────
│  LLM Client │ ◄─────────────────► │  MCP Server      │ ◄──────────────────► │   Blender    │
│  (OpenClaw) │    stdio / HTTP     │  (Python process) │    port 9876         │   (Addon)    │
└─────────────┘                     └──────────────────┘                      └──────────────

Two-component architecture:

  1. Blender Addon — runs inside Blender, provides a TCP Socket Server (default localhost:9876)
  2. MCP Server — standalone Python process that bridges the LLM client and the Blender Addon

Installation

1. Install the Blender Addon

Option A: From ZIP

  1. Download addon ZIP: https://projects.blender.org/lab/blender_mcp/releases/download/v1.0.0/mcp-1.0.0.zip
  2. Blender → Edit → Preferences → Add-ons → Install from Disk
  3. Enable the "Blender MCP" addon
  4. Confirm Host/Port in addon settings (default localhost:9876)

Option B: Drag & Drop

  • Drag the ZIP file into the Blender window (twice: first to add the Blender Lab repository, second to install the addon)

Option C: From Source

  • Source code locations: mcp/blmcp/ and addon/blender_mcp_addon/

2. Start the Blender MCP Server

# Install dependencies
cd path/to/blender_mcp
pip install mcp pyyaml starlette

# Start MCP Server (stdio mode)
python -m blmcp --transport stdio

# Or HTTP mode (default 127.0.0.1:8000)
python -m blmcp --transport http --host 127.0.0.1 --port 8000

3. Configure mcporter

# Add Blender MCP Server config
mcporter config add blender-mcp --transport stdio --command "python -m blmcp --transport stdio"

# Or use HTTP mode
mcporter config add blender-mcp --transport http --url "http://127.0.0.1:8000"

# Verify connection
mcporter list blender-mcp --schema

Usage

Method 1: Via mcporter (recommended)

# List all available tools
mcporter list blender-mcp --schema

# Call a specific tool
mcporter call blender-mcp.execute_blender_code code='import bpy; result = {"objects": [o.name for o in bpy.data.objects]}'

mcporter call blender-mcp.get_objects_summary

mcporter call blender-mcp.get_object_detail_summary object_name="Cube"

# Search API docs
mcporter call blender-mcp.search_api_docs query="bpy.ops.object.delete"

# Search user manual
mcporter call blender-mcp.search_manual_docs query="Geometry Nodes"

# Screenshot
mcporter call blender-mcp.get_screenshot_of_window_as_image

# Render viewport
mcporter call blender-mcp.render_viewport_to_path output_path="C:\\render.png"

Method 2: Direct TCP Socket to Blender Addon (lightweight)

⚠️ Warning: This mode sends caller-supplied code directly to Blender with no guardrails. Review code before execution.

When you don't need the full MCP Server, you can communicate directly with the Blender Addon via TCP Socket:

import socket
import json

def send_to_blender(code: str, host="localhost", port=9876, timeout=30.0) -> dict:
    """Send Python code directly to Blender Addon for execution."""
    request = json.dumps({
        "type": "execute",
        "code": code,
        "strict_json": False,
    }) + "\0"
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.settimeout(timeout)
        sock.connect((host, port))
        sock.sendall(request.encode("utf-8"))
        
        buf = bytearray()
        while True:
            chunk = sock.recv(65536)
            if not chunk:
                break
            buf.extend(chunk)
            if b"\0" in buf:
                break
    
    line, _, _ = buf.partition(b"\0")
    return json.loads(line.decode("utf-8"))

# Example: get all object names in the scene
response = send_to_blender(
    'import bpy\nresult = {"objects": [o.name for o in bpy.data.objects]}'
)
print(response)
# {"status": "ok", "result": {"objects": ["Cube", "Camera", "Light"]}}

Method 3: Blender Background Mode (headless rendering / batch)

# Start Blender background MCP Server
blender --background myscene.blend --command blender_mcp --host localhost --port 9876

# Or execute code via CLI
blender --background myscene.blend --python-expr "
import bpy
# your code
result = {'count': len(bpy.data.objects)}
print('__BLMCP_RESULT__' + str(result))
"

Built-in Tools (20 total)

Core

ToolDescriptionParams
execute_blender_codeExecute arbitrary Python code (full bpy access)code: str
execute_blender_code_for_cliExecute code in a background Blender processblend_file: str, code: str

Scene Analysis

ToolDescriptionParams
get_objects_summaryGet scene object hierarchy and basic infonone
get_object_detail_summaryGet detailed info for a specific objectobject_name: str
get_blendfile_summary_datablocksAnalyze .blend file data-blocksblend_file: str
get_blendfile_summary_missing_filesCheck for missing external file referencesblend_file: str
get_blendfile_summary_of_linked_librariesList linked external librariesblend_file: str
get_blendfile_summary_path_infoAnalyze .blend file path informationblend_file: str
get_blendfile_summary_usage_guessGuess the purpose of a .blend fileblend_file: str

Screenshots & Rendering

ToolDescriptionParams
get_screenshot_of_window_as_imageCapture Blender window screenshotnone
get_screenshot_of_area_as_imageCapture specific area screenshotarea_type: str
get_screenshot_of_window_as_jsonGet window layout as JSON descriptionnone
render_viewport_to_pathRender viewport to fileoutput_path: str
render_thumbnail_to_pathRender thumbnail to fileoutput_path: str

Navigation

ToolDescriptionParams
jump_to_tab_by_nameJump to a named editor tabtab_name: str
jump_to_tab_by_space_typeJump to a space typespace_type: str
jump_to_view3d_object_by_nameFocus on an object in 3D Viewobject_name: str
jump_to_view3d_object_data_by_nameFocus on object data in 3D Viewdata_name: str

Documentation Search

ToolDescriptionParams
search_api_docsSearch Blender Python API docsquery: str
search_manual_docsSearch Blender user manualquery: str
get_python_api_docsGet Python API docsquery: str

Communication Protocol

TCP Socket Protocol

Request format (null-byte delimited JSON):

{"type": "execute", "code": "import bpy\nresult = {'key': 'value'}", "strict_json": false}\0

Response format:

// Success
{"status": "ok", "result": {"key": "value"}, "stdout": "", "stderr": ""}\0

// Error
{"status": "error", "message": "Traceback...", "stdout": "", "stderr": ""}\0

Code Execution Conventions

  • Assign return value to the result variable (must be a dict)
  • strict_json=True: strict JSON serialization; non-serializable values will error
  • strict_json=False: uses repr() as fallback for non-JSON values
  • Supports deferred responses: return a check_is_finished callable for long-running tasks

Example: Get Object Info

import bpy
obj = bpy.data.objects.get("Cube")
if obj:
    result = {
        "name": obj.name,
        "type": obj.type,
        "location": list(obj.location),
        "vertices": len(obj.data.vertices) if obj.type == "MESH" else 0,
    }
else:
    result = {"error": "Object not found"}

Example: Create an Object

import bpy
bpy.ops.mesh.primitive_torus_add(
    align='WORLD',
    location=(0, 0, 0),
    major_radius=1.0,
    minor_radius=0.3,
)
result = {"status": "created", "name": bpy.context.active_object.name}

Environment Variables

VariableDefaultDescription
BLENDER_MCP_HOSTlocalhostBlender Addon host address
BLENDER_MCP_PORT9876Blender Addon port
BLENDER_PATHblenderPath to Blender executable

Security Notes

⚠️ Official security warning: The MCP Server executes LLM-generated code with no sandboxing.

Built-in weak sandbox (WeakSandboxForLLM):

  • Blocks sys.exit() calls
  • Blocks dangerous operators: wm.quit_blender, wm.read_factory_settings, wm.read_factory_userpref, wm.read_userpref

Security Best Practices

1. Keep server local only

  • Always use localhost / 127.0.0.1 — never bind to 0.0.0.0
  • Never expose port 9876 to your network or firewall rules
  • Stop the MCP server when not actively using it

2. Review code before execution

  • Prefer scoped built-in tools (e.g., get_objects_summary) over raw execute_blender_code for routine tasks
  • Review generated Python code before running, especially for:
    • File operations (save, export, delete)
    • Batch modifications (all objects, all materials)
    • External API calls (network requests, subprocess)

3. Protect your projects

  • Keep backups of important .blend files before running automated code
  • Test new code on a copy of your project first
  • Use version control for production scenes

4. Verify external dependencies

  • Download the MCP addon only from official Blender Lab sources
  • Verify pip package names (mcp, pyyaml, starlette) match official releases
  • Do not use unofficial mirrors or third-party builds

Recommendation: Run in a VM or on a system without sensitive data.


Troubleshooting

ErrorCauseSolution
ConnectionRefusedErrorBlender not running or Addon not startedStart Blender, enable MCP Addon, click "Start Server"
ConnectionError: Empty responseNetwork timeout or Addon crashedCheck Blender console output, verify port
result is not JSON-serializableReturned a Blender objectUse strict_json=False or manually convert to dict
Blender executable not foundBlender command not foundSet BLENDER_PATH environment variable
Deferred responses not supportedBackground mode doesn't support deferred responsesUse synchronous code or switch to GUI mode

Blender 5.1 API Compatibility Notes

Action Layered Structure (Breaking Change)

In Blender 5.1, Action.fcurves was removed. The new layered animation system uses:

# ❌ Old (5.0 and earlier)
fcurves = action.fcurves

# ✅ Blender 5.1+
fcurves = action.layers[0].strips[0].channelbags[0].fcurves

Principled BSDF Node Input Renames

Old (5.0)New (5.1)
inputs['Transmission']inputs['Transmission Weight']
inputs['Emission']inputs['Emission Color'] + inputs['Emission Strength']

OpenClaw Integration

Configure openclaw.json

{
  "plugins": {
    "entries": {
      "mcp": {
        "servers": {
          "blender-mcp": {
            "command": "python",
            "args": ["-m", "blmcp", "--transport", "stdio"],
            "cwd": "path/to/blender_mcp",
            "env": {
              "BLENDER_MCP_HOST": "localhost",
              "BLENDER_MCP_PORT": "9876"
            }
          }
        }
      }
    }
  }
}

Via mcporter CLI

# List tools
mcporter call blender-mcp.get_objects_summary

# Execute code
mcporter call blender-mcp.execute_blender_code code='import bpy; result = {"count": len(bpy.data.objects)}'

Quick Start Checklist

  • Blender 5.1+ installed
  • MCP Addon installed and enabled
  • MCP Server started (python -m blmcp --transport stdio)
  • mcporter installed (npm install -g mcporter)
  • Port 9876 available (default)
  • BLENDER_PATH environment variable set (if needed)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Peon Ping for Openclaw

Install and configure PeonPing with an opinionated default (Orc Peon voice) so alerts work immediately with minimal user friction. Use when the user asks for...

Registry SourceRecently Updated
General

Openclaw Skill Publish

Polymarket prediction markets: analytics, trading, hot markets, price movements, top traders, and market search. Powered by prob.trade.

Registry SourceRecently Updated
General

post-to-xhs

小红书内容发布与管理助手。当用户要求登录、发小红书、搜索小红书、评论点赞收藏等任何小红书相关操作时使用。

Registry SourceRecently Updated
General

Chat History Analyzer

Extracts and analyzes Cursor IDE chat history to identify key discoveries, obstacles, and solutions, saving findings to the journal.

Registry SourceRecently Updated