Skip to main content
Glama

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:

Provider

Persistence

Cloud Sync

OAuth Required

Setup

Best For

vfs-filesystem (default)

βœ… Local

❌

❌

Zero

Local dev

vfs-filesystem + OAuth

βœ… Persistent

βœ… Google Drive

βœ…

Medium

Production (small)

vfs-s3

βœ… Persistent

βœ… S3

❌

Medium

Production (large)

vfs-memory

❌ RAM only

❌

❌

Zero

Testing 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:

Property

Description

Example

id

Unique identifier

"ball", "ground", "car-chassis"

type

Primitive shape

"sphere", "box", "cylinder", "plane"

transform

Position, rotation, scale

{position: [0, 5, 0], rotation: [0, 0, 0], scale: [1, 1, 1]}

material

Visual appearance

"glass-blue", "metal-dark", custom PBR

physics_binding

Optional 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

Example

Purpose

What You'll Learn

00_golden_path_ball_throw.py ⭐

Complete pipeline

Full workflow, artifact URIs, two-phase model

01_simple_scene.py

Basic scene creation

Objects, transforms, materials, simple camera

02_physics_integration_demo.py

Physics binding concepts

Binding objects to physics bodies, metadata

03_camera_shots_demo.py

Camera cinematography

ORBIT, STATIC, DOLLY, CHASE modes, easing functions

04_export_formats.py

Export capabilities

JSON, R3F, Remotion, glTF formats and use cases

05_full_physics_workflow.py

Complete pipeline

Full 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

Mode

Use Case

Parameters

orbit

Product shots, inspection

radius, elevation, speed, focus

static

Fixed observation

position, look_at

chase

Follow moving objects

target, offset, damping

dolly

Linear reveals

from_position, to_position, look_at

flythrough

Scene tours

waypoints[]

crane

Cinematic sweeps

pivot, 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

Install Server
A
security – no known vulnerabilities
A
license - permissive license
A
quality - confirmed to work

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chrishayuk/chuk-mcp-stage'

If you have feedback or need assistance with the MCP directory API, please join our Discord server