MCP Servers

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

Blender addon that starts a local TCP server (port 9876) so Claude / Cowork can execute Python code inside Blender via MCP.

Created 5/4/2026
Updated about 4 hours ago
Repository documentation and setup instructions

Blender MCP Server Addon

Execute Python code inside a running Blender instance from any MCP client — including Claude Cowork, Claude Code, or your own tooling.


What it does

This Blender addon starts a lightweight TCP server on localhost:9876 when Blender launches. Any MCP client can then send Python code and receive the result in real-time — with full access to bpy, all scene data, and Blender's Python API.

Claude / Cowork  ──TCP JSON──►  Blender MCP Addon  ──exec()──►  bpy
                ◄──JSON result──                   ◄──result────

Key features

  • Zero configuration — installs as a standard Blender addon, auto-starts on launch
  • Full bpy access — create meshes, apply modifiers, render, import/export, anything
  • stdout captureprint() output is returned alongside the result
  • Robust error handling — Python exceptions are caught and returned as structured JSON; the server never crashes
  • Stale-socket cleanup — automatically closes leftover sockets from previous sessions (critical on Windows)
  • Configurable port — change the port from Blender's addon preferences
  • N-Panel UI — Start / Stop / Restart buttons in the 3D Viewport sidebar (N key → MCP tab)
  • Compatible with Blender 4.0 → 5.x (tested on 4.2 LTS and 5.1.1)

Installation

Option A — Install from file (recommended)

  1. Download blender_mcp_addon.py
  2. In Blender: Edit → Preferences → Add-ons → Install…
  3. Select the downloaded .py file and click Install Add-on
  4. Enable the checkbox next to "MCP Server"
  5. Click Save Preferences (hamburger icon → Save Preferences)

The server starts automatically the next time Blender opens. You can also start it immediately from 3D Viewport → N-Panel → MCP → Start Server.

Option B — Copy manually

# Linux / macOS
cp blender_mcp_addon.py ~/.config/blender/4.x/scripts/addons/

# Windows
copy blender_mcp_addon.py "%APPDATA%\Blender Foundation\Blender\4.x\scripts\addons\"

Then enable it in Edit → Preferences → Add-ons (search for "MCP Server").


Usage

With Claude Cowork / Claude Code

Install the official Blender MCP connector from the Claude extensions marketplace. Once both the connector and this addon are active, Claude can directly control Blender — no further setup needed.

Example prompt:

"Create a low-poly house with a red roof and two trees on a green ground plane."

With any MCP client

Send a JSON request over TCP to localhost:9876:

{"type": "execute", "code": "result = {'objects': len(bpy.data.objects)}", "strict_json": false}

Terminate the frame with a null byte (\0). The response is also null-byte delimited:

{"status": "ok", "result": {"objects": 3}, "stdout": ""}

Direct Python test

import socket, json

def run_in_blender(code: str) -> dict:
    req = json.dumps({"type": "execute", "code": code, "strict_json": False}) + "\0"
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect(("localhost", 9876))
        s.sendall(req.encode())
        buf = bytearray()
        while b"\0" not in buf:
            buf.extend(s.recv(65536))
    return json.loads(buf.split(b"\0")[0])

# Example
print(run_in_blender("result = {'version': bpy.app.version_string}"))
# → {'status': 'ok', 'result': {'version': '5.1.1'}, 'stdout': ''}

Returning data

Assign a JSON-serialisable dict to a variable named result:

code = """
import bpy
result = {
    "objects": [obj.name for obj in bpy.data.objects],
    "scene":   bpy.context.scene.name,
}
"""

Non-serialisable values (Blender objects, vectors, etc.) are automatically converted via repr() rather than raising an error.


Protocol reference

| Field | Type | Description | |-------|------|-------------| | type | "execute" | Always "execute" (reserved for future commands) | | code | str | Python source to execute inside Blender | | strict_json | bool | Ignored by this addon (kept for compatibility) |

Response

| Field | Type | Description | |-------|------|-------------| | status | "ok" | "error" | Execution outcome | | result | any | Value assigned to result in user code (on success) | | stdout | str | Text printed to stdout/stderr during execution | | message | str | Full Python traceback (on error) |


Architecture

Blender main thread
│
├── register()
│   ├── bpy.utils.register_class(…)   ← UI operators & panel
│   └── bpy.app.timers.register(_auto_start, first_interval=0.5)
│
└── _tick()  [every 50 ms, persistent timer]
    └── exec(code, {"bpy": bpy, "result": None})
        └── writes result to sys.modules["_blender_mcp_srv"].st.rm

Background threads
├── _accept_loop(srv_sock)            ← waits for TCP connections
└── _handle(conn)  [one per client]
    ├── recv request
    ├── push (tid, code) onto task queue
    ├── poll result map until result appears
    └── send response

Why sys.modules?
Blender's timer callbacks run inside exec(), which has its own scope. Storing state in a custom entry in sys.modules ensures it persists across calls, restarts, and the addon's own exec() execution context.

Why stale-socket cleanup?
On Windows, SO_REUSEADDR allows multiple sockets to bind the same port simultaneously. Without cleanup, old server instances (e.g. from a previous exec(open(...).read()) in the Blender console) keep intercepting connections. The cleanup function uses gc.get_objects() to find and close any socket bound to the same port other than the current server socket.


Troubleshooting

"Connection refused" / "Cannot connect to Blender"

  • Make sure the addon is enabled in Blender preferences
  • Check the N-Panel (3D Viewport → N → MCP) — the status should show ● Running
  • If the status shows ○ Stopped, click Start Server
  • Verify no firewall is blocking localhost:9876

"Empty response from Blender" / timeout

Click Restart in the N-Panel. This purges any stale state and re-binds the port cleanly.

Port already in use

Change the port in Edit → Preferences → Add-ons → MCP Server → Port, then restart the server.

Blender 5.x: KeyError: 'Principled BSDF'

In Blender 5.x the Principled BSDF node is no longer auto-created. Always create it explicitly:

nodes.clear()
bsdf = nodes.new('ShaderNodeBsdfPrincipled')
out  = nodes.new('ShaderNodeOutputMaterial')
links.new(bsdf.outputs['BSDF'], out.inputs['Surface'])

bpy.ops.*.poll() failed, context is incorrect

bpy.ops operators require a valid context. When possible, use the bpy.data / bmesh API directly (no context needed). For operators that truly require a VIEW_3D context:

for window in bpy.context.window_manager.windows:
    for area in window.screen.areas:
        if area.type == 'VIEW_3D':
            for region in area.regions:
                if region.type == 'WINDOW':
                    with bpy.context.temp_override(window=window, area=area, region=region):
                        bpy.ops.object.shade_flat()

Changelog

v1.3.0 (2026-05-04)

  • Configurable port via addon preferences
  • auto_start toggle in preferences
  • Improved protocol error handling (JSON / UTF-8 decode errors)
  • server_restart() public function
  • _close_stale_sockets() returns count of sockets closed
  • English UI and docstrings
  • doc_url and tracker_url in bl_info

v1.2.0

  • Stale-socket cleanup via gc.get_objects() (fixes Windows SO_REUSEADDR issue)
  • N-Panel with Start / Stop / Restart buttons
  • _auto_start deferred timer (0.5 s) to let Blender initialise first
  • Persistent state in sys.modules[_MOD] to survive exec() scope issues

v1.1.0

  • Initial working version with bpy.app.timers main-thread execution
  • stdout/stderr capture per request
  • JSON default=str fallback for non-serialisable values

License

GPL-3.0-or-later — the same license as Blender itself.


Author

Olivier HoarauTarraw974@gmail.com

Contributions, issues and pull requests are welcome!

Quick Setup
Installation guide for this server

Install Package (if required)

uvx blender-mcp-addon

Cursor configuration (mcp.json)

{ "mcpServers": { "oli97430-blender-mcp-addon": { "command": "uvx", "args": [ "blender-mcp-addon" ] } } }