MCP Hub
Back to servers

chuk-mcp-stage

A specialized MCP server for orchestrating 3D scenes, camera choreography, and physics-driven animations, bridging Rapier simulations with React Three Fiber and Remotion video rendering.

Tools
9
Updated
Dec 2, 2025

chuk-mcp-stage

3D Scene & Camera MCP Server - The director layer between physics simulation and motion rendering

Python MCP Async

🌐 Quick Install: uvx stage.chukai.io/mcp

chuk-mcp-stage is the orchestration layer that bridges:

  • chuk-mcp-physics (Rapier simulations) → Scene animations
  • chuk-motion / Remotion (video rendering) → Export targets

It's the "director + set designer" that defines what's in the 3D world, where the camera goes, and how physics drives motion.


🎯 What This Does

Core capabilities:

  1. Scene Graph - Define 3D worlds (objects, materials, lighting)
  2. Camera Paths - Cinematography (orbit, chase, dolly, static shots)
  3. Physics Bridge - Bind scene objects to physics bodies (uses public Rapier service by default)
  4. Animation Baking - Convert physics simulations → keyframes
  5. Export - Generate R3F components, Remotion projects, glTF

The full pipeline:

Physics Simulation → Stage → Motion/Video
(chuk-mcp-physics) → (chuk-mcp-stage) → (chuk-motion/Remotion)

🚀 Quick Start

Installation

Option 1: Install from public URL (Recommended)

# Install directly from public URL with uvx
uvx stage.chukai.io/mcp

Option 2: Install from PyPI

pip install chuk-mcp-stage

Option 3: Install from source

cd chuk-mcp-stage
pip install -e .

Physics ready out-of-the-box! Uses the public Rapier service at https://rapier.chukai.io by default. No additional setup required for physics simulations.

Run the Server

# STDIO mode (default - for MCP clients like Claude Desktop)
uv run chuk-mcp-stage

# HTTP mode (REST API on port 8000)
uv run chuk-mcp-stage http

# Streamable mode (Server-Sent Events for streaming responses)
uv run chuk-mcp-stage streamable

Transport modes:

  • stdio: Standard MCP protocol via stdin/stdout (default for Claude Desktop)
  • http: HTTP REST API server on port 8000 (used by chuk-mcp-r3f-preview)
  • streamable: SSE (Server-Sent Events) transport for streaming responses

📖 Complete Transport Modes Guide - Detailed documentation, examples, and troubleshooting

Configure in Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

Option 1: Using public URL (Recommended)

{
  "mcpServers": {
    "stage": {
      "command": "uvx",
      "args": ["stage.chukai.io/mcp"],
      "env": {
        "RAPIER_SERVICE_URL": "https://rapier.chukai.io"
      }
    }
  }
}

Option 2: Using local installation

{
  "mcpServers": {
    "stage": {
      "command": "chuk-mcp-stage",
      "env": {
        "RAPIER_SERVICE_URL": "https://rapier.chukai.io"
      }
    }
  }
}

Physics Integration Configuration

chuk-mcp-stage integrates with physics simulations via chuk-mcp-physics and the Rapier physics engine.

Three Integration Methods:

  1. Direct Rapier HTTP (Default) - Fastest for simulations

    • Directly calls Rapier service HTTP API
    • Used by stage_bake_simulation tool
    • Defaults to public service: https://rapier.chukai.io
  2. Via MCP Tools - Most flexible

    • Use chuk-mcp-physics MCP server tools
    • Supports both analytic calculations and Rapier simulations
    • Requires chuk-mcp-physics server running
  3. Hybrid - Best of both worlds

    • Use MCP tools for simulation creation/setup
    • Use direct HTTP for baking trajectories

Environment Variables:

# Rapier service URL (default: https://rapier.chukai.io)
RAPIER_SERVICE_URL=https://rapier.chukai.io  # Public service
# RAPIER_SERVICE_URL=http://localhost:9000   # Local development

# Rapier timeout in seconds (default: 30.0)
RAPIER_TIMEOUT=30.0

# Physics provider type (default: auto)
PHYSICS_PROVIDER=auto  # or 'rapier', 'mcp'

Claude Desktop with Custom Rapier Service:

{
  "mcpServers": {
    "stage": {
      "command": "chuk-mcp-stage",
      "env": {
        "RAPIER_SERVICE_URL": "http://localhost:9000",
        "RAPIER_TIMEOUT": "60.0"
      }
    },
    "physics": {
      "command": "uvx",
      "args": ["chuk-mcp-physics"],
      "env": {
        "RAPIER_SERVICE_URL": "http://localhost:9000"
      }
    }
  }
}

Public Rapier Service:

  • URL: https://rapier.chukai.io
  • No authentication required
  • Rate limits may apply
  • Perfect for prototyping and demos

Local Rapier Service:

# Run locally with Docker
docker run -p 9000:9000 chuk-rapier-service

# Or from source
cd rapier-service && cargo run --release

See chuk-mcp-physics README for complete physics integration guide.

What's New in chuk-mcp-physics v0.3.1:

  • 52 physics tools (expanded from 27) - Now covers ~50% of common physics use cases
  • Rotational dynamics: Torque, moment of inertia, angular momentum calculations
  • Springs & oscillations: Simple harmonic motion, damped oscillations, pendulums
  • Circular motion: Orbital mechanics, centripetal force, escape velocity
  • Advanced collisions: 3D elastic/inelastic collisions with coefficient of restitution
  • Conservation laws: Energy and momentum verification for simulations
  • Fluid dynamics: Drag, buoyancy, terminal velocity, underwater motion

Google Drive OAuth Storage (HTTP Mode)

Store your scenes in Google Drive with OAuth 2.1 authentication for secure, persistent, user-owned storage!

When running in HTTP mode, chuk-mcp-stage supports Google Drive OAuth integration. Users authenticate via their browser, and scenes are stored in their own Google Drive under /CHUK/stage/.

Benefits:

  • Secure OAuth 2.1 - Industry-standard authentication with PKCE
  • User Owns Data - Scenes stored in user's Google Drive, not your infrastructure
  • Auto Token Refresh - Seamless authentication with automatic refresh
  • Cross-Device Access - Access scenes from any device with Drive
  • Built-in Sharing - Share scenes using Google Drive's native sharing
  • Natural Discoverability - View/edit scene files directly in Drive UI
  • No Infrastructure Cost - Zero storage costs for the provider

Setup Steps

1. Create Google Cloud Project:

  • Go to https://console.cloud.google.com/
  • Create new project (or select existing)
  • Enable Google Drive API
  • Go to OAuth consent screen:
    • User Type: External
    • Add your email as test user
  • Go to Credentials → Create OAuth 2.0 Client ID:
    • Application type: Web application
    • Authorized redirect URIs: http://localhost:8000/oauth/callback
  • Copy Client ID and Client Secret

2. Install with Google Drive Support:

pip install "chuk-mcp-stage[google_drive]"

3. Configure Environment:

# Copy example environment file
cp .env.example .env

# Edit .env and add your Google credentials:
# GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
# GOOGLE_CLIENT_SECRET=your-client-secret

4. Verify OAuth Integration (Optional but Recommended):

# Verify that OAuth setup works
python examples/verify_google_drive_oauth.py

This will verify:

  • OAuth provider initializes correctly
  • Credentials are valid
  • OAuth endpoints can be registered
  • Ready for Google Drive integration

5. Run Server in HTTP Mode:

# Load from .env file
uv run chuk-mcp-stage http

# Or set environment variables directly
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-client-secret"
uv run chuk-mcp-stage http

6. Authorize Access:

When Claude Desktop (or any MCP client) connects:

  1. OAuth flow automatically initiates
  2. Browser opens for Google authorization
  3. User grants access to Google Drive
  4. Tokens securely stored and auto-refreshed

OAuth Endpoints (automatically registered):

  • Authorization: http://localhost:8000/oauth/authorize
  • Token: http://localhost:8000/oauth/token
  • Discovery: http://localhost:8000/.well-known/oauth-authorization-server
  • Callback: http://localhost:8000/oauth/callback

Deployment to Fly.io

✅ OAuth is now configured for https://stage.chukai.io and https://physics.chukai.io

See OAUTH_SETUP_COMPLETE.md for details on the production OAuth setup.

For production deployments, set secrets instead of using .env:

# Set Google OAuth credentials as Fly secrets
fly secrets set GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
fly secrets set GOOGLE_CLIENT_SECRET="your-client-secret"

# Set OAuth server URL (use your Fly.io app URL)
fly secrets set OAUTH_SERVER_URL="https://your-app.fly.dev"
fly secrets set GOOGLE_REDIRECT_URI="https://your-app.fly.dev/oauth/callback"

# Optional: Configure session backend for production
fly secrets set SESSION_PROVIDER="redis"
fly secrets set SESSION_REDIS_URL="redis://your-redis-url:6379/0"

# Deploy
fly deploy

Important: Update Google Cloud Console with production redirect URI:

  • Add https://your-app.fly.dev/oauth/callback to authorized redirect URIs

Storage Providers

chuk-mcp-stage supports multiple storage backends - see STORAGE_CONFIGURATION.md for complete details.

Quick Comparison:

ProviderPersistenceCloud SyncOAuth RequiredSetupBest For
vfs-filesystem (default)✅ LocalZeroLocal dev
vfs-filesystem + OAuth✅ Persistent✅ Google DriveMediumProduction (small)
vfs-s3✅ Persistent✅ S3MediumProduction (large)
vfs-memory❌ RAM onlyZeroTesting only

Environment Variables:

# Storage provider selection (default: vfs-filesystem)
STORAGE_PROVIDER=vfs-filesystem

# Session metadata storage (default: memory)
SESSION_PROVIDER=memory

# For Redis sessions (production)
SESSION_PROVIDER=redis
REDIS_URL=redis://localhost:6379/0

# For AWS S3 storage
STORAGE_PROVIDER=vfs-s3
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
AWS_S3_BUCKET=chuk-artifacts
AWS_REGION=us-east-1

See STORAGE_CONFIGURATION.md for:

  • Detailed provider comparison
  • Migration guides
  • Production best practices
  • Troubleshooting

Where Your Scenes Live

With vfs-filesystem (default):

~/.chuk-artifacts/
└── grid/
    └── {sandbox_id}/
        └── {session_id}/
            └── {namespace_id}/
                ├── scene.json
                ├── animations/
                └── export/

With Google Drive (vfs-filesystem + OAuth):

Google Drive
└── chuk-artifacts/
    └── {user_id}/
        └── {namespace_id}/
            ├── scene.json
            ├── animations/
            │   └── cannonball.json
            └── export/
                └── remotion/

With AWS S3 (vfs-s3):

s3://your-bucket/
└── grid/
    └── {sandbox_id}/
        └── {session_id}/
            └── {namespace_id}/
                ├── scene.json
                └── animations/

Storage Scope Behavior:

  • SESSION scope (unauthenticated) → Local filesystem only, ephemeral
  • USER scope (authenticated) → Google Drive (if OAuth enabled) or S3, persistent

📦 Tool Surface

Scene Management

# Create a new scene
stage_create_scene(name, author, description)

# Add 3D objects
stage_add_object(
    scene_id,
    object_id,
    object_type,  # "box", "sphere", "cylinder", "plane"
    position_x, position_y, position_z,
    radius, size_x, size_y, size_z,
    material_preset,  # "metal-dark", "glass-blue", "plastic-white"
    color_r, color_g, color_b
)

# Set environment & lighting
stage_set_environment(
    scene_id,
    environment_type,  # "gradient", "solid", "hdri"
    lighting_preset    # "three-point", "studio", "noon"
)

Camera & Shots

# Add camera shot
stage_add_shot(
    scene_id,
    shot_id,
    camera_mode,  # "orbit", "static", "chase", "dolly"
    start_time,
    end_time,
    focus_object,      # Object to orbit/chase
    orbit_radius,
    orbit_elevation,
    orbit_speed,
    easing  # "ease-in-out-cubic", "spring", "linear"
)

# Get shot details
stage_get_shot(scene_id, shot_id)

Physics Integration

# Bind object to physics body
stage_bind_physics(
    scene_id,
    object_id,
    physics_body_id  # "rapier://sim-abc/body-ball"
)

# Bake simulation to keyframes
stage_bake_simulation(
    scene_id,
    simulation_id,
    fps=60,
    duration=10.0,
    physics_server_url=None  # Optional: defaults to https://rapier.chukai.io
)

Export

# Export to R3F/Remotion/glTF
stage_export_scene(
    scene_id,
    format,  # "r3f-component", "remotion-project", "gltf", "json"
    output_path
)

# Get complete scene data
stage_get_scene(scene_id)

🧩 Core Concepts

Stage Objects

A Stage Object is an entry in the scene graph that represents a 3D visual element. Every object has:

PropertyDescriptionExample
idUnique identifier"ball", "ground", "car-chassis"
typePrimitive shape"sphere", "box", "cylinder", "plane"
transformPosition, rotation, scale{position: [0, 5, 0], rotation: [0, 0, 0], scale: [1, 1, 1]}
materialVisual appearance"glass-blue", "metal-dark", custom PBR
physics_bindingOptional physics link"rapier://sim-abc/body-ball"

Example scene JSON:

{
  "id": "demo-scene",
  "name": "Falling Ball Demo",
  "objects": {
    "ground": {
      "id": "ground",
      "type": "plane",
      "transform": {
        "position": {"x": 0, "y": 0, "z": 0},
        "rotation": {"x": 0, "y": 0, "z": 0},
        "scale": {"x": 1, "y": 1, "z": 1}
      },
      "size": {"x": 20, "y": 20, "z": 1},
      "material": {
        "preset": "metal-dark"
      },
      "physics_binding": null
    },
    "ball": {
      "id": "ball",
      "type": "sphere",
      "transform": {
        "position": {"x": 0, "y": 5, "z": 0},
        "rotation": {"x": 0, "y": 0, "z": 0},
        "scale": {"x": 1, "y": 1, "z": 1}
      },
      "radius": 1.0,
      "material": {
        "preset": "glass-blue",
        "color": {"r": 0.3, "g": 0.6, "b": 1.0}
      },
      "physics_binding": "rapier://sim-falling/body-ball"
    }
  },
  "shots": {
    "main": {
      "id": "main",
      "camera_path": {
        "mode": "orbit",
        "focus": "ball",
        "radius": 8.0,
        "elevation": 30.0
      },
      "start_time": 0.0,
      "end_time": 10.0
    }
  }
}

Why this matters for LLMs:

When you create an object with stage_add_object, you're modifying this scene graph. Later operations like stage_bind_physics or stage_add_shot reference the same object ID you created. This makes it easy to reason about: "I want to modify the ball I just created" → just use object_id="ball".

Authoring vs Baking

chuk-mcp-stage has two distinct phases:

1️⃣ Authoring Phase (Define the World)

What you're doing: Planning and composing the scene

Operations:

  • Create scene structure
  • Place objects (primitives, positions, materials)
  • Define camera shots and movements
  • Bind object IDs to physics body IDs
  • Set environment and lighting

Output: Scene definition (metadata only, no animation yet)

Tools used:

  • stage_create_scene
  • stage_add_object
  • stage_add_shot
  • stage_bind_physics
  • stage_set_environment

2️⃣ Baking Phase (Generate Animation Data)

What you're doing: Converting physics simulation to renderable keyframes

Operations:

  • Connect to physics simulation (Rapier)
  • Sample physics state at desired FPS
  • Convert body positions/rotations → keyframes
  • Store animation data in scene VFS

Output: Timestamped keyframe arrays (position, rotation, velocity per frame)

Tools used:

  • stage_bake_simulation (connects to physics, generates keyframes)
  • stage_export_scene (exports scene + baked animations)

Typical Flow

┌──────────────────────────────────────────────────────────────┐
│ AUTHORING PHASE                                              │
├──────────────────────────────────────────────────────────────┤
│ 1. stage_create_scene(name="demo")                           │
│    → Creates empty scene graph                               │
│                                                               │
│ 2. stage_add_object(id="ground", type="plane", ...)          │
│    stage_add_object(id="ball", type="sphere", y=10, ...)     │
│    → Defines visual objects (no motion yet)                  │
│                                                               │
│ 3. stage_set_environment(lighting="three-point")             │
│    → Sets lights, background                                 │
│                                                               │
│ 4. Use physics MCP to create simulation                      │
│    create_simulation(gravity_y=-9.81)                        │
│    add_rigid_body(sim_id, body_id="ball", ...)               │
│    → Physics oracle creates simulation                       │
│                                                               │
│ 5. stage_bind_physics(object_id="ball",                      │
│                       body_id="rapier://sim-id/body-ball")   │
│    → Links visual object to physics body                     │
│                                                               │
│ 6. step_simulation(sim_id, steps=600)  # 10s @ 60 FPS        │
│    → Physics oracle runs simulation                          │
│                                                               │
│ 7. stage_add_shot(mode="orbit", focus="ball", ...)           │
│    → Defines camera cinematography                           │
├──────────────────────────────────────────────────────────────┤
│ BAKING PHASE                                                 │
├──────────────────────────────────────────────────────────────┤
│ 8. stage_bake_simulation(scene_id, sim_id, fps=60, dur=10)  │
│    → Fetches physics data from Rapier                        │
│    → Converts to keyframes                                   │
│    → Stores in /animations/ball.json                         │
│                                                               │
│ 9. stage_export_scene(format="remotion-project")            │
│    → Generates R3F/Remotion code                             │
│    → Includes baked animation data                           │
│    → Returns artifact URIs                                   │
└──────────────────────────────────────────────────────────────┘

   Authoring = "What should exist and where?"
   Baking    = "What motion actually happened?"

Key Insight: Authoring is declarative (you define intent), baking is computational (physics oracle generates the motion).


🎬 Example Workflow

1. Simple Falling Ball Demo

# 1. Create scene
scene = await stage_create_scene(
    name="falling-ball-demo",
    description="Ball falling under gravity"
)

# 2. Add ground plane
await stage_add_object(
    scene_id=scene.scene_id,
    object_id="ground",
    object_type="plane",
    size_x=20.0,
    size_y=20.0,
    material_preset="metal-dark"
)

# 3. Add falling ball
await stage_add_object(
    scene_id=scene.scene_id,
    object_id="ball",
    object_type="sphere",
    radius=1.0,
    position_y=5.0,
    material_preset="glass-blue",
    color_r=0.3,
    color_g=0.5,
    color_b=1.0
)

# 4. Add orbiting camera shot
await stage_add_shot(
    scene_id=scene.scene_id,
    shot_id="orbit-shot",
    camera_mode="orbit",
    focus_object="ball",
    orbit_radius=8.0,
    orbit_elevation=30.0,
    orbit_speed=0.1,
    start_time=0.0,
    end_time=10.0
)

# 5. Export to Remotion
result = await stage_export_scene(
    scene_id=scene.scene_id,
    format="remotion-project"
)

2. Physics-Driven Animation

Note: This example uses the public Rapier service (https://rapier.chukai.io) by default. No configuration needed!

# 1. Create physics simulation (chuk-mcp-physics)
sim = await create_simulation(gravity_y=-9.81)

await add_rigid_body(
    sim_id=sim.sim_id,
    body_id="ball",
    body_type="dynamic",
    shape="sphere",
    radius=1.0,
    position=[0, 5, 0]
)

# 2. Create scene
scene = await stage_create_scene(name="physics-demo")

await stage_add_object(
    scene_id=scene.scene_id,
    object_id="ball",
    object_type="sphere",
    radius=1.0,
    position_y=5.0
)

# 3. Bind physics to visual
await stage_bind_physics(
    scene_id=scene.scene_id,
    object_id="ball",
    physics_body_id=f"rapier://{sim.sim_id}/body-ball"
)

# 4. Run simulation (chuk-mcp-physics)
await step_simulation(sim_id=sim.sim_id, steps=600)

# 5. Bake physics → keyframes
await stage_bake_simulation(
    scene_id=scene.scene_id,
    simulation_id=sim.sim_id,
    fps=60,
    duration=10.0
)

# 6. Export with animation data
await stage_export_scene(
    scene_id=scene.scene_id,
    format="r3f-component"
)

📚 Examples

The examples/ directory contains ready-to-run demonstrations of all features.

🌟 Start Here: Golden Path

The canonical example showing the complete pipeline:

uv run examples/00_golden_path_ball_throw.py

This example demonstrates:

  • Authoring phase - Scene creation, object placement, camera shots
  • Baking phase - Physics simulation → keyframes (conceptual)
  • Export phase - Generate R3F/Remotion code
  • Artifact URIs - How chuk-mcp-stage integrates with chuk-artifacts
  • Two-phase model - Declarative → Computational
  • Complete pipeline - Physics → Stage → Motion → Video

This is the best example to understand the CHUK stack cohesion.

Getting Started

# Run any example
uv run examples/00_golden_path_ball_throw.py  # ⭐ Start here!
uv run examples/01_simple_scene.py
uv run examples/02_physics_integration_demo.py
uv run examples/03_camera_shots_demo.py
uv run examples/04_export_formats.py
uv run examples/05_full_physics_workflow.py

Example Guide

ExamplePurposeWhat You'll Learn
00_golden_path_ball_throw.pyComplete pipelineFull workflow, artifact URIs, two-phase model
01_simple_scene.pyBasic scene creationObjects, transforms, materials, simple camera
02_physics_integration_demo.pyPhysics binding conceptsBinding objects to physics bodies, metadata
03_camera_shots_demo.pyCamera cinematographyORBIT, STATIC, DOLLY, CHASE modes, easing functions
04_export_formats.pyExport capabilitiesJSON, R3F, Remotion, glTF formats and use cases
05_full_physics_workflow.pyComplete pipelineFull physics-to-video workflow with public Rapier

Example Outputs

00_golden_path_ball_throw.py ⭐ - Complete pipeline demonstration

📂 Artifact URIs (Not file contents!):
   Scene data:  artifact://stage/golden-path-ball-throw/exports/scene.json
   R3F:         artifact://stage/golden-path-ball-throw/exports/r3f/Scene.tsx
   Remotion:    artifact://stage/golden-path-ball-throw/exports/remotion/

🎬 Complete Pipeline:
   1. Authoring   - Define scene structure   ✓
   2. Physics     - Create simulation         (conceptual)
   3. Binding     - Link objects → bodies     ✓
   4. Baking      - Physics → keyframes       (conceptual)
   5. Export      - Scene → R3F/Remotion      ✓
   6. Render      - Remotion → MP4            (external)

01_simple_scene.py - Creates falling ball scene

✓ Created scene: falling-ball
✓ Added ground plane
✓ Added ball at (0, 5, 0)
✓ Added orbit camera shot (10s)

03_camera_shots_demo.py - 38-second multi-shot sequence

📹 Shot Sequence:
   •   0.0s -  10.0s  ORBIT   - Smooth orbit around center
   •  10.0s -  15.0s  STATIC  - Static wide angle
   •  15.0s -  22.0s  DOLLY   - Dolly tracking shot
   •  22.0s -  28.0s  CHASE   - Chase with spring easing
   •  28.0s -  33.0s  ORBIT   - Fast linear orbit
   •  33.0s -  38.0s  STATIC  - Low angle hero shot

04_export_formats.py - Exports to all formats

✓ JSON:     /exports/scene.json
✓ R3F:      /exports/r3f/Scene.tsx
✓ Remotion: /exports/remotion/Root.tsx
✓ glTF:     /exports/scene.gltf

Note: In production, these would be artifact URIs like:
  artifact://stage/{scene_id}/exports/scene.json

05_full_physics_workflow.py - Shows complete pipeline

🎬 Complete Pipeline:
   1. Physics Simulation (chuk-mcp-physics)
   2. Scene Composition (chuk-mcp-stage) ✓
   3. Bind Physics ✓
   4. Bake Simulation (Rapier service)
   5. Export (R3F/Remotion) ✓
   6. Render Video (Remotion)

Learning Path

Recommended order:

  1. Start with 00_golden_path_ball_throw.py ⭐ - See the complete pipeline first
  2. Understand basics with 01_simple_scene.py
  3. Explore camera control with 03_camera_shots_demo.py
  4. Learn export options with 04_export_formats.py
  5. See physics concepts with 02_physics_integration_demo.py
  6. Complete workflow with 05_full_physics_workflow.py

Why start with golden path? It shows you the destination (full pipeline) before diving into individual pieces. You'll understand how all the tools work together in the CHUK stack.


🏗️ Architecture

Scene Storage

  • Backend: chuk-artifacts (VFS-backed workspaces)
  • Format: JSON scene definitions with nested objects
  • Scope: SESSION (ephemeral), USER (persistent), SANDBOX (shared)

Each scene is a workspace containing:

/scene.json          # Scene definition
/animations/         # Baked keyframe data
  ball.json
  car.json
/export/             # Generated R3F/Remotion code
  r3f/
  remotion/

Camera Path Modes

ModeUse CaseParameters
orbitProduct shots, inspectionradius, elevation, speed, focus
staticFixed observationposition, look_at
chaseFollow moving objectstarget, offset, damping
dollyLinear revealsfrom_position, to_position, look_at
flythroughScene tourswaypoints[]
craneCinematic sweepspivot, arc, height_range

Material Presets

  • metal-dark, metal-light
  • glass-clear, glass-blue, glass-green
  • plastic-red, plastic-blue, plastic-white
  • rubber-black
  • wood-oak

Export Formats

  • R3F Component - React Three Fiber .tsx files
  • Remotion Project - Full project with package.json
  • glTF - Static 3D scene file
  • JSON - Raw scene data

VFS & Artifacts Integration

chuk-mcp-stage is tightly integrated with chuk-artifacts and chuk-virtual-fs for storage and asset management.

Why This Matters

Unlike typical MCP servers that return large JSON blobs inline, chuk-mcp-stage returns artifact URIs:

# ❌ Traditional approach (bloated)
{
  "scene_data": "...<10MB of JSON>...",
  "r3f_component": "...<5000 lines of TSX>...",
  "animations": "...<50MB of keyframes>..."
}

# ✅ CHUK approach (cohesive)
{
  "scene": "artifact://stage/demo-scene/scene.json",
  "component": "artifact://stage/demo-scene/export/r3f/Scene.tsx",
  "animations": "artifact://stage/demo-scene/animations/ball.json"
}

Benefits:

  1. No inline bloat - Tools return URIs, not massive data
  2. Persistent storage - Scenes survive across sessions (if using USER scope)
  3. VFS operations - Use vfs_ls, vfs_find, vfs_cp to manage scene files
  4. Cross-tool sharing - Other MCP servers can access same artifacts
  5. Checkpoint support - Version control for scene iterations

Storage Model

Each scene = one workspace in chuk-artifacts:

artifact://stage/{scene_id}/
├── scene.json              # Scene definition
├── animations/             # Baked physics keyframes
│   ├── ball.json          # Per-object animation data
│   ├── car.json
│   └── character.json
└── export/                 # Generated code
    ├── r3f/               # React Three Fiber
    │   ├── Scene.tsx
    │   ├── Camera.tsx
    │   └── animations.json
    ├── remotion/          # Remotion project
    │   ├── Composition.tsx
    │   ├── Root.tsx
    │   └── package.json
    └── gltf/              # 3D model exports
        └── scene.gltf

Example: Working with Artifacts

# 1. Create scene (returns artifact URI)
result = await stage_create_scene(name="demo")
# → {"scene_id": "demo-xyz", "workspace": "artifact://stage/demo-xyz"}

# 2. Add objects and bake simulation
# ... (authoring phase)

# 3. Export to Remotion (returns artifact URIs)
export_result = await stage_export_scene(
    scene_id="demo-xyz",
    format="remotion-project",
    output_path="/export/remotion"
)
# → {
#     "composition": "artifact://stage/demo-xyz/export/remotion/Composition.tsx",
#     "root": "artifact://stage/demo-xyz/export/remotion/Root.tsx",
#     "package": "artifact://stage/demo-xyz/export/remotion/package.json"
# }

# 4. Use VFS tools to explore (via chuk-virtual-fs MCP)
await vfs_ls("artifact://stage/demo-xyz/export/remotion")
# → ["Composition.tsx", "Root.tsx", "package.json"]

await vfs_read("artifact://stage/demo-xyz/export/remotion/package.json")
# → Returns package.json contents

# 5. Copy to another location
await vfs_cp(
    "artifact://stage/demo-xyz/export/remotion",
    "artifact://projects/my-video"
)

Integration with Other CHUK Tools

chuk-mcp-r3f-preview can directly preview scenes:

# Stage creates scene
scene_uri = "artifact://stage/demo-xyz/export/r3f/Scene.tsx"

# R3F preview server loads it
await r3f_preview_scene(scene_uri)
# → Opens interactive 3D preview in browser

chuk-motion can render baked animations:

# Stage bakes physics
animation_uri = "artifact://stage/demo-xyz/animations/ball.json"

# Motion applies spring physics to keyframes
await motion_apply_spring(animation_uri, stiffness=100)

This is where the CHUK stack cohesion shines: Every tool speaks the same artifact URI language.


🔗 Integration with CHUK Stack

┌─────────────────────────────────────────────────────────────┐
│                     chuk-mcp-stage                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐  │
│  │ Scene Graph  │  │   Camera     │  │  Physics Bridge  │  │
│  │              │  │   Paths      │  │                  │  │
│  └──────┬───────┘  └──────┬───────┘  └────────┬─────────┘  │
└─────────┼─────────────────┼───────────────────┼────────────┘
          │                 │                   │
          ▼                 ▼                   ▼
┌─────────────────┐  ┌─────────────┐  ┌─────────────────────┐
│ chuk-artifacts  │  │ chuk-motion │  │  chuk-mcp-physics   │
│                 │  │             │  │      (Rapier)       │
│ • scene.json    │  │ • easing    │  │                     │
│ • assets/       │  │ • springs   │  │ • rigid bodies      │
│ • animations/   │  │ • keyframes │  │ • constraints       │
└─────────────────┘  └──────┬──────┘  │ • sim state         │
                            │         └─────────────────────┘
                            ▼
                   ┌─────────────────┐
                   │ Remotion        │
                   │                 │
                   │ • R3F render    │
                   │ • video export  │
                   │ • MP4 output    │
                   └─────────────────┘

🎯 Use Cases

Immediate Wins

  1. Physics Explainer Videos - Auto-generate educational content
  2. Simulation-as-a-Service - LLMs can request visualizations
  3. Procedural B-Roll - Synthetic motion graphics

Vertical Plays

  1. Motorsport Visualization - Racing lines, braking zones, overtakes
  2. 3D Data Storytelling - Animated datasets with cinematography
  3. Science Journalism - Render model predictions visually

Weird & Powerful

  1. Explainable AI Animations - Show what models are thinking
  2. Virtual Physics Lab - Programmable experiments
  3. Agent Cinematography - AI chooses camera paths

📐 Data Models

All models are Pydantic-native with no dictionary goop:

from chuk_mcp_stage.models import (
    Scene,              # Complete scene definition
    SceneObject,        # 3D object (mesh, material, transform)
    Shot,               # Camera path + time range
    CameraPath,         # Camera movement definition
    Material,           # PBR material properties
    Environment,        # Lighting & background
    BakedAnimation,     # Physics → keyframes
)

Enums everywhere:

ObjectType.SPHERE
MaterialPreset.GLASS_BLUE
CameraPathMode.ORBIT
LightingPreset.THREE_POINT
ExportFormat.R3F_COMPONENT

🧪 Testing

# Run tests
pytest

# With coverage
pytest --cov=chuk_mcp_stage

🛠️ Development

# Install dev dependencies
pip install -e ".[dev]"

# Format
black src/ tests/

# Lint
ruff check src/

# Type check
mypy src/

📄 License

MIT License - see LICENSE for details


🌟 Why This Matters

Most people can: ✅ Run simulations ✅ Generate charts ✅ Animate text

Almost nobody can:

Simulate → Direct → Render → Explain → Export

chuk-mcp-stage gives you that pipeline.

You're not rendering things anymore. You're producing explainable simulations as media.


Built with ❤️ for the CHUK AI stack

Reviews

No reviews yet

Sign in to write a review