GameContextProtocol / backend /mcp_server.py
ArturoNereu's picture
Added tools, and improved player movement
5b29015
"""
GCP - Game Context Protocol
MCP Server using the official Anthropic MCP SDK
This module defines all MCP tools for building 3D scenes with AI assistants.
"""
import os
from typing import Any
from mcp.server import Server
from mcp.types import Tool, TextContent
# Import tool implementations
from backend.tools.scene_tools import (
create_game_scene,
add_game_object,
remove_game_object,
set_scene_lighting,
get_scene_info,
add_brick,
BRICK_TYPES,
)
from backend.tools.player_tools import (
set_player_speed,
set_jump_force,
set_mouse_sensitivity,
set_gravity,
set_player_dimensions,
set_movement_acceleration,
set_air_control,
set_camera_fov,
set_vertical_look_limits,
get_player_config,
)
from backend.tools.rendering_tools import (
add_light,
remove_light,
update_light,
get_lights,
update_object_material,
set_background_color,
set_fog,
# Post-processing
set_bloom,
set_ssao,
set_color_grading,
set_vignette,
get_post_processing,
# Camera effects
set_depth_of_field,
set_motion_blur,
set_chromatic_aberration,
get_camera_effects,
# Toon shading
update_material_to_toon,
)
from backend.tools.environment_tools import (
add_skybox,
remove_skybox,
add_particles,
remove_particles,
)
from backend.tools.ui_tools import (
render_text_on_screen,
render_bar_on_screen,
remove_ui_element,
get_ui_elements,
)
from backend.game_models import create_vector3, create_material
# Base URL for viewer links
BASE_URL = os.getenv("SPACE_URL", "http://localhost:8000")
# Create MCP server instance
server = Server("gcp-server")
# =============================================================================
# Tool Definitions
# =============================================================================
SCENE_TOOLS = [
Tool(
name="create_scene",
description="""Create a new 3D scene/level.
Args:
name: Name of the scene (default: "New Scene")
description: Optional description
world_width: Width of the world in units (default: 100.0)
world_height: Height of the world in units (default: 100.0)
world_depth: Depth of the world in units (default: 100.0)
lighting_preset: "day", "night", "sunset", or "studio" (default: "day")
Returns: scene_id, viewer_url, and confirmation message""",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "default": "New Scene"},
"description": {"type": "string"},
"world_width": {"type": "number", "default": 100.0},
"world_height": {"type": "number", "default": 100.0},
"world_depth": {"type": "number", "default": 100.0},
"lighting_preset": {
"type": "string",
"enum": ["day", "night", "sunset", "studio"],
"default": "day"
},
},
},
),
Tool(
name="add_object",
description="""Add a 3D object to the scene.
Args:
scene_id: ID of the scene to add the object to (required)
object_type: "cube", "sphere", "cylinder", "plane", "cone", or "torus" (default: "cube")
name: Optional name for the object
x, y, z: Position coordinates (default: 0, 0, 0)
rotation_x, rotation_y, rotation_z: Rotation in degrees (default: 0, 0, 0)
scale_x, scale_y, scale_z: Scale factors (default: 1, 1, 1)
color: Hex color code like "#ff0000" for red (default: "#ffffff")
Returns: object_id, scene_id, viewer_url, and confirmation message""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"object_type": {
"type": "string",
"enum": ["cube", "sphere", "cylinder", "plane", "cone", "torus"],
"default": "cube"
},
"name": {"type": "string"},
"x": {"type": "number", "default": 0.0},
"y": {"type": "number", "default": 0.0},
"z": {"type": "number", "default": 0.0},
"rotation_x": {"type": "number", "default": 0.0},
"rotation_y": {"type": "number", "default": 0.0},
"rotation_z": {"type": "number", "default": 0.0},
"scale_x": {"type": "number", "default": 1.0},
"scale_y": {"type": "number", "default": 1.0},
"scale_z": {"type": "number", "default": 1.0},
"color": {"type": "string", "default": "#ffffff"},
},
"required": ["scene_id"],
},
),
Tool(
name="remove_object",
description="""Remove an object from the scene.
Args:
scene_id: ID of the scene (required)
object_id: ID of the object to remove (required)
Returns: scene_id, viewer_url, and confirmation message""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"object_id": {"type": "string"},
},
"required": ["scene_id", "object_id"],
},
),
Tool(
name="set_lighting",
description="""Set the lighting preset for the scene.
Args:
scene_id: ID of the scene (required)
preset: "day", "night", "sunset", or "studio" (default: "day")
Returns: scene_id, viewer_url, and confirmation message""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"preset": {
"type": "string",
"enum": ["day", "night", "sunset", "studio"],
"default": "day"
},
},
"required": ["scene_id"],
},
),
Tool(
name="get_scene_info",
description="""Get detailed information about a scene.
Args:
scene_id: ID of the scene to retrieve (required)
Returns: scene details including name, objects, lights, and viewer_url""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
Tool(
name="add_brick",
description="""Add a LEGO-style brick from the Kenney brick kit.
Args:
scene_id: ID of the scene (required)
brick_type: Type of brick (required) - brick_1x1, brick_1x2, brick_1x4, brick_2x2, brick_2x4,
plate_1x2, plate_2x2, plate_2x4, plate_4x4, slope_2x2
position: {x, y, z} position
rotation: {x, y, z} rotation in degrees
color: Hex color code (default: #ff0000 red)
name: Optional name for the brick
Examples:
add_brick(scene_id, "brick_2x4", position={x:0, y:0, z:0}, color="#ff0000")
add_brick(scene_id, "slope_2x2", position={x:1, y:0.5, z:0}, color="#0000ff")""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"brick_type": {
"type": "string",
"enum": ["brick_1x1", "brick_1x2", "brick_1x4", "brick_2x2", "brick_2x4",
"plate_1x2", "plate_2x2", "plate_2x4", "plate_4x4", "slope_2x2"]
},
"position": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"rotation": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"color": {"type": "string", "default": "#ff0000"},
"name": {"type": "string"},
},
"required": ["scene_id", "brick_type"],
},
),
]
PLAYER_TOOLS = [
Tool(
name="set_player_speed",
description="""Set the player's movement speed.
Args:
scene_id: ID of the scene (required)
walk_speed: Movement speed in units/second (default: 5.0)
Example: set_player_speed(scene_id, walk_speed=8.0) for faster movement""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"walk_speed": {"type": "number", "default": 5.0},
},
"required": ["scene_id"],
},
),
Tool(
name="set_jump_force",
description="""Configure jump height by setting initial upward velocity.
Args:
scene_id: ID of the scene (required)
jump_force: Initial jump velocity in m/s (default: 5.0, higher = higher jumps)
Example: set_jump_force(scene_id, jump_force=7.0) for higher jumps""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"jump_force": {"type": "number", "default": 5.0},
},
"required": ["scene_id"],
},
),
Tool(
name="set_mouse_sensitivity",
description="""Configure mouse look sensitivity and Y-axis inversion.
Args:
scene_id: ID of the scene (required)
sensitivity: Mouse sensitivity multiplier (default: 0.002, lower = more precise)
invert_y: Invert vertical look, flight-sim style (default: false)
Example: set_mouse_sensitivity(scene_id, sensitivity=0.001) for precise aiming""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"sensitivity": {"type": "number", "default": 0.002},
"invert_y": {"type": "boolean", "default": False},
},
"required": ["scene_id"],
},
),
Tool(
name="set_gravity",
description="""Set the world's gravity strength.
Args:
scene_id: ID of the scene (required)
gravity: Gravity in m/s² (default: -9.82 = Earth, negative = downward)
Examples:
-9.82 = Earth gravity (default)
-1.62 = Moon gravity (floaty)
-3.7 = Mars gravity
-20.0 = Heavy gravity""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"gravity": {"type": "number", "default": -9.82},
},
"required": ["scene_id"],
},
),
Tool(
name="set_player_dimensions",
description="""Configure player collision capsule dimensions.
Args:
scene_id: ID of the scene (required)
height: Player height in meters (default: 1.7)
radius: Player radius in meters (default: 0.3)
eye_height: Camera height from feet (default: height - 0.1)
Example: set_player_dimensions(scene_id, height=1.2, radius=0.25) for child-sized""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"height": {"type": "number", "default": 1.7},
"radius": {"type": "number", "default": 0.3},
"eye_height": {"type": "number"},
},
"required": ["scene_id"],
},
),
Tool(
name="set_movement_acceleration",
description="""Configure how quickly player reaches max speed and movement friction.
Args:
scene_id: ID of the scene (required)
acceleration: Time to reach max speed (0.0=instant, 0.5=snappy, 1.0=sliding)
damping: Linear damping/friction (0.0-1.0, higher=more friction, default: 0.9)
Example: set_movement_acceleration(scene_id, acceleration=0.3, damping=0.5) for sliding feel""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"acceleration": {"type": "number", "default": 0.0},
"damping": {"type": "number", "default": 0.9},
},
"required": ["scene_id"],
},
),
Tool(
name="set_air_control",
description="""Configure movement control while airborne (jumping/falling).
Args:
scene_id: ID of the scene (required)
air_control_factor: Control while airborne 0.0-1.0 (default: 1.0)
1.0 = full control (typical FPS)
0.0 = no air steering (realistic)
Example: set_air_control(scene_id, air_control_factor=0.3) for limited air control""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"air_control_factor": {"type": "number", "default": 1.0},
},
"required": ["scene_id"],
},
),
Tool(
name="set_camera_fov",
description="""Set the camera field of view.
Args:
scene_id: ID of the scene (required)
fov: Field of view in degrees (default: 75)
60-70 = narrow/zoomed (competitive shooters)
75-85 = normal (most games)
90-120 = wide/"quake pro" style
Example: set_camera_fov(scene_id, fov=90.0) for wide angle""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"fov": {"type": "number", "default": 75.0},
},
"required": ["scene_id"],
},
),
Tool(
name="set_vertical_look_limits",
description="""Configure how far up and down the player can look.
Args:
scene_id: ID of the scene (required)
min_pitch: Min angle in degrees, looking down (default: -89)
max_pitch: Max angle in degrees, looking up (default: 89)
Example: set_vertical_look_limits(scene_id, min_pitch=-45, max_pitch=45) for restricted""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"min_pitch": {"type": "number", "default": -89.0},
"max_pitch": {"type": "number", "default": 89.0},
},
"required": ["scene_id"],
},
),
Tool(
name="get_player_config",
description="""Get the current player controller configuration.
Args:
scene_id: ID of the scene (required)
Returns: All player settings (speed, jump, gravity, dimensions, etc.)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
]
RENDERING_TOOLS = [
Tool(
name="add_light",
description="""Add a new light source to the scene.
Args:
scene_id: Scene to modify (required)
light_type: "ambient", "directional", "point", or "spot" (required)
name: Unique identifier like "Torch1", "MainLight" (required)
color: Hex color code (default: "#ffffff")
intensity: Brightness 0.0-2.0 (default: 1.0)
position: {x, y, z} for directional/point/spot lights
target: {x, y, z} where directional/spot lights point
cast_shadow: Enable shadows (default: false)
spot_angle: Cone angle in degrees for spot lights (default: 45)
Examples:
add_light(scene_id, "point", "Torch", "#ff6600", 1.5, {x:2, y:3, z:0})
add_light(scene_id, "ambient", "Fill", "#aaaaaa", 0.3)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"light_type": {
"type": "string",
"enum": ["ambient", "directional", "point", "spot"]
},
"name": {"type": "string"},
"color": {"type": "string", "default": "#ffffff"},
"intensity": {"type": "number", "default": 1.0},
"position": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"target": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"cast_shadow": {"type": "boolean", "default": False},
"spot_angle": {"type": "number", "default": 45.0},
},
"required": ["scene_id", "light_type", "name"],
},
),
Tool(
name="remove_light",
description="""Remove a light from the scene.
Args:
scene_id: Scene to modify (required)
light_name: Name of the light to remove (required)
Example: remove_light(scene_id, "Torch1")""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"light_name": {"type": "string"},
},
"required": ["scene_id", "light_name"],
},
),
Tool(
name="update_light",
description="""Update existing light properties.
Args:
scene_id: Scene to modify (required)
light_name: Name of light to update (required)
color: New hex color (optional)
intensity: New brightness 0.0-2.0 (optional)
position: New {x, y, z} position (optional)
cast_shadow: Enable/disable shadows (optional)
Example: update_light(scene_id, "Sun", color="#ffaa00", intensity=0.8)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"light_name": {"type": "string"},
"color": {"type": "string"},
"intensity": {"type": "number"},
"position": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"cast_shadow": {"type": "boolean"},
},
"required": ["scene_id", "light_name"],
},
),
Tool(
name="get_lights",
description="""Get all lights in the scene.
Args:
scene_id: Scene to query (required)
Returns: List of all lights with their properties""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
Tool(
name="update_object_material",
description="""Update an object's material properties.
Args:
scene_id: Scene to modify (required)
object_id: ID of object to update (required)
color: Hex color code (optional)
metalness: 0.0 (matte) to 1.0 (metal) (optional)
roughness: 0.0 (shiny) to 1.0 (rough) (optional)
opacity: 0.0 (invisible) to 1.0 (solid) (optional)
emissive: Hex color for self-glow (optional)
emissive_intensity: Glow brightness 0.0-1.0 (optional)
Examples:
update_object_material(scene_id, object_id, color="#ff0000")
update_object_material(scene_id, object_id, metalness=0.9, roughness=0.1)
update_object_material(scene_id, object_id, emissive="#00ffff", emissive_intensity=0.8)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"object_id": {"type": "string"},
"color": {"type": "string"},
"metalness": {"type": "number"},
"roughness": {"type": "number"},
"opacity": {"type": "number"},
"emissive": {"type": "string"},
"emissive_intensity": {"type": "number"},
},
"required": ["scene_id", "object_id"],
},
),
Tool(
name="set_background_color",
description="""Set scene background color or gradient.
Args:
scene_id: Scene to modify (required)
color: Hex color for solid background
bg_type: "solid" or "gradient" (default: "solid")
gradient_top: Top hex color for gradient
gradient_bottom: Bottom hex color for gradient
Examples:
set_background_color(scene_id, color="#000000") # Black
set_background_color(scene_id, bg_type="gradient", gradient_top="#87CEEB", gradient_bottom="#FFE4B5")""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"color": {"type": "string"},
"bg_type": {
"type": "string",
"enum": ["solid", "gradient"],
"default": "solid"
},
"gradient_top": {"type": "string"},
"gradient_bottom": {"type": "string"},
},
"required": ["scene_id"],
},
),
Tool(
name="set_fog",
description="""Add atmospheric fog to the scene.
Args:
scene_id: Scene to modify (required)
enabled: Enable or disable fog (required)
color: Hex color of fog (default: "#aaaaaa")
near: Start distance for linear fog
far: End distance for linear fog
density: Density for exponential fog (overrides near/far)
Examples:
set_fog(scene_id, enabled=True, color="#aaaaaa", near=10, far=50)
set_fog(scene_id, enabled=True, density=0.05) # Exponential
set_fog(scene_id, enabled=False) # Disable""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"color": {"type": "string", "default": "#aaaaaa"},
"near": {"type": "number"},
"far": {"type": "number"},
"density": {"type": "number"},
},
"required": ["scene_id", "enabled"],
},
),
]
POST_PROCESSING_TOOLS = [
Tool(
name="set_bloom",
description="""Configure bloom (glow) post-processing effect.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable bloom (required)
strength: Bloom intensity 0.0-3.0 (default: 1.0)
radius: Bloom spread/blur radius 0.0-1.0 (default: 0.4)
threshold: Brightness threshold to trigger bloom 0.0-1.0 (default: 0.8)
Example: set_bloom(scene_id, enabled=True, strength=1.5, threshold=0.6)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"strength": {"type": "number", "default": 1.0},
"radius": {"type": "number", "default": 0.4},
"threshold": {"type": "number", "default": 0.8},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="set_ssao",
description="""Configure Screen Space Ambient Occlusion (SSAO).
Adds soft shadows in corners and crevices for depth and realism.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable SSAO (required)
radius: Sample radius in world units 0.1-2.0 (default: 0.5)
intensity: Shadow intensity 0.0-2.0 (default: 1.0)
bias: Depth bias to prevent self-occlusion 0.001-0.1 (default: 0.025)
Example: set_ssao(scene_id, enabled=True, intensity=1.5)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"radius": {"type": "number", "default": 0.5},
"intensity": {"type": "number", "default": 1.0},
"bias": {"type": "number", "default": 0.025},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="set_color_grading",
description="""Configure color grading post-processing.
Adjust overall image colors for cinematic looks or stylized effects.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable color grading (required)
brightness: Brightness adjustment -1.0 to 1.0 (default: 0.0)
contrast: Contrast multiplier 0.0-2.0 (default: 1.0)
saturation: Color saturation 0.0-2.0 (default: 1.0)
hue: Hue shift in degrees -180 to 180 (default: 0)
exposure: Exposure adjustment 0.0-3.0 (default: 1.0)
gamma: Gamma correction 0.5-2.5 (default: 1.0)
Example: set_color_grading(scene_id, enabled=True, saturation=0.5) for desaturated look""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"brightness": {"type": "number", "default": 0.0},
"contrast": {"type": "number", "default": 1.0},
"saturation": {"type": "number", "default": 1.0},
"hue": {"type": "number", "default": 0.0},
"exposure": {"type": "number", "default": 1.0},
"gamma": {"type": "number", "default": 1.0},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="set_vignette",
description="""Configure vignette effect (darkened edges).
Darkens corners and edges of the screen, drawing focus to the center.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable vignette (required)
intensity: Darkness of the vignette 0.0-1.0 (default: 0.5)
smoothness: Softness of the vignette edge 0.0-1.0 (default: 0.5)
Example: set_vignette(scene_id, enabled=True, intensity=0.7)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"intensity": {"type": "number", "default": 0.5},
"smoothness": {"type": "number", "default": 0.5},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="get_post_processing",
description="""Get all post-processing settings for the scene.
Args:
scene_id: Scene to query (required)
Returns: All post-processing settings (bloom, SSAO, color grading, vignette)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
]
CAMERA_EFFECTS_TOOLS = [
Tool(
name="set_depth_of_field",
description="""Configure depth of field (DoF) camera effect.
Blurs objects that are not at the focus distance, simulating real camera lenses.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable depth of field (required)
focus_distance: Distance to the focal plane in units (default: 10.0)
aperture: Aperture size, affects blur amount 0.001-0.1 (default: 0.025)
max_blur: Maximum blur strength 0.0-0.05 (default: 0.01)
Example: set_depth_of_field(scene_id, enabled=True, focus_distance=5.0)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"focus_distance": {"type": "number", "default": 10.0},
"aperture": {"type": "number", "default": 0.025},
"max_blur": {"type": "number", "default": 0.01},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="set_motion_blur",
description="""Configure motion blur camera effect.
Adds blur in the direction of camera or object movement.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable motion blur (required)
intensity: Blur intensity 0.0-2.0 (default: 0.5)
samples: Quality samples for blur 4-32 (default: 8)
Example: set_motion_blur(scene_id, enabled=True, intensity=0.8)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"intensity": {"type": "number", "default": 0.5},
"samples": {"type": "integer", "default": 8},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="set_chromatic_aberration",
description="""Configure chromatic aberration effect.
Simulates lens imperfection by separating color channels at the edges.
Args:
scene_id: Scene to modify (required)
enabled: Enable/disable chromatic aberration (required)
intensity: Effect strength 0.0-0.05 (default: 0.005)
Example: set_chromatic_aberration(scene_id, enabled=True, intensity=0.01)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"enabled": {"type": "boolean"},
"intensity": {"type": "number", "default": 0.005},
},
"required": ["scene_id", "enabled"],
},
),
Tool(
name="get_camera_effects",
description="""Get all camera effects settings for the scene.
Args:
scene_id: Scene to query (required)
Returns: All camera effects settings (depth of field, motion blur, chromatic aberration)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
]
ENVIRONMENT_TOOLS = [
Tool(
name="add_skybox",
description="""Add a procedural sky to the scene.
Creates realistic outdoor environments with atmospheric scattering.
Args:
scene_id: Scene to modify (required)
preset: Quick preset - "day", "sunset", "noon", "dawn", "night" (default: "day")
turbidity: Haziness 2.0=clear, 10.0=hazy, 20.0=foggy (default: 10.0)
rayleigh: Blue sky intensity 0.0-4.0 (default: 2.0)
sun_elevation: Sun angle from horizon -90 to 90 degrees (default: 45)
sun_azimuth: Sun compass direction 0-360 degrees (default: 180)
Examples:
add_skybox(scene_id, preset="sunset")
add_skybox(scene_id, sun_elevation=5, turbidity=4)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"preset": {
"type": "string",
"enum": ["day", "sunset", "noon", "dawn", "night"],
"default": "day"
},
"turbidity": {"type": "number", "default": 10.0},
"rayleigh": {"type": "number", "default": 2.0},
"sun_elevation": {"type": "number", "default": 45.0},
"sun_azimuth": {"type": "number", "default": 180.0},
},
"required": ["scene_id"],
},
),
Tool(
name="remove_skybox",
description="""Remove the skybox from the scene.
Reverts to solid background color.
Args:
scene_id: Scene to modify (required)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
},
"required": ["scene_id"],
},
),
Tool(
name="add_particles",
description="""Add a particle effect to the scene.
Use presets for quick setup of common effects.
Args:
scene_id: Scene to modify (required)
preset: Effect type - "fire", "smoke", "sparkle", "rain", "snow" (required)
position: {x, y, z} for localized effects (fire, smoke, sparkle)
particle_id: Optional unique identifier
Examples:
add_particles(scene_id, "fire", position={x:0, y:1, z:0})
add_particles(scene_id, "rain") # Weather covers entire world""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"preset": {
"type": "string",
"enum": ["fire", "smoke", "sparkle", "rain", "snow"]
},
"position": {
"type": "object",
"properties": {
"x": {"type": "number"},
"y": {"type": "number"},
"z": {"type": "number"},
}
},
"particle_id": {"type": "string"},
},
"required": ["scene_id", "preset"],
},
),
Tool(
name="remove_particles",
description="""Remove a particle system from the scene.
Args:
scene_id: Scene to modify (required)
particle_id: ID of the particle system to remove (required)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"particle_id": {"type": "string"},
},
"required": ["scene_id", "particle_id"],
},
),
]
UI_TOOLS = [
Tool(
name="render_text_on_screen",
description="""Render text on the screen as a 2D overlay.
Args:
scene_id: Scene to modify (required)
text: The text to display (required)
x: Horizontal position in % (0=left, 50=center, 100=right, default: 50)
y: Vertical position in % (0=top, 50=center, 100=bottom, default: 10)
font_size: Font size in pixels (default: 24)
color: Text color hex (default: "#ffffff")
text_id: Optional unique ID for updates/removal
background_color: Optional background color for text box
Examples:
render_text_on_screen(scene_id, "Score: 100", x=10, y=5)
render_text_on_screen(scene_id, "Game Over", x=50, y=50, font_size=48)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"text": {"type": "string"},
"x": {"type": "number", "default": 50.0},
"y": {"type": "number", "default": 10.0},
"font_size": {"type": "integer", "default": 24},
"color": {"type": "string", "default": "#ffffff"},
"text_id": {"type": "string"},
"font_family": {"type": "string", "default": "Arial"},
"text_align": {
"type": "string",
"enum": ["left", "center", "right"],
"default": "center"
},
"background_color": {"type": "string"},
"padding": {"type": "integer", "default": 8},
},
"required": ["scene_id", "text"],
},
),
Tool(
name="render_bar_on_screen",
description="""Render a progress/health bar on the screen.
Args:
scene_id: Scene to modify (required)
x: Horizontal position in % (default: 10)
y: Vertical position in % (default: 10)
width: Bar width in pixels (default: 200)
height: Bar height in pixels (default: 20)
value: Current value (default: 100)
max_value: Maximum value (default: 100)
bar_color: Fill color (default: "#00ff00" green)
background_color: Background color (default: "#333333")
bar_id: Optional unique ID for updates/removal
label: Optional label above the bar
show_value: Show numeric value on bar (default: false)
Examples:
render_bar_on_screen(scene_id, value=75, bar_color="#ff0000", label="Health")
render_bar_on_screen(scene_id, x=10, y=90, value=50, bar_color="#0088ff", label="Mana")""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"x": {"type": "number", "default": 10.0},
"y": {"type": "number", "default": 10.0},
"width": {"type": "number", "default": 200.0},
"height": {"type": "number", "default": 20.0},
"value": {"type": "number", "default": 100.0},
"max_value": {"type": "number", "default": 100.0},
"bar_color": {"type": "string", "default": "#00ff00"},
"background_color": {"type": "string", "default": "#333333"},
"border_color": {"type": "string", "default": "#ffffff"},
"bar_id": {"type": "string"},
"label": {"type": "string"},
"show_value": {"type": "boolean", "default": False},
},
"required": ["scene_id"],
},
),
Tool(
name="remove_ui_element",
description="""Remove a UI element from the screen.
Args:
scene_id: Scene to modify (required)
element_id: ID of the text or bar to remove (required)""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"element_id": {"type": "string"},
},
"required": ["scene_id", "element_id"],
},
),
]
TOON_TOOLS = [
Tool(
name="update_material_to_toon",
description="""Apply toon/cel-shading to an object for cartoon-like appearance.
Creates discrete shading bands instead of smooth gradients, common in anime styles.
Args:
scene_id: Scene to modify (required)
object_id: Object to update (required)
enabled: Enable/disable toon shading (default: true)
color: Base color (optional, keeps existing)
gradient_steps: Shading steps 2=hard, 3=medium, 5=soft (default: 3)
outline: Add black outline effect (default: true)
outline_color: Outline color (default: "#000000")
outline_thickness: Outline thickness 0.01-0.1 (default: 0.03)
Examples:
update_material_to_toon(scene_id, object_id, gradient_steps=2)
update_material_to_toon(scene_id, object_id, enabled=False) # Revert""",
inputSchema={
"type": "object",
"properties": {
"scene_id": {"type": "string"},
"object_id": {"type": "string"},
"enabled": {"type": "boolean", "default": True},
"color": {"type": "string"},
"gradient_steps": {"type": "integer", "default": 3},
"outline": {"type": "boolean", "default": True},
"outline_color": {"type": "string", "default": "#000000"},
"outline_thickness": {"type": "number", "default": 0.03},
},
"required": ["scene_id", "object_id"],
},
),
]
# Combine all tools
ALL_TOOLS = SCENE_TOOLS + PLAYER_TOOLS + RENDERING_TOOLS + POST_PROCESSING_TOOLS + CAMERA_EFFECTS_TOOLS + ENVIRONMENT_TOOLS + UI_TOOLS + TOON_TOOLS
# =============================================================================
# MCP Handlers
# =============================================================================
@server.list_tools()
async def list_tools() -> list[Tool]:
"""Return all available GCP tools."""
return ALL_TOOLS
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""Handle tool calls from MCP clients."""
try:
result = await _execute_tool(name, arguments)
return [TextContent(type="text", text=str(result))]
except Exception as e:
return [TextContent(type="text", text=f"Error: {str(e)}")]
async def _execute_tool(name: str, args: dict) -> Any:
"""Route tool calls to their implementations."""
# Scene tools
if name == "create_scene":
return create_game_scene(
name=args.get("name", "New Scene"),
description=args.get("description"),
world_width=args.get("world_width", 100.0),
world_height=args.get("world_height", 100.0),
world_depth=args.get("world_depth", 100.0),
lighting_preset=args.get("lighting_preset", "day"),
base_url=BASE_URL,
)
elif name == "add_object":
return add_game_object(
scene_id=args["scene_id"],
object_type=args.get("object_type", "cube"),
name=args.get("name"),
position=create_vector3(
args.get("x", 0.0),
args.get("y", 0.0),
args.get("z", 0.0)
),
rotation=create_vector3(
args.get("rotation_x", 0.0),
args.get("rotation_y", 0.0),
args.get("rotation_z", 0.0)
),
scale=create_vector3(
args.get("scale_x", 1.0),
args.get("scale_y", 1.0),
args.get("scale_z", 1.0)
),
material=create_material(color=args.get("color", "#ffffff")),
base_url=BASE_URL,
)
elif name == "remove_object":
return remove_game_object(
scene_id=args["scene_id"],
object_id=args["object_id"],
base_url=BASE_URL,
)
elif name == "set_lighting":
return set_scene_lighting(
scene_id=args["scene_id"],
preset=args.get("preset", "day"),
base_url=BASE_URL,
)
elif name == "get_scene_info":
return get_scene_info(args["scene_id"], BASE_URL)
elif name == "add_brick":
return add_brick(
args["scene_id"],
args["brick_type"],
args.get("position"),
args.get("rotation"),
args.get("color", "#ff0000"),
args.get("name"),
BASE_URL
)
# Player tools
elif name == "set_player_speed":
return set_player_speed(
args["scene_id"],
args.get("walk_speed", 5.0)
)
elif name == "set_jump_force":
return set_jump_force(
args["scene_id"],
args.get("jump_force", 5.0)
)
elif name == "set_mouse_sensitivity":
return set_mouse_sensitivity(
args["scene_id"],
args.get("sensitivity", 0.002),
args.get("invert_y", False)
)
elif name == "set_gravity":
return set_gravity(
args["scene_id"],
args.get("gravity", -9.82)
)
elif name == "set_player_dimensions":
return set_player_dimensions(
args["scene_id"],
args.get("height", 1.7),
args.get("radius", 0.3),
args.get("eye_height")
)
elif name == "set_movement_acceleration":
return set_movement_acceleration(
args["scene_id"],
args.get("acceleration", 0.0),
args.get("damping", 0.9)
)
elif name == "set_air_control":
return set_air_control(
args["scene_id"],
args.get("air_control_factor", 1.0)
)
elif name == "set_camera_fov":
return set_camera_fov(
args["scene_id"],
args.get("fov", 75.0)
)
elif name == "set_vertical_look_limits":
return set_vertical_look_limits(
args["scene_id"],
args.get("min_pitch", -89.0),
args.get("max_pitch", 89.0)
)
elif name == "get_player_config":
return get_player_config(args["scene_id"])
# Rendering tools
elif name == "add_light":
return add_light(
args["scene_id"],
args["light_type"],
args["name"],
args.get("color", "#ffffff"),
args.get("intensity", 1.0),
args.get("position"),
args.get("target"),
args.get("cast_shadow", False),
args.get("spot_angle")
)
elif name == "remove_light":
return remove_light(
args["scene_id"],
args["light_name"]
)
elif name == "update_light":
return update_light(
args["scene_id"],
args["light_name"],
args.get("color"),
args.get("intensity"),
args.get("position"),
args.get("cast_shadow")
)
elif name == "get_lights":
return get_lights(args["scene_id"])
elif name == "update_object_material":
return update_object_material(
args["scene_id"],
args["object_id"],
args.get("color"),
args.get("metalness"),
args.get("roughness"),
args.get("opacity"),
args.get("emissive"),
args.get("emissive_intensity")
)
elif name == "set_background_color":
return set_background_color(
args["scene_id"],
args.get("color"),
args.get("bg_type", "solid"),
args.get("gradient_top"),
args.get("gradient_bottom")
)
elif name == "set_fog":
return set_fog(
args["scene_id"],
args["enabled"],
args.get("color"),
args.get("near"),
args.get("far"),
args.get("density")
)
# Post-processing tools
elif name == "set_bloom":
return set_bloom(
args["scene_id"],
args["enabled"],
args.get("strength", 1.0),
args.get("radius", 0.4),
args.get("threshold", 0.8)
)
elif name == "set_ssao":
return set_ssao(
args["scene_id"],
args["enabled"],
args.get("radius", 0.5),
args.get("intensity", 1.0),
args.get("bias", 0.025)
)
elif name == "set_color_grading":
return set_color_grading(
args["scene_id"],
args["enabled"],
args.get("brightness", 0.0),
args.get("contrast", 1.0),
args.get("saturation", 1.0),
args.get("hue", 0.0),
args.get("exposure", 1.0),
args.get("gamma", 1.0)
)
elif name == "set_vignette":
return set_vignette(
args["scene_id"],
args["enabled"],
args.get("intensity", 0.5),
args.get("smoothness", 0.5)
)
elif name == "get_post_processing":
return get_post_processing(args["scene_id"])
# Camera effects tools
elif name == "set_depth_of_field":
return set_depth_of_field(
args["scene_id"],
args["enabled"],
args.get("focus_distance", 10.0),
args.get("aperture", 0.025),
args.get("max_blur", 0.01)
)
elif name == "set_motion_blur":
return set_motion_blur(
args["scene_id"],
args["enabled"],
args.get("intensity", 0.5),
args.get("samples", 8)
)
elif name == "set_chromatic_aberration":
return set_chromatic_aberration(
args["scene_id"],
args["enabled"],
args.get("intensity", 0.005)
)
elif name == "get_camera_effects":
return get_camera_effects(args["scene_id"])
# Environment tools (skybox, particles)
elif name == "add_skybox":
return add_skybox(
args["scene_id"],
args.get("preset", "day"),
args.get("turbidity", 10.0),
args.get("rayleigh", 2.0),
args.get("sun_elevation", 45.0),
args.get("sun_azimuth", 180.0)
)
elif name == "remove_skybox":
return remove_skybox(args["scene_id"])
elif name == "add_particles":
return add_particles(
args["scene_id"],
args["preset"],
args.get("position"),
args.get("particle_id")
)
elif name == "remove_particles":
return remove_particles(
args["scene_id"],
args["particle_id"]
)
# UI tools
elif name == "render_text_on_screen":
return render_text_on_screen(
args["scene_id"],
args["text"],
args.get("x", 50.0),
args.get("y", 10.0),
args.get("font_size", 24),
args.get("color", "#ffffff"),
args.get("text_id"),
args.get("font_family", "Arial"),
args.get("text_align", "center"),
args.get("background_color"),
args.get("padding", 8)
)
elif name == "render_bar_on_screen":
return render_bar_on_screen(
args["scene_id"],
args.get("x", 10.0),
args.get("y", 10.0),
args.get("width", 200.0),
args.get("height", 20.0),
args.get("value", 100.0),
args.get("max_value", 100.0),
args.get("bar_color", "#00ff00"),
args.get("background_color", "#333333"),
args.get("border_color", "#ffffff"),
args.get("bar_id"),
args.get("label"),
args.get("show_value", False)
)
elif name == "remove_ui_element":
return remove_ui_element(
args["scene_id"],
args["element_id"]
)
# Toon shading tools
elif name == "update_material_to_toon":
return update_material_to_toon(
args["scene_id"],
args["object_id"],
args.get("enabled", True),
args.get("color"),
args.get("gradient_steps", 3),
args.get("outline", True),
args.get("outline_color", "#000000"),
args.get("outline_thickness", 0.03)
)
else:
raise ValueError(f"Unknown tool: {name}")
# =============================================================================
# Server runner (for standalone MCP mode)
# =============================================================================
async def run_stdio():
"""Run the MCP server using stdio transport."""
from mcp.server.stdio import stdio_server
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
import asyncio
asyncio.run(run_stdio())