Skip to main content
Glama
sattua

Blender MCP Server

by sattua
README.md
# Blender MCP Server

MCP server for **Cursor** that controls **Blender** through a local HTTP bridge.  
`bpy` runs **inside Blender** — this repo does not import bpy in the MCP process.

**Separate from [Summit](../summit)** — export `.glb` files to Summit's `Assets/` when ready.

## Architecture

```
Cursor Agent → MCP (this repo) → HTTP bridge → bpy → Blender
```

| Path | Role |
|------|------|
| `server.py` | MCP entry (stdio) |
| `mcp_server/` | Tools exposed to the agent |
| `blender_addon/blender_mcp_bridge/` | Blender addon (HTTP + bpy commands) |
| `config.json` | Bridge port, Summit export paths, default `.blend` |

Blender 5.1: `/home/juan/blender-5.1.2/blender`

## Quick start

### 1. Install MCP server (Python)

```bash
cd /home/juan/source/blender_mcp_server
./scripts/setup_mcp.sh
cp config.example.json config.json   # edit paths if needed
```

### 2. Install Blender addon

```bash
BLENDER_VERSION=5.1 ./scripts/install_addon.sh
# Detect version: ls ~/.config/blender/
```

In Blender:

1. **Edit → Preferences → Add-ons** → enable **Blender MCP Bridge**
2. **N panel → MCP tab → Start Server** (default `http://127.0.0.1:9876`)

Or start headless with the default export blend:

```bash
./scripts/start_bridge.sh
```

Logs: `bridge.log` in this repo. Override blend: `BLENDER_MCP_BLEND=/path/to/file.blend ./scripts/start_bridge.sh`

### 3. Connect Cursor

Merge `cursor.mcp.example.json` into `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "blender": {
      "command": "/home/juan/source/blender_mcp_server/.venv/bin/python",
      "args": ["/home/juan/source/blender_mcp_server/server.py"],
      "env": {
        "BLENDER_MCP_CONFIG": "/home/juan/source/blender_mcp_server/config.json"
      }
    }
  }
}
```

Restart Cursor. Open this folder as workspace when animating.

### 4. Test

With Blender bridge running:

```bash
curl -s http://127.0.0.1:9876/health
```

In Cursor chat (with MCP enabled):

> Use ping_blender, then scene_information

## MCP tools

**Connection:** `ping_blender`, `get_server_config`

**Inspection:** `scene_information`, `list_objects`, `list_armatures`, `list_bones`, `list_actions`, `get_object_transform`

**Animation:** `create_action`, `rename_action`, `set_active_action`, `set_frame`, `set_bone_rotation_keyframe`, `set_action_loop_mode`

**Export / validate:** `export_gltf`, `export_to_summit`, `validate_scene_scale`, `validate_action_root_motion`, `validate_rts_asset`, `render_preview`

**Modeling (recipes):** `create_summit_bobcat` — low-poly harvester blockout + `idle` / `harvest` animations

### Bridge-only commands (not MCP tools yet)

Callable via `scripts/run_command.py` or HTTP bridge dispatch:

| Command | Purpose |
|---------|---------|
| `create_natural_idle_action` | Breathing idle from a pose frame (quaternion offsets) |
| `create_rifle_attack_action` | Forward rifle aim + recoil clip |
| `create_idle_action` | Static hold from source action |
| `prepare_rifleman_locomotion` | Import walk GLB, remap bones, strip hip motion, create idle |
| `duplicate_action` | Copy an action |
| `strip_action_root_motion` | Remove root bone location keys |

## Human Rifleman pipeline (current)

Source blends live under `~/Documents/BlenderSaves/summit/`:

| File | Content |
|------|---------|
| `riflemenStand.blend` | `idle` — natural breathing (~48 frames) |
| `riflemenwalk.blend` | `walk` — in-place **rifle run** sprint (22 frames) |
| `riflemenfire.blend` | `attack` — rifle aim + recoil (~24 frames) |
| `riflemenExport.blend` | Merged master (idle + walk + attack) |
| `riflemen-backup-dont-edit.blend` | Safety backup |

**Regenerate walk + attack from stand** (run FBX + procedural fire), then merge + export:

```bash
/home/juan/blender-5.1.2/blender --background --python scripts/prepare_rifleman_animations.py
```

**Body textures (Ch36):** merge exports from `riflemenStand.blend` (painted mesh). The exporter rebuilds `Ch36_Body` for glTF PBR and syncs packed images into the GLB. If sidecar PNGs look stale in Godot, reimport `Rifleman.glb` or run:

```bash
/home/juan/blender-5.1.2/blender --background --python scripts/fix_and_export_rifleman_body.py
/home/juan/blender-5.1.2/blender --background --python scripts/extract_textures_from_glb.py
```

**Re-export only** (if walk/fire blends already exist):

```bash
/home/juan/blender-5.1.2/blender --background --python scripts/prepare_rifleman_export.py
```

Output: `/home/juan/source/summit/Assets/Units/Human/Rifleman.glb`  
Godot view: `Scenes/Units/HumanRiflemanView.tscn` (animations `idle`, `walk`, `attack`).

Rifle mesh is parented to `mixamorig1:RightHand` in the fire blend. Attack uses explicit aim quaternions (+Y barrel forward), not a copied walk pose.

Or export from the open blend via MCP:

```
export_to_summit(target_key="summit_human_units", filename="Rifleman.glb", action_names=["idle","walk","attack"])
```

## Bobcat harvester (vehicle recipe)

### V2 (RTS parts catalog — recommended)

Procedural **Generals-style** assembly from reusable mechanical parts:

```bash
BLENDER_VERSION=5.1 ./scripts/install_addon.sh
/home/juan/blender-5.1.2/blender --background --python scripts/create_summit_bobcat_v2.py
```

Output blend: `~/Documents/BlenderSaves/summit/bobcatExport.blend`  
Silhouette preview: `~/Documents/BlenderSaves/summit/bobcat_v2_silhouette.png`  
Output GLB: `/home/juan/source/summit/Assets/Units/Human/Bobcat.glb` (`idle`, `harvest`)

MCP: `create_summit_bobcat_v2`, `validate_rts_asset`, `validate_rts_silhouette`, `render_rts_silhouette_preview`

Parts catalog (`modeling/parts/`): cabin, wheel, bucket, hydraulic, chassis, fender, exhaust, headlight, arm, grille.

Animated pivots (stable Godot contract): `Bobcat_Arm_L`, `Bobcat_Arm_R`, `Bobcat_Bucket`.

### V1 (blockout)

```bash
/home/juan/blender-5.1.2/blender --background --python scripts/create_summit_bobcat.py
```

## Summit export

Config keys in `config.json`:

```json
"export_targets": {
  "summit_human_units": "/home/juan/source/summit/Assets/Units/Human",
  "summit_props": "/home/juan/source/summit/Assets/Props"
}
```

Default blend: `riflemenExport.blend` (see `default_blend` in config).

Then switch workspace to `/home/juan/source/summit` to wire Godot views and sim.

## Summit conventions

| Rule | Value |
|------|--------|
| Scale | 1 Blender unit = 1 meter |
| Infantry height | ~**1.6 m** (`Ch36` reference mesh) |
| Forward | **+Y** in Blender |
| Animation names | `idle`, `walk`, `attack`, `death` (infantry); vehicles: `idle`, `harvest` |
| Vehicle tri budget | **2500** tris (blockout recipe) |
| Locomotion | Walk **in place** — no hip translation (`validate_action_root_motion`) |

See also Summit [player identity](../summit/docs/02-Architecture/player-identity.md) for **team color masks** when authoring units:

- Paint tint regions in Blender (vertex color or `*_TeamMask.png`)
- One GLB per unit type; player color applied at runtime in Godot
- Human = military paint zones; Robot = LED emissive mask; etc.

## Headless

```bash
blender mychar.blend --background --python scripts/run_command.py -- '{"command":"scene_information","args":{}}'
```

## Roadmap

- [x] Rifleman idle / walk / attack pipeline + `prepare_rifleman_export.py`
- [x] Bobcat blockout recipe + `create_summit_bobcat.py`
- [x] `validate_rts_asset` + MCP modeling tools
- [x] `create_natural_idle_action`, `create_rifle_attack_action` (bridge)
- [x] `start_bridge.sh` headless bridge daemon
- [ ] Expose locomotion commands as MCP tools
- [ ] Team color mask validation / export hints for Summit shader
- [ ] `death` animation for rifleman
- [ ] Rigging helpers
- [ ] Auto tool registration review gate

TDQS

B3.2/5.0

Scored across 32 tools

Disambiguation5/5

Each tool has a highly specific and unique purpose, from creating individual RTS models (e.g., create_summit_bobcat) to distinct validation and export operations. No two tools appear to overlap in functionality, ensuring an agent can reliably select the correct tool.

Naming Consistency5/5

Tool names follow a consistent verb_noun_snake_case pattern, with clear prefixes like create_, list_, validate_, and export_. Within each category, naming is uniform (e.g., create_summit_*_v# or validate_*), making the tool set predictable and easy to navigate.

Tool Count3/5

32 tools is on the high side, but the server is focused on a specialized RTS asset pipeline, which justifies many specific model creators and validators. However, the sheer number may overwhelm agents, and some generic operations could be consolidated.

Completeness4/5

The tool set covers the full lifecycle for the Summit RTS asset domain: creation of multiple specific models, validation of conventions, animation management, and export. Minor gaps exist (e.g., no geometry or material editing), but core workflows are well supported.