MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

Control Blender with AI via the Model Context Protocol — 69 tools, BVH assembly analysis, thread-safe bpy execution, 499 tests

Created 3/10/2026
Updated about 8 hours ago
Repository documentation and setup instructions

Inspired by blender-mcp by Siddharth Ahuja — the original proof-of-concept that demonstrated connecting AI agents to Blender over MCP. This project builds on that idea with a production-grade architecture: 69 tool groups, 550+ actions, multilingual intent routing, BVH assembly analysis, thread-safe execution, and a 499-test suite.


Blender MCP

Control Blender with AI — naturally, reliably, at production scale.

Give Claude, GPT, or any MCP-capable AI the ability to create, inspect, and animate 3D scenes in Blender using plain language and structured tool calls.

Python 3.10+ Blender 5.0+ MCP License: MIT


What is this?

MCP (Model Context Protocol) is an open standard that lets AI assistants call structured tools — the same way a programmer calls an API. This project implements an MCP server that bridges your AI assistant to a live Blender session running on your computer.

In practice: tell your AI "create a red metallic sphere above the cube" or "check if all drone parts are touching" and it will call the right Blender tools, get real geometry data back, and show you a screenshot — no Python required from your side.

Local-only. Blender must be installed and running on your machine. The bpy API only exists inside Blender's own Python — there is no cloud version.

execute_blender_code is the primary tool. Almost everything you can do with the other 68 tools can also be done directly with execute_blender_code (which gives full bpy Python access). The specialized tools exist for three reasons: they provide structured, validated inputs the AI can use reliably; they implement complex operations (like BVH assembly analysis or multi-view screenshots) that would be verbose to write from scratch each time; and they are useful for learning how specific Blender operations work.

Note on tool errors. Some tools may return errors in certain Blender states (e.g. sculpt tools require an active mesh in sculpt mode, render tools require a camera). The AI may also occasionally call a tool with slightly wrong parameters — this is normal. The parameter validator will coerce or reject bad values with a clear error message, and the AI will self-correct on the next attempt. If a tool consistently fails, execute_blender_code can usually accomplish the same thing directly.


Architecture

System diagram
Claude / AI Agent
       │  stdio  (JSON-RPC 2.0 / MCP)
       ▼
stdio_bridge.py              ← MCP bridge  [standard Python, runs outside Blender]
       │                       · Validates JSON schemas before forwarding
       │                       · Caches tool list from Blender on first connect
       │  TCP localhost:9879  (4-byte Big-Endian length-prefix + JSON body)
       ▼
Blender Addon                ← blender_mcp/__init__.py  [runs inside Blender]
  ├── dispatcher.py            Command router + handler registry (HANDLER_REGISTRY)
  ├── handlers/                52 handler modules (manage_*.py)
  │     manage_scene_comprehension.py   11-action scene intelligence suite
  │     manage_rendering.py             Render, screenshot, view control
  │     manage_scripting.py             execute_blender_code (safe eval)
  │     polyhaven / sketchfab / hunyuan / hyper3d  (4 external integrations)
  └── core/
        protocol.py           Wire protocol (4-byte header + JSON)
        thread_safety.py      All bpy calls routed to Blender's main thread
        execution_engine.py   Safe bpy.ops wrapper + ExecutionPolicy
        parameter_validator.py Type coercion + JSON schema validation
        intent_router.py      Multi-language intent classification (EN/TR/FR)
        semantic_memory.py    Tag-based object resolution
        security.py           High Mode / Safe Mode toggle
        job_manager.py        Async subprocess + internal job queue

All bpy operations are marshalled to Blender's main thread via bpy.app.timers, preventing EXCEPTION_ACCESS_VIOLATION crashes that would occur if a background TCP thread touched the Blender API directly.

See docs/ARCHITECTURE.md for detailed diagrams.


Installation

Prerequisites

| Requirement | Version | Notes | |-------------|---------|-------| | Platform | Windows / macOS / Linux | All three are supported — the MCP protocol and wire format are platform-agnostic | | Blender | 5.0 or later | Must be installed and running locally | | Python | 3.10 or later | For the MCP bridge (outside Blender) | | uv | latest | Recommended — fast, isolated environments | | git | any | To clone the repository |

Step 1 — Clone the repository

git clone https://github.com/glonorce/Blender_mcp.git
cd Blender_mcp

Step 2 — Set up the Python environment

Using uv (recommended)
# Create .venv and install all dependencies in one command
uv sync --all-extras

# Verify everything works (no Blender needed for tests)
uv run pytest tests/unit -q
# → 499 passed in ~1.4s

uv sync creates .venv/ in the project directory — your system Python stays clean. All uv run <cmd> calls use this environment automatically, no manual activation needed.

Using pip (alternative)
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate

pip install -e ".[dev]"

Step 3 — Build the Blender addon ZIP

python create_release_zip.py
# → blender_mcp_v1.0.0.zip

Step 4 — Install the addon in Blender

Blender → Edit → Preferences → Add-ons → Install
  → select blender_mcp_v1.0.0.zip
  → enable "Blender MCP"

The addon starts a TCP server on port 9879 automatically. Verify: press N in the 3D Viewport → MCP tab → status should show Listening on :9879.


MCP Client Configuration

Replace <path-to-blender-mcp> with the absolute path where you cloned this repo.

Claude Desktopclaude_desktop_config.json

Windows: %APPDATA%\Claude\claude_desktop_config.json macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "blender": {
      "command": "python",
      "args": ["-u", "<path-to-blender-mcp>/stdio_bridge.py"],
      "env": {
        "BLENDER_HOST": "localhost",
        "BLENDER_PORT": "9879",
        "MCP_TRANSPORT": "stdio",
        "PYTHONPATH": "<path-to-blender-mcp>"
      }
    }
  }
}
Cursor / Windsurf / VS Code.cursor/mcp.json or .vscode/mcp.json
{
  "mcpServers": {
    "blender": {
      "command": "python",
      "args": ["-u", "<path-to-blender-mcp>/stdio_bridge.py"],
      "env": {
        "BLENDER_HOST": "localhost",
        "BLENDER_PORT": "9879",
        "MCP_TRANSPORT": "stdio",
        "PYTHONPATH": "<path-to-blender-mcp>"
      }
    }
  }
}
OpenAI Codex CLI~/.codex/config.toml
[mcp_servers.blender]
command = "python"
args = ["-u", "<path-to-blender-mcp>/stdio_bridge.py"]
cwd = "<path-to-blender-mcp>"
enabled = true

[mcp_servers.blender.env]
BLENDER_HOST = "localhost"
BLENDER_PORT = "9879"
MCP_TRANSPORT = "stdio"
PYTHONPATH = "<path-to-blender-mcp>"
Generic shell / .env
export BLENDER_HOST=localhost
export BLENDER_PORT=9879
export MCP_TRANSPORT=stdio
export PYTHONPATH=<path-to-blender-mcp>

python -u <path-to-blender-mcp>/stdio_bridge.py

-u flag — disables Python's stdout/stderr buffering. Required for stdio transport. Without it, MCP messages may be held in Python's internal buffer and never reach the client.

Environment variables reference

| Variable | Default | Description | |----------|---------|-------------| | BLENDER_HOST | localhost | Hostname where Blender's addon is listening | | BLENDER_PORT | 9879 | TCP port of the Blender addon | | MCP_TRANSPORT | stdio | Transport mode (stdio for all current clients) | | PYTHONPATH | — | Must include the project root so blender_mcp is importable |


Verify the Connection

Tool: get_server_status
→ {
    "status": "active",
    "blender_version": [5, 0, 0],
    "blender_language": "en_US",
    "handler_count": 69,
    "next_step": "Call list_all_tools to see all available tools…"
  }

Recommended First Workflow

1. manage_agent_context  GET_PRIMER       → full quick-start guide for the AI
2. get_scene_graph       GET_OBJECTS_FLAT → what objects exist + world positions
3. get_viewport_screenshot_base64         → see the current viewport
4. execute_blender_code                   → create or modify objects
5. get_viewport_screenshot_base64         → confirm the result visually

ESSENTIAL Tools (priority 1–9)

These 9 tools handle the vast majority of tasks. The AI discovers them first.

| Pri | Tool | Purpose | |-----|------|---------| | 1 | execute_blender_code | Full bpy Python API — the primary tool for everything | | 2 | get_scene_graph | 11-action scene intelligence suite | | 3 | get_viewport_screenshot_base64 | Visual verification — see what Blender sees | | 4 | get_object_info | Deep object inspector — modifiers, constraints, animation | | 5 | get_local_transforms | Parent-relative coordinates | | 6 | manage_agent_context | Workflow guides (GET_PRIMER, GET_TACTICS) | | 7 | list_all_tools | Tool discovery with intent filtering (77% token savings) | | 8 | get_server_status | Health check — version, language, handler count | | 9 | new_scene | Create an empty scene |

⚡ execute_blender_code

The primary and most powerful tool. Executes arbitrary Python with full bpy access inside Blender.

Note: Almost all of the other 68 tools are essentially wrappers around things you can also do with execute_blender_code. The specialized tools add structured validation, complex analysis algorithms, and clear action names — which makes them more reliable and readable for AI agents. But for one-off operations or learning what bpy can do, execute_blender_code is often the fastest path.

One hardcoded guard: bpy.ops.render.render() is always blocked — it freezes Blender's main thread for the entire render duration, making the MCP unresponsive. Use manage_rendering action=RENDER_FRAME instead (async subprocess).

# Create a metallic sphere
import bpy, bmesh
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, location=(0, 0, 1))
obj = bpy.context.active_object
mat = bpy.data.materials.new("Metal")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Metallic"].default_value = 1.0
bsdf.inputs["Roughness"].default_value = 0.1
obj.data.materials.append(mat)
print(f"Created: {obj.name}")

🔍 get_scene_graph

11-action scene intelligence suite. The AI uses this to understand what's in the scene before modifying it.

All 11 actions

| Action | Description | |--------|-------------| | GET_OBJECTS_FLAT | All objects: world transforms, hierarchy, matrix_world, geometry_center_world | | GET_SCENE_MATRIX | Deep spatial analysis: AABB center, nearest neighbors, distances | | ANALYZE_ASSEMBLY | Integrity score 0–100: BVH surface gaps, interpenetration, hierarchy-aware pairs | | CHECK_INTERSECTION | AABB intersection test between two objects | | GET_SPATIAL_REPORT | Spatial summary for one object: bounds, nearby objects | | CAST_RAY | Ray cast from origin=[x,y,z] in direction=[dx,dy,dz] | | VERIFY_ASSEMBLY | Rule-based checks: must_touch, parent_must_be | | DETECT_GEOMETRY_ERRORS | Per-object: non_manifold_edges, boundary_edges, zero_area_faces | | GEOMETRY_COMPLEXITY | Triangle/vertex/ngon counts + complexity tier | | CHECK_PRODUCTION_READINESS | Manifold, UV, materials, naming, origin alignment; score 0–100 | | GET_HIERARCHY_TREE | BFS parent→children tree up to max_depth |

📸 get_viewport_screenshot_base64

Captures the viewport as a base64 PNG the AI can directly see and reason about.

Key parameters

| Parameter | Example | Description | |-----------|---------|-------------| | view_direction | "MULTI" | FRONT, RIGHT, TOP, ISOMETRIC, or MULTI (all four) | | target_objects | ["Arm_L", "Body"] | Frame specific objects instead of full scene | | gap_focus_m | 0.002 | Auto-zoom to show a gap of this distance | | display_mode | "MATERIAL" | SOLID, MATERIAL, or WIREFRAME | | action | "SMART_SCREENSHOT" | Automatically picks the best view |


Tool Tier System

The AI context window would overflow if all 69 tools were listed in full detail every time. The tier system solves this:

| Tier | Priority | Count | Format in list_all_tools | |------|----------|-------|---------------------------| | ESSENTIAL | 1–9 | 9 | Full detail — title, description, all parameters | | CORE | 10–49 | ~35 | Compact table row | | STANDARD | 50–149 | ~20 | Compact table row | | OPTIONAL | 150+ | 4 | Listed last (external integrations) |

# Filter by intent — reduces 69 tools to ~15 relevant ones (77% fewer tokens)
list_all_tools(intent="rig a character")
list_all_tools(intent="physics simulation")
list_all_tools(intent="export to Unity")

Supports English, Turkish, and French intent keywords.


Key Features

Assembly Intelligence

get_scene_graph ANALYZE_ASSEMBLY gives a full integrity report:

  • BVH surface-gap measurement — actual vertex-to-face distance, not just bounding-box
  • INTERPENETRATION detection — BVH face overlap, not just AABB
  • Hierarchy-aware pairs — always tests parent↔child; skips distant objects to avoid O(N²)
  • Production readiness score 0–100 — manifold geometry, UV maps, materials, naming, origin alignment
Thread Safety

All bpy calls from the TCP socket thread are automatically marshalled to Blender's main thread via bpy.app.timers. This prevents EXCEPTION_ACCESS_VIOLATION crashes that occur when background threads touch the Blender API.

Multilingual Intent Routing

list_all_tools(intent="...") accepts keywords in English, Turkish, and French. The intent router maps your description to tool categories and returns only the relevant subset — dramatically reducing context window usage.

Visual Verification

get_viewport_screenshot_base64 captures the viewport and returns it as base64 the AI can see:

  • Multi-view in one call: FRONT, RIGHT, TOP, ISOMETRIC
  • gap_focus_m — zoom precisely to the scale of an assembly gap
  • target_objects — frame specific parts, not the whole scene

Testing

Tests run without Blender — bpy is mocked with unittest.mock.MagicMock.

uv run pytest tests/unit -q              # 499 unit tests, ~1.4s
uv run pytest tests -v --tb=short        # Full suite
uv run pytest tests -v --cov=blender_mcp # With coverage report
uv run python scripts/quality/run_checks.py --fast   # 8 quality checks
uv run python scripts/quality/run_checks.py          # 12 quality checks
Coverage map — 17 test files

| Module | Test File | Tests | |--------|-----------|-------| | 8 ESSENTIAL handlers | test_essential_tools.py | 183 | | core/parameter_validator.py | test_parameter_validator.py | 60 | | core/intent_router.py | test_intent_router.py | 35 | | core/execution_engine.py | test_execution_engine.py | 31 | | dispatcher.py | test_dispatcher_deep.py + test_dispatch_routing.py | 51 | | core/semantic_memory.py | test_semantic_memory.py | 25 | | core/job_manager.py | test_job_manager.py | 25 | | core/response_builder.py | test_response_builder.py | 21 | | core/protocol.py | test_protocol.py | 17 | | core/error_protocol.py | test_error_protocol.py | 13 | | Project structure | test_smoke.py | 10 | | MCP bridge validation | test_engine.py | 9 | | handlers/manage_history.py | test_manage_history.py | 9 | | core/security.py | test_security.py | 6 | | Geometry center computation | test_scene_graph_geo_center.py | 6 | | Total | 17 test files | 499 |

See tests/TESTS.md for full documentation.


Developer Guide

Environment setup
uv sync --all-extras          # Install all dependencies
Quality gates
make check           # 12 checks: lint + format + type-check + tests
make check-fast      # 8 checks: lint + custom checks
make test-fast       # Unit tests only, stop on first failure
Tool inspection
make inspect-summary        # Compact table of all 69 tools
make inspect-essential      # ESSENTIAL tier full detail
uv run python scripts/inspect_tools.py --tool get_scene_graph
uv run python scripts/inspect_tools.py --cat animation
Adding a new handler

Create a file in blender_mcp/handlers/ with @register_handler. Auto-discovered — no list to update.

from ..dispatcher import register_handler

@register_handler(
    "manage_my_feature",
    actions=["CREATE", "DELETE", "LIST"],
    schema={
        "type": "object",
        "properties": {
            "action": {"type": "string", "enum": ["CREATE", "DELETE", "LIST"]},
            "name":   {"type": "string"},
        },
        "required": ["action"],
    },
    category="scene",
    priority=60,          # 1-9=ESSENTIAL, 10-49=CORE, 50-149=STANDARD, 150+=OPTIONAL
    description="STANDARD — Create, delete, and list my features.",
)
def manage_my_feature(action, **params):
    if action == "CREATE":
        return {"created": params.get("name")}
    elif action == "LIST":
        return {"items": []}
Scripts reference

See scripts/SCRIPTS.md for comprehensive documentation of every script.

python -m blender_mcp --help        # Quick CLI overview
python -m blender_mcp --list-tools  # List all tools
python -m blender_mcp --status      # Project health

Project Structure

Click to expand
Blender_mcp/
├── blender_mcp/                     Blender addon (installs via ZIP)
│   ├── __init__.py                  Addon entry + BlenderMCPServer + N-panel UI
│   ├── __main__.py                  python -m blender_mcp CLI
│   ├── dispatcher.py                Handler registry + dispatch_command
│   ├── __version__.py               Single source of version truth
│   ├── handlers/                    52 handler modules
│   │   ├── manage_scene_comprehension.py   get_scene_graph (11 actions)
│   │   ├── manage_rendering.py             RENDER_FRAME, screenshot
│   │   ├── manage_scripting.py             execute_blender_code
│   │   ├── manage_agent_context.py         GET_PRIMER, GET_TACTICS
│   │   ├── manage_history.py               Session checkpoints
│   │   ├── get_local_transforms.py         Parent-relative coordinates
│   │   ├── polyhaven_handler.py            Polyhaven CC0 assets
│   │   ├── sketchfab_handler.py            Sketchfab 3D models
│   │   ├── hunyuan_handler.py              Hunyuan3D AI generation
│   │   ├── hyper3d_handler.py              Hyper3D Rodin AI generation
│   │   └── ...                             40+ more handlers
│   └── core/
│       ├── protocol.py              Wire protocol (4-byte header + JSON)
│       ├── thread_safety.py         Main-thread routing via bpy.app.timers
│       ├── execution_engine.py      Safe bpy.ops + ExecutionPolicy
│       ├── parameter_validator.py   Type coercion + schema validation
│       ├── intent_router.py         Multi-language intent classification
│       ├── semantic_memory.py       Tag-based object resolution
│       ├── security.py              High Mode / Safe Mode
│       ├── job_manager.py           Async subprocess queue
│       ├── response_builder.py      Structured response format
│       └── error_protocol.py        280+ ErrorCode enum values
├── stdio_bridge.py                  MCP bridge (runs outside Blender)
├── scripts/
│   ├── SCRIPTS.md                   Full scripts documentation
│   ├── inspect_tools.py             Tool catalog inspector
│   ├── count_tools.py               Handler count audit
│   ├── sync_version.py              Version synchronization
│   ├── test_blender_imports.py      Runtime import validation (needs Blender)
│   ├── remove_unused_ignores.py     mypy cleanup helper
│   └── quality/
│       ├── run_checks.py            Quality gate (8–12 checks)
│       ├── check_version.py         Version consistency
│       ├── check_forbidden.py       Fatal Blender 5.x pattern scanner
│       ├── check_handler_completeness.py  Registry audit
│       ├── check_handler_imports.py Import style validator
│       ├── check_schemas.py         JSON schema validator
│       ├── check_tool_groups.py     Tool group integrity
│       └── lint_imports.py          Import architecture rules
├── tests/
│   ├── unit/                        499 unit tests (17 files, no Blender needed)
│   ├── integration/                 24 mock + live integration tests
│   └── TESTS.md                     Test suite documentation
├── docs/
│   └── ARCHITECTURE.md              System design, wire protocol, thread model
├── create_release_zip.py            Builds the addon ZIP for Blender
├── Makefile                         Developer shortcuts
├── pyproject.toml                   Build + lint + type-check config
└── LICENSE                          MIT License

Contribution Guidelines

  1. Use @register_handler decorator on all handlers — no exceptions
  2. @ensure_main_thread on any handler that calls bpy
  3. No bpy.types.SimpleNamespace — not available in Blender 5.x
  4. No eval/exec outside the execute_blender_code security layer
  5. Use MCPLogger / get_logger() instead of print()
  6. Run make check before committing — all 12 checks must pass
  7. Add unit tests for new logic in tests/unit/

Log Files

| Component | Windows | macOS / Linux | |-----------|---------|---------------| | Addon (Blender side) | %TEMP%\blender_server_debug.log | /tmp/blender_server_debug.log | | Bridge (MCP side) | %TEMP%\mcp_bridge_debug.log | /tmp/mcp_bridge_debug.log |


License

MIT License — © 2026 GÖKSEL ÖZKAN

Quick Setup
Installation guide for this server

Install Package (if required)

uvx blender_mcp

Cursor configuration (mcp.json)

{ "mcpServers": { "glonorce-blender-mcp": { "command": "uvx", "args": [ "blender_mcp" ] } } }