mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-18 14:52:04 +00:00
refactor(skills): rework blender-mcp skill around the catalog MCP entry (#65066)
The optional blender-mcp skill predates the blender MCP catalog entry (#64463) and taught the agent to hand-roll raw TCP JSON to the addon's socket on port 9876 from execute_code — bypassing the catalog's version pinning and install-time tool curation. Reworked to v2.0.0 as the companion skill for the catalog entry: - prerequisites now go through 'hermes mcp install blender' - interaction surface is the four curated MCP tools, not a raw socket - keeps the valuable content: addon setup, bpy recipes (materials, keyframes, render-to-file), pitfalls (timeouts, absolute paths, object mode), plus new pitfalls (xvfb headless, no-sandbox warning, remote-host path resolution) - explicit anti-pattern note: do not hand-roll TCP to 9876 - description shortened to <=60 chars per skill authoring standards alireza78a's original bpy patterns and pitfalls are preserved and credited. Docs page regenerated via generate-skill-docs.py (scoped to this skill only; unrelated generator drift left untouched).
This commit is contained in:
parent
6a8e7069b4
commit
6efec39ecf
3 changed files with 168 additions and 136 deletions
|
|
@ -1,94 +1,88 @@
|
|||
---
|
||||
name: blender-mcp
|
||||
description: Control Blender directly from Hermes via socket connection to the blender-mcp addon. Create 3D objects, materials, animations, and run arbitrary Blender Python (bpy) code. Use when user wants to create or modify anything in Blender.
|
||||
version: 1.0.0
|
||||
requires: Blender 4.3+ (desktop instance required, headless not supported)
|
||||
author: alireza78a
|
||||
description: Drive Blender via the catalog blender MCP, with bpy recipes.
|
||||
version: 2.0.0
|
||||
requires: Blender 3.0+ desktop instance (headless via xvfb-run)
|
||||
author: alireza78a + Hermes Agent
|
||||
tags: [blender, 3d, animation, modeling, bpy, mcp]
|
||||
platforms: [linux, macos, windows]
|
||||
---
|
||||
|
||||
# Blender MCP
|
||||
# Blender MCP Skill
|
||||
|
||||
Control a running Blender instance from Hermes via socket on TCP port 9876.
|
||||
Companion skill for the `blender` entry in the Hermes MCP catalog. The MCP
|
||||
server provides the connection to Blender; this skill teaches the bpy idioms
|
||||
and pitfalls for driving it well. It does not cover Blender UI workflows —
|
||||
everything here goes through the MCP tools against a live Blender session.
|
||||
|
||||
## Setup (one-time)
|
||||
## When to Use
|
||||
|
||||
### 1. Install the Blender addon
|
||||
Use when the user wants to create or modify anything in a running Blender
|
||||
instance: meshes, materials, animations, lighting, renders. Requires the
|
||||
blender MCP server installed and a Blender desktop session with the addon
|
||||
connected.
|
||||
|
||||
curl -sL https://raw.githubusercontent.com/ahujasid/blender-mcp/main/addon.py -o ~/Desktop/blender_mcp_addon.py
|
||||
## Prerequisites
|
||||
|
||||
In Blender:
|
||||
Edit > Preferences > Add-ons > Install > select blender_mcp_addon.py
|
||||
Enable "Interface: Blender MCP"
|
||||
1. Install the MCP server from the Nous catalog (one-time):
|
||||
|
||||
### 2. Start the socket server in Blender
|
||||
hermes mcp install blender
|
||||
|
||||
Press N in Blender viewport to open sidebar.
|
||||
Find "BlenderMCP" tab and click "Start Server".
|
||||
This configures the pinned `blender-mcp` stdio server with the curated
|
||||
tool set: `get_scene_info`, `get_object_info`, `get_viewport_screenshot`,
|
||||
`execute_blender_code`.
|
||||
|
||||
### 3. Verify connection
|
||||
2. Install the addon inside Blender (one-time — the catalog entry's
|
||||
post-install notes cover this too):
|
||||
- Download https://raw.githubusercontent.com/ahujasid/blender-mcp/main/addon.py
|
||||
- Blender > Edit > Preferences > Add-ons > Install... > select addon.py,
|
||||
enable "Interface: Blender MCP".
|
||||
|
||||
nc -z -w2 localhost 9876 && echo "OPEN" || echo "CLOSED"
|
||||
3. Every session: start Blender FIRST, press N in the viewport, open the
|
||||
"BlenderMCP" tab, click "Connect to Claude" (starts the local bridge
|
||||
socket). Then start your Hermes session so the MCP tools are loaded.
|
||||
|
||||
## Protocol
|
||||
The addon refuses to start under `blender -b` (background mode). On a
|
||||
machine without a display, run Blender under a virtual one:
|
||||
`xvfb-run blender`. GPU rendering works fine under Xvfb.
|
||||
|
||||
Plain UTF-8 JSON over TCP -- no length prefix.
|
||||
## Quick Reference
|
||||
|
||||
Send: {"type": "<command>", "params": {<kwargs>}}
|
||||
Receive: {"status": "success", "result": <value>}
|
||||
{"status": "error", "message": "<reason>"}
|
||||
| MCP tool | Use for |
|
||||
|---------------------------|--------------------------------------------|
|
||||
| `get_scene_info` | List objects before touching the scene |
|
||||
| `get_object_info` | Inspect one object (transform, materials) |
|
||||
| `get_viewport_screenshot` | Visual check of what you built |
|
||||
| `execute_blender_code` | Everything else — arbitrary bpy Python |
|
||||
|
||||
## Available Commands
|
||||
Optional asset-service tools (PolyHaven, Sketchfab, Hyper3D, Hunyuan3D) are
|
||||
disabled by default. If the user has enabled a service in the addon panel,
|
||||
opt into its tools with `hermes mcp configure blender`.
|
||||
|
||||
| type | params | description |
|
||||
|-------------------------|-------------------|---------------------------------|
|
||||
| execute_code | code (str) | Run arbitrary bpy Python code |
|
||||
| get_scene_info | (none) | List all objects in scene |
|
||||
| get_object_info | object_name (str) | Details on a specific object |
|
||||
| get_viewport_screenshot | (none) | Screenshot of current viewport |
|
||||
## Procedure
|
||||
|
||||
## Python Helper
|
||||
1. Call `get_scene_info` first — never assume the scene is empty.
|
||||
2. Build with `execute_blender_code`, in small focused calls (one logical
|
||||
step per call: add objects, then materials, then animation). Large
|
||||
monolithic scripts hit the bridge timeout.
|
||||
3. Verify visually with `get_viewport_screenshot` between major steps.
|
||||
4. Render to an absolute path and tell the user where the file is.
|
||||
|
||||
Use this inside execute_code tool calls:
|
||||
### Common bpy Patterns
|
||||
|
||||
import socket, json
|
||||
Clear scene:
|
||||
|
||||
def blender_exec(code: str, host="localhost", port=9876, timeout=15):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((host, port))
|
||||
s.settimeout(timeout)
|
||||
payload = json.dumps({"type": "execute_code", "params": {"code": code}})
|
||||
s.sendall(payload.encode("utf-8"))
|
||||
buf = b""
|
||||
while True:
|
||||
try:
|
||||
chunk = s.recv(4096)
|
||||
if not chunk:
|
||||
break
|
||||
buf += chunk
|
||||
try:
|
||||
json.loads(buf.decode("utf-8"))
|
||||
break
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
except socket.timeout:
|
||||
break
|
||||
s.close()
|
||||
return json.loads(buf.decode("utf-8"))
|
||||
|
||||
## Common bpy Patterns
|
||||
|
||||
### Clear scene
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
### Add mesh objects
|
||||
Add mesh objects:
|
||||
|
||||
bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(0, 0, 0))
|
||||
bpy.ops.mesh.primitive_cube_add(size=2, location=(3, 0, 0))
|
||||
bpy.ops.mesh.primitive_cylinder_add(radius=0.5, depth=2, location=(-3, 0, 0))
|
||||
|
||||
### Create and assign material
|
||||
Create and assign material:
|
||||
|
||||
mat = bpy.data.materials.new(name="MyMat")
|
||||
mat.use_nodes = True
|
||||
bsdf = mat.node_tree.nodes.get("Principled BSDF")
|
||||
|
|
@ -97,21 +91,43 @@ Use this inside execute_code tool calls:
|
|||
bsdf.inputs["Metallic"].default_value = 0.0
|
||||
obj.data.materials.append(mat)
|
||||
|
||||
### Keyframe animation
|
||||
Keyframe animation:
|
||||
|
||||
obj.location = (0, 0, 0)
|
||||
obj.keyframe_insert(data_path="location", frame=1)
|
||||
obj.location = (0, 0, 3)
|
||||
obj.keyframe_insert(data_path="location", frame=60)
|
||||
|
||||
### Render to file
|
||||
Render to file:
|
||||
|
||||
bpy.context.scene.render.filepath = "/tmp/render.png"
|
||||
bpy.context.scene.render.engine = 'CYCLES'
|
||||
bpy.ops.render.render(write_still=True)
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Must check socket is open before running (nc -z localhost 9876)
|
||||
- Addon server must be started inside Blender each session (N-panel > BlenderMCP > Connect)
|
||||
- Break complex scenes into multiple smaller execute_code calls to avoid timeouts
|
||||
- Render output path must be absolute (/tmp/...) not relative
|
||||
- shade_smooth() requires object to be selected and in object mode
|
||||
- The blender MCP tools only exist if the server is installed and the session
|
||||
started after install. If they're missing, run `hermes mcp install blender`
|
||||
and start a new session.
|
||||
- The addon bridge must be (re)connected inside Blender each Blender session
|
||||
(N-panel > BlenderMCP > Connect). "Connection refused" from the tools means
|
||||
Blender isn't running or the addon isn't connected — fix that, don't retry.
|
||||
- Break complex scenes into multiple smaller `execute_blender_code` calls to
|
||||
avoid bridge timeouts.
|
||||
- Render output paths must be absolute (`/tmp/render.png`), not relative —
|
||||
they resolve on the BLENDER host's filesystem, which matters if Hermes and
|
||||
Blender run on different machines.
|
||||
- `shade_smooth()` requires the object to be selected and in object mode.
|
||||
- `execute_blender_code` runs arbitrary Python inside Blender with no sandbox
|
||||
— same trust level as the `terminal` tool. Don't paste untrusted code into
|
||||
it.
|
||||
- Do NOT hand-roll raw TCP JSON to port 9876 from `execute_code` — that was
|
||||
this skill's pre-MCP workaround. It bypasses the catalog's version pinning
|
||||
and tool curation. The MCP tools are the supported path.
|
||||
|
||||
## Verification
|
||||
|
||||
- `get_scene_info` returns the expected object list after each build step.
|
||||
- `get_viewport_screenshot` shows the scene you intended.
|
||||
- After a render, confirm the output file exists and report its absolute
|
||||
path to the user.
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ hermes skills uninstall <skill-name>
|
|||
|-------|-------------|
|
||||
| [**baoyu-article-illustrator**](/docs/user-guide/skills/optional/creative/creative-baoyu-article-illustrator) | Article illustrations: type × style × palette consistency. |
|
||||
| [**baoyu-comic**](/docs/user-guide/skills/optional/creative/creative-baoyu-comic) | Knowledge comics (知识漫画): educational, biography, tutorial. |
|
||||
| [**blender-mcp**](/docs/user-guide/skills/optional/creative/creative-blender-mcp) | Control Blender directly from Hermes via socket connection to the blender-mcp addon. Create 3D objects, materials, animations, and run arbitrary Blender Python (bpy) code. Use when user wants to create or modify anything in Blender. |
|
||||
| [**blender-mcp**](/docs/user-guide/skills/optional/creative/creative-blender-mcp) | Drive Blender via the catalog blender MCP, with bpy recipes. |
|
||||
| [**concept-diagrams**](/docs/user-guide/skills/optional/creative/creative-concept-diagrams) | Generate flat, minimal light/dark-aware SVG diagrams as standalone HTML files, using a unified educational visual language with 9 semantic color ramps, sentence-case typography, and automatic dark mode. Best suited for educational and no... |
|
||||
| [**creative-ideation**](/docs/user-guide/skills/optional/creative/creative-creative-ideation) | Generate ideas via named methods from creative practice. |
|
||||
| [**hyperframes**](/docs/user-guide/skills/optional/creative/creative-hyperframes) | Create HTML-based video compositions, animated title cards, social overlays, captioned talking-head videos, audio-reactive visuals, and shader transitions using HyperFrames. HTML is the source of truth for video. Use when the user wants... |
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
title: "Blender Mcp — Control Blender directly from Hermes via socket connection to the blender-mcp addon"
|
||||
title: "Blender Mcp — Drive Blender via the catalog blender MCP, with bpy recipes"
|
||||
sidebar_label: "Blender Mcp"
|
||||
description: "Control Blender directly from Hermes via socket connection to the blender-mcp addon"
|
||||
description: "Drive Blender via the catalog blender MCP, with bpy recipes"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Blender Mcp
|
||||
|
||||
Control Blender directly from Hermes via socket connection to the blender-mcp addon. Create 3D objects, materials, animations, and run arbitrary Blender Python (bpy) code. Use when user wants to create or modify anything in Blender.
|
||||
Drive Blender via the catalog blender MCP, with bpy recipes.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
|
|
@ -16,8 +16,8 @@ Control Blender directly from Hermes via socket connection to the blender-mcp ad
|
|||
|---|---|
|
||||
| Source | Optional — install with `hermes skills install official/creative/blender-mcp` |
|
||||
| Path | `optional-skills/creative/blender-mcp` |
|
||||
| Version | `1.0.0` |
|
||||
| Author | alireza78a |
|
||||
| Version | `2.0.0` |
|
||||
| Author | alireza78a + Hermes Agent |
|
||||
| Platforms | linux, macos, windows |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
|
@ -26,87 +26,81 @@ Control Blender directly from Hermes via socket connection to the blender-mcp ad
|
|||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Blender MCP
|
||||
# Blender MCP Skill
|
||||
|
||||
Control a running Blender instance from Hermes via socket on TCP port 9876.
|
||||
Companion skill for the `blender` entry in the Hermes MCP catalog. The MCP
|
||||
server provides the connection to Blender; this skill teaches the bpy idioms
|
||||
and pitfalls for driving it well. It does not cover Blender UI workflows —
|
||||
everything here goes through the MCP tools against a live Blender session.
|
||||
|
||||
## Setup (one-time)
|
||||
## When to Use
|
||||
|
||||
### 1. Install the Blender addon
|
||||
Use when the user wants to create or modify anything in a running Blender
|
||||
instance: meshes, materials, animations, lighting, renders. Requires the
|
||||
blender MCP server installed and a Blender desktop session with the addon
|
||||
connected.
|
||||
|
||||
curl -sL https://raw.githubusercontent.com/ahujasid/blender-mcp/main/addon.py -o ~/Desktop/blender_mcp_addon.py
|
||||
## Prerequisites
|
||||
|
||||
In Blender:
|
||||
Edit > Preferences > Add-ons > Install > select blender_mcp_addon.py
|
||||
Enable "Interface: Blender MCP"
|
||||
1. Install the MCP server from the Nous catalog (one-time):
|
||||
|
||||
### 2. Start the socket server in Blender
|
||||
hermes mcp install blender
|
||||
|
||||
Press N in Blender viewport to open sidebar.
|
||||
Find "BlenderMCP" tab and click "Start Server".
|
||||
This configures the pinned `blender-mcp` stdio server with the curated
|
||||
tool set: `get_scene_info`, `get_object_info`, `get_viewport_screenshot`,
|
||||
`execute_blender_code`.
|
||||
|
||||
### 3. Verify connection
|
||||
2. Install the addon inside Blender (one-time — the catalog entry's
|
||||
post-install notes cover this too):
|
||||
- Download https://raw.githubusercontent.com/ahujasid/blender-mcp/main/addon.py
|
||||
- Blender > Edit > Preferences > Add-ons > Install... > select addon.py,
|
||||
enable "Interface: Blender MCP".
|
||||
|
||||
nc -z -w2 localhost 9876 && echo "OPEN" || echo "CLOSED"
|
||||
3. Every session: start Blender FIRST, press N in the viewport, open the
|
||||
"BlenderMCP" tab, click "Connect to Claude" (starts the local bridge
|
||||
socket). Then start your Hermes session so the MCP tools are loaded.
|
||||
|
||||
## Protocol
|
||||
The addon refuses to start under `blender -b` (background mode). On a
|
||||
machine without a display, run Blender under a virtual one:
|
||||
`xvfb-run blender`. GPU rendering works fine under Xvfb.
|
||||
|
||||
Plain UTF-8 JSON over TCP -- no length prefix.
|
||||
## Quick Reference
|
||||
|
||||
Send: {"type": "<command>", "params": {<kwargs>}}
|
||||
Receive: {"status": "success", "result": <value>}
|
||||
{"status": "error", "message": "<reason>"}
|
||||
| MCP tool | Use for |
|
||||
|---------------------------|--------------------------------------------|
|
||||
| `get_scene_info` | List objects before touching the scene |
|
||||
| `get_object_info` | Inspect one object (transform, materials) |
|
||||
| `get_viewport_screenshot` | Visual check of what you built |
|
||||
| `execute_blender_code` | Everything else — arbitrary bpy Python |
|
||||
|
||||
## Available Commands
|
||||
Optional asset-service tools (PolyHaven, Sketchfab, Hyper3D, Hunyuan3D) are
|
||||
disabled by default. If the user has enabled a service in the addon panel,
|
||||
opt into its tools with `hermes mcp configure blender`.
|
||||
|
||||
| type | params | description |
|
||||
|-------------------------|-------------------|---------------------------------|
|
||||
| execute_code | code (str) | Run arbitrary bpy Python code |
|
||||
| get_scene_info | (none) | List all objects in scene |
|
||||
| get_object_info | object_name (str) | Details on a specific object |
|
||||
| get_viewport_screenshot | (none) | Screenshot of current viewport |
|
||||
## Procedure
|
||||
|
||||
## Python Helper
|
||||
1. Call `get_scene_info` first — never assume the scene is empty.
|
||||
2. Build with `execute_blender_code`, in small focused calls (one logical
|
||||
step per call: add objects, then materials, then animation). Large
|
||||
monolithic scripts hit the bridge timeout.
|
||||
3. Verify visually with `get_viewport_screenshot` between major steps.
|
||||
4. Render to an absolute path and tell the user where the file is.
|
||||
|
||||
Use this inside execute_code tool calls:
|
||||
### Common bpy Patterns
|
||||
|
||||
import socket, json
|
||||
Clear scene:
|
||||
|
||||
def blender_exec(code: str, host="localhost", port=9876, timeout=15):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((host, port))
|
||||
s.settimeout(timeout)
|
||||
payload = json.dumps({"type": "execute_code", "params": {"code": code}})
|
||||
s.sendall(payload.encode("utf-8"))
|
||||
buf = b""
|
||||
while True:
|
||||
try:
|
||||
chunk = s.recv(4096)
|
||||
if not chunk:
|
||||
break
|
||||
buf += chunk
|
||||
try:
|
||||
json.loads(buf.decode("utf-8"))
|
||||
break
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
except socket.timeout:
|
||||
break
|
||||
s.close()
|
||||
return json.loads(buf.decode("utf-8"))
|
||||
|
||||
## Common bpy Patterns
|
||||
|
||||
### Clear scene
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
### Add mesh objects
|
||||
Add mesh objects:
|
||||
|
||||
bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(0, 0, 0))
|
||||
bpy.ops.mesh.primitive_cube_add(size=2, location=(3, 0, 0))
|
||||
bpy.ops.mesh.primitive_cylinder_add(radius=0.5, depth=2, location=(-3, 0, 0))
|
||||
|
||||
### Create and assign material
|
||||
Create and assign material:
|
||||
|
||||
mat = bpy.data.materials.new(name="MyMat")
|
||||
mat.use_nodes = True
|
||||
bsdf = mat.node_tree.nodes.get("Principled BSDF")
|
||||
|
|
@ -115,21 +109,43 @@ Use this inside execute_code tool calls:
|
|||
bsdf.inputs["Metallic"].default_value = 0.0
|
||||
obj.data.materials.append(mat)
|
||||
|
||||
### Keyframe animation
|
||||
Keyframe animation:
|
||||
|
||||
obj.location = (0, 0, 0)
|
||||
obj.keyframe_insert(data_path="location", frame=1)
|
||||
obj.location = (0, 0, 3)
|
||||
obj.keyframe_insert(data_path="location", frame=60)
|
||||
|
||||
### Render to file
|
||||
Render to file:
|
||||
|
||||
bpy.context.scene.render.filepath = "/tmp/render.png"
|
||||
bpy.context.scene.render.engine = 'CYCLES'
|
||||
bpy.ops.render.render(write_still=True)
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Must check socket is open before running (nc -z localhost 9876)
|
||||
- Addon server must be started inside Blender each session (N-panel > BlenderMCP > Connect)
|
||||
- Break complex scenes into multiple smaller execute_code calls to avoid timeouts
|
||||
- Render output path must be absolute (/tmp/...) not relative
|
||||
- shade_smooth() requires object to be selected and in object mode
|
||||
- The blender MCP tools only exist if the server is installed and the session
|
||||
started after install. If they're missing, run `hermes mcp install blender`
|
||||
and start a new session.
|
||||
- The addon bridge must be (re)connected inside Blender each Blender session
|
||||
(N-panel > BlenderMCP > Connect). "Connection refused" from the tools means
|
||||
Blender isn't running or the addon isn't connected — fix that, don't retry.
|
||||
- Break complex scenes into multiple smaller `execute_blender_code` calls to
|
||||
avoid bridge timeouts.
|
||||
- Render output paths must be absolute (`/tmp/render.png`), not relative —
|
||||
they resolve on the BLENDER host's filesystem, which matters if Hermes and
|
||||
Blender run on different machines.
|
||||
- `shade_smooth()` requires the object to be selected and in object mode.
|
||||
- `execute_blender_code` runs arbitrary Python inside Blender with no sandbox
|
||||
— same trust level as the `terminal` tool. Don't paste untrusted code into
|
||||
it.
|
||||
- Do NOT hand-roll raw TCP JSON to port 9876 from `execute_code` — that was
|
||||
this skill's pre-MCP workaround. It bypasses the catalog's version pinning
|
||||
and tool curation. The MCP tools are the supported path.
|
||||
|
||||
## Verification
|
||||
|
||||
- `get_scene_info` returns the expected object list after each build step.
|
||||
- `get_viewport_screenshot` shows the scene you intended.
|
||||
- After a render, confirm the output file exists and report its absolute
|
||||
path to the user.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue