Skip to content

Commit 4be2cea

Browse files
TMHSDigitalclaude
andcommitted
feat(plugin): register the Blender Lab MCP server for live sessions
Both plugin manifests now set "mcpServers": "./mcp.json", which launches the official Blender Lab MCP server (projects.blender.org/lab/blender_mcp) with uvx from a pinned upstream commit (dbbf836). The server is GPL-3.0, so the plugin references it and does not vendor it. The plugin-dist build ships mcp.json and fails if a manifest's mcpServers path is missing. check_manifest_meta requires both manifests to name the same file and every server in it to be pinned to a full 40-hex SHA. README gains a "Live Blender session (MCP)" setup section covering uv, the Blender 5.1+ add-on, env vars and safety. CLAUDE/AGENTS/CONTRIBUTING no longer say there is no MCP server. Headless runs remain the only source of correctness evidence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent e09b641 commit 4be2cea

9 files changed

Lines changed: 65 additions & 10 deletions

File tree

‎.claude-plugin/plugin.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"homepage": "https://tmhsdigital.github.io/Blender-Developer-Tools/",
1010
"repository": "https://github.com/TMHSDigital/Blender-Developer-Tools",
1111
"license": "CC-BY-NC-ND-4.0 AND MIT",
12+
"mcpServers": "./mcp.json",
1213
"skills": [
1314
"./claude/skills/"
1415
],

‎.cursor-plugin/plugin.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"blender-addon",
2020
"blender-python"
2121
],
22+
"mcpServers": "./mcp.json",
2223
"skills": [
2324
"skills/addon-scaffolding/SKILL.md",
2425
"skills/ai-mesh-cleanup/SKILL.md",

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repeats the other.
1515

1616
Skills, rules, snippets, starter templates, and runnable smoke-gated examples
1717
for Blender Python development. The repo targets **Blender 5.2 LTS** (current
18-
stable) with a **Blender 4.5 LTS** fallback. **Blender 5.1** is prior stable. There is no MCP server. It ships
18+
stable) with a **Blender 4.5 LTS** fallback. **Blender 5.1** is prior stable. The repo ships no MCP server of its own; the plugin's `mcp.json` registers the upstream Blender Lab server (pinned commit, launched with `uvx`) for optional live sessions. It ships
1919
a `.cursor-plugin/plugin.json` manifest so the ecosystem drift checker
2020
classifies it as a `cursor-plugin`. This is content the AI loads when the user
2121
asks Blender questions or works on Blender add-ons in Cursor or Claude Code.

‎CLAUDE.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
88

99
## Project Overview
1010

11-
The **Blender Developer Tools** repository is at **v0.152.1**. It packages skills, rules, snippets, starter templates, and runnable smoke-gated examples for Blender Python development with Cursor and Claude Code. Coverage targets **Blender 5.2 LTS** (current stable) with **Blender 4.5 LTS** fallback. **Blender 5.1** is prior stable. There is no MCP server; content is consumed directly by the AI when working in Blender add-on or scripting projects.
11+
The **Blender Developer Tools** repository is at **v0.152.1**. It packages skills, rules, snippets, starter templates, and runnable smoke-gated examples for Blender Python development with Cursor and Claude Code. Coverage targets **Blender 5.2 LTS** (current stable) with **Blender 4.5 LTS** fallback. **Blender 5.1** is prior stable. The repo ships no MCP server of its own: the plugin registers the official Blender Lab server through `mcp.json` (see Live MCP vs Headless Harness). Content is consumed directly by the AI when working in Blender add-on or scripting projects.
1212

1313
**Version:** 0.152.1
1414
**License:** CC-BY-NC-ND-4.0
@@ -148,7 +148,7 @@ cross-example import mechanism (see its docstring).
148148

149149
## Live MCP vs Headless Harness
150150

151-
Two execution paths exist for Blender work. The headless harness (`.scratch/` or system binaries, check-only scripts, CI smoke) is the **only source of truth for correctness** — every witness, check, and CI gate runs headless. The official Blender Lab MCP server ([lab/blender_mcp](https://projects.blender.org/lab/blender_mcp)), when registered on the local machine, provides a live interactive session for exploration.
151+
Two execution paths exist for Blender work. The headless harness (`.scratch/` or system binaries, check-only scripts, CI smoke) is the **only source of truth for correctness** — every witness, check, and CI gate runs headless. The official Blender Lab MCP server ([lab/blender_mcp](https://projects.blender.org/lab/blender_mcp)), when registered on the local machine, provides a live interactive session for exploration. The plugin ships it: both manifests set `"mcpServers": "./mcp.json"`, which runs `uvx --from git+https://projects.blender.org/lab/blender_mcp.git@<sha>#subdirectory=mcp blender-mcp`. `tests/check_manifest_meta.py` requires a full 40-hex commit pin, and `build_plugin_dist.py` ships `mcp.json` and fails if a manifest's path is missing. To bump it, review the upstream diff, replace the SHA, and confirm `initialize` + `tools/list` over stdio. The server is GPL-3.0: reference it, never vendor it. The add-on needs Blender 5.1+.
152152

153153
- **Use the live MCP for:** interactively inspecting a scene while designing a render, querying data relations, diagnosing why staged geometry or lighting looks wrong, and prototyping API calls before committing them to a script.
154154
- **Never use the live MCP for:** anything a check depends on, anything reported as verification evidence, or anything CI must reproduce. A behavior observed in the live session must be re-proven in the headless script before it counts. Examples must never import from, depend on, or assume the MCP server.

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ see the end of this file). Examples and showcase pieces have more gates
4949

5050
## Repository Structure
5151

52-
This repo is a content collection (skills, rules, snippets, templates, examples, and showcase pieces) for Blender Python development. There is no runtime and no MCP server. Headless checks run through `tests/smoke/run_example.py`; CI validates frontmatter, syntax, and aggregate counts.
52+
This repo is a content collection (skills, rules, snippets, templates, examples, and showcase pieces) for Blender Python development. There is no runtime and no MCP server of its own; `mcp.json` only registers the upstream Blender Lab MCP server for the plugin, pinned to a commit that `tests/check_manifest_meta.py` requires. Headless checks run through `tests/smoke/run_example.py`; CI validates frontmatter, syntax, and aggregate counts.
5353

5454
```text
5555
skills/

‎README.md‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
This repository ships **18 skills, 9 rules, 3 templates, 29 snippets, 66 examples, and 80 showcase pieces** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable.
4848

49-
The content is consumed by AI coding agents, installed as a plugin or read from a checkout — **there is no MCP server in this repository, and none is required**. Cursor and Claude Code both install it as a plugin (see [Quick start](#quick-start)): Cursor loads the skills and applies `rules/*.mdc` wherever their scope globs match; Claude Code loads the skills and gets the rules through a generated `blender-rules` skill, since it does not read Cursor `.mdc` files. An agent picks a skill up when its description matches the task. Any agent that can read files in a workspace can use it the same way. There is no build step for the content — edit the Markdown and Python files directly.
49+
The content is consumed by AI coding agents, installed as a plugin or read from a checkout. The plugin also registers the official [Blender Lab MCP server](https://www.blender.org/lab/mcp-server/) for live sessions (see [Live Blender session](#live-blender-session-mcp)); it is referenced from upstream, not part of this repository, and nothing else depends on it. Cursor and Claude Code both install it as a plugin (see [Quick start](#quick-start)): Cursor loads the skills and applies `rules/*.mdc` wherever their scope globs match; Claude Code loads the skills and gets the rules through a generated `blender-rules` skill, since it does not read Cursor `.mdc` files. An agent picks a skill up when its description matches the task. Any agent that can read files in a workspace can use it the same way. There is no build step for the content — edit the Markdown and Python files directly.
5050

5151
| Layer | Role |
5252
| --- | --- |
@@ -79,6 +79,16 @@ Neither agent needs a clone of `main`: both install the slim `plugin-dist` build
7979

8080
Claude Code does not read Cursor `.mdc` rules, so the plugin ships them as the `blender-rules` skill (generated from `rules/`), which Claude loads when it writes or reviews bpy code. No second clone is needed. To keep the rules in context all the time instead, add `@/path/to/Blender-Developer-Tools/claude/blender-rules.md` to your project's `CLAUDE.md` from a checkout. Without the plugin, copy `skills/*` and `claude/skills/*` into your project's `.claude/skills/`.
8181

82+
### Live Blender session (MCP)
83+
84+
Both plugin manifests point at [`mcp.json`](mcp.json), which registers the official [Blender Lab MCP server](https://www.blender.org/lab/mcp-server/) as `blender`, so the agent can inspect and drive a running Blender: scene and object summaries, screenshots, viewport renders, `bpy` execution and bundled API docs. The plugin launches it with `uvx` from [projects.blender.org/lab/blender_mcp](https://projects.blender.org/lab/blender_mcp), pinned to a reviewed commit. The server is GPL-licensed and is not copied into this repository. To use it:
85+
86+
1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) so `uvx` is on `PATH`. The first launch fetches and builds the server.
87+
2. In **Blender 5.1 or newer** (the add-on's minimum, so 4.5 LTS has no live session), install the MCP add-on: zip `addon/blender_mcp_addon/` from the upstream repository and use **Edit → Preferences → Get Extensions → Install from Disk**. Start its server from the add-on preferences, or turn on auto-start. It listens on `localhost:9876`.
88+
3. Optional: set `BLENDER_PATH` if `blender` is not on `PATH` (the `*_for_cli` tools use it to run background Blender), and `BLENDER_MCP_HOST`/`BLENDER_MCP_PORT` to move the socket.
89+
90+
The server runs whatever code the agent sends inside your Blender session, without guards, so attach it only to scenes you can afford to lose. Without the add-on running, the `blender` tools just report that they cannot connect; the skills and rules work the same either way. If you already registered the server yourself, remove one of the two entries so the tools are not listed twice.
91+
8292
### Run the examples or contribute
8393

8494
The examples, the showcase and the gallery live on `main` (about 30 MB with the renders), so clone it only to run them or to send a change:

‎mcp.json‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"mcpServers": {
3+
"blender": {
4+
"type": "stdio",
5+
"command": "uvx",
6+
"args": [
7+
"--from",
8+
"git+https://projects.blender.org/lab/blender_mcp.git@dbbf836ad4b1025f14a2b3b504c43903f39e0b04#subdirectory=mcp",
9+
"blender-mcp"
10+
]
11+
}
12+
}
13+
}

‎scripts/build_plugin_dist.py‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
as a self-contained marketplace (its marketplace.json points at "./"):
77
88
skills/ claude/ rules/ snippets/ templates/ LICENSE files
9-
.claude-plugin/ and .cursor-plugin/ manifests, the Cursor logo, and a short README
9+
.claude-plugin/ and .cursor-plugin/ manifests, the Cursor logo, mcp.json,
10+
and a short README
1011
1112
python scripts/build_plugin_dist.py --out DIR # build (DIR must be absent or empty)
1213
python scripts/build_plugin_dist.py --out DIR --force # replace a previous build in DIR
@@ -32,10 +33,12 @@
3233
DIRS = ("skills", "claude", "rules", "snippets", "templates")
3334
# The Cursor manifest ships too, so Cursor users can install the same slim
3435
# tree as a local plugin (~/.cursor/plugins/local/) instead of the full repo.
35-
# assets/favicon.svg is the Cursor manifest's "logo".
36+
# assets/favicon.svg is the Cursor manifest's "logo". mcp.json is both
37+
# manifests' "mcpServers": the Blender Lab MCP server, launched with uvx from
38+
# a pinned upstream commit (GPL, so it is referenced, never vendored).
3639
FILES = ("LICENSE", ".claude-plugin/plugin.json",
3740
".cursor-plugin/plugin.json", ".cursor-plugin/marketplace.json",
38-
"assets/favicon.svg")
41+
"assets/favicon.svg", "mcp.json")
3942
MAX_BYTES = 2_000_000
4043
IGNORE = shutil.ignore_patterns("__pycache__", "*.pyc")
4144

@@ -44,7 +47,9 @@
4447
Generated from https://github.com/TMHSDigital/Blender-Developer-Tools by
4548
`scripts/build_plugin_dist.py` on every release. Do not edit this branch; it
4649
is force-pushed. It carries only what the plugin loads: skills, the
47-
`blender-rules` skill generated from `rules/`, snippets, templates and licenses.
50+
`blender-rules` skill generated from `rules/`, snippets, templates, licenses,
51+
and `mcp.json`, which registers the official Blender Lab MCP server (needs `uv`,
52+
and the MCP add-on enabled in a running Blender 5.1+).
4853
Examples, the showcase and the gallery live on `main`.
4954
5055
```text
@@ -153,6 +158,10 @@ def verify(out: Path, size: int) -> list[str]:
153158
if not (out / "claude" / "skills" / "blender-rules" / "SKILL.md").is_file():
154159
errors.append("blender-rules skill missing")
155160
cursor = json.loads((out / ".cursor-plugin" / "plugin.json").read_text(encoding="utf-8"))
161+
for name, manifest in (("Claude", plugin), ("Cursor", cursor)):
162+
mcp = manifest.get("mcpServers")
163+
if isinstance(mcp, str) and not (out / mcp).is_file():
164+
errors.append(f"{name} manifest mcpServers path {mcp} missing from the dist")
156165
for key in ("skills", "rules"):
157166
for rel in cursor.get(key, []):
158167
if not (out / rel).is_file():

‎tests/check_manifest_meta.py‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,22 @@
1212
- keywords: the same set, apart from the agent-specific "cursor-plugin"
1313
- logo: the Cursor manifest names one, it exists, and the plugin-dist build
1414
ships it (scripts/build_plugin_dist.py FILES)
15+
- mcpServers: the same path in both plugin.json files, and every server in
16+
that file runs the Blender Lab MCP from a full 40-hex commit pin, so a plugin
17+
install never floats to an unreviewed upstream head
1518
1619
Run: python tests/check_manifest_meta.py (exit 0 ok, 1 on mismatch)
1720
"""
1821
from __future__ import annotations
1922

2023
import html
2124
import json
25+
import re
2226
import sys
2327
from pathlib import Path
2428

2529
ROOT = Path(__file__).resolve().parent.parent
30+
PINNED_MCP = re.compile(r"^git\+https://projects\.blender\.org/lab/blender_mcp\.git@[0-9a-f]{40}#subdirectory=mcp$")
2631

2732

2833
def load(rel: str) -> dict:
@@ -80,6 +85,22 @@ def check() -> list[str]:
8085
if logo not in FILES:
8186
errors.append(f"logo {logo!r} is not shipped in the plugin-dist build "
8287
"(scripts/build_plugin_dist.py FILES)")
88+
89+
mcp = cursor.get("mcpServers")
90+
if claude.get("mcpServers") != mcp:
91+
errors.append(f".claude-plugin/plugin.json mcpServers {claude.get('mcpServers')!r} != {mcp!r}")
92+
if not isinstance(mcp, str) or not (root / mcp).is_file():
93+
errors.append(f".cursor-plugin/plugin.json mcpServers {mcp!r} is not a file in the repo")
94+
else:
95+
servers = load(mcp).get("mcpServers") or {}
96+
if not servers:
97+
errors.append(f"{mcp} declares no mcpServers")
98+
for name, server in servers.items():
99+
args = server.get("args", [])
100+
src = args[args.index("--from") + 1] if "--from" in args[:-1] else ""
101+
if server.get("command") != "uvx" or not PINNED_MCP.match(src):
102+
errors.append(f"{mcp} server {name!r} must run uvx --from the Blender Lab repo "
103+
"pinned to a full commit SHA")
83104
return errors
84105

85106

@@ -89,7 +110,7 @@ def main() -> int:
89110
print(f"::error::{e}", file=sys.stderr)
90111
if errors:
91112
return 1
92-
print("Manifest metadata consistent: description, homepage, license, keywords, logo")
113+
print("Manifest metadata consistent: description, homepage, license, keywords, logo, mcpServers")
93114
return 0
94115

95116

0 commit comments

Comments
 (0)