robot_virtual
Manage virtual robots in Unity or VRChat by creating, updating, deleting, and operating them. Perform tasks like loading environments, testing navigation, and syncing with physical robots.
Instructions
Virtual robot lifecycle and operations portmanteau.
PORTMANTEAU PATTERN: Consolidates virtual robot CRUD operations and virtual robotics operations into a single unified tool. This reduces tool explosion while maintaining full functionality for virtual robot management.
CRUD OPERATIONS:
create: Create/spawn and register a new virtual robot
read: Get details of an existing virtual robot
update: Modify virtual robot properties (scale, position, metadata, etc.)
delete: Remove and unregister a virtual robot
list: List all virtual robots with optional filtering
VIRTUAL ROBOT OPERATIONS:
spawn: Spawn robot in Unity/VRChat scene (alias for create)
load_environment: Load Marble/Chisel environment into scene
get_status: Get virtual robot status
get_lidar: Get virtual LiDAR scan (Unity physics raycast)
set_scale: Scale robot size (for size testing)
test_navigation: Test pathfinding in environment
sync_with_physical: Sync vbot state with physical bot
Args: operation: Operation to perform (see CRUD and Virtual Robot Operations above). robot_type: Type of robot (required for create/spawn). Examples: "scout", "go2", "g1", "robbie", "custom" robot_id: Virtual robot identifier (required for read, update, delete, get_status, etc.). Auto-generated for create/spawn if not provided. platform: Target platform ("unity" or "vrchat"). Default: "unity". position: Spawn/update position (x, y, z) for create/spawn/update. scale: Size multiplier for create/spawn/update/set_scale. metadata: Additional metadata dictionary for create/update. model_path: Path to 3D model file (.glb, .fbx, .vrm) for custom robot_type. environment: Environment name (Marble-generated) for load_environment. environment_path: Path to environment file for load_environment. project_path: Unity project path (optional, auto-detected if not provided). include_colliders: Whether to import collider meshes (default: True).
Returns: Dictionary containing operation result with robot details.
Examples: # Create a Scout vbot result = await robot_virtual( operation="create", robot_type="scout", platform="unity", position={"x": 0.0, "y": 0.0, "z": 0.0}, scale=1.0 )
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| operation | Yes | ||
| robot_type | No | ||
| robot_id | No | ||
| platform | No | unity | |
| position | No | ||
| scale | No | ||
| metadata | No | ||
| model_path | No | ||
| environment | No | ||
| environment_path | No | ||
| project_path | No | ||
| include_colliders | No |
Implementation Reference
- The main handler function 'robot_virtual' decorated with @mcp.tool(). It defines the input schema and dispatches to specific operation handlers (CRUD and virtual robot ops) based on the 'operation' parameter.@self.mcp.tool() async def robot_virtual( operation: Literal[ # CRUD operations "create", "read", "update", "delete", "list", # Virtual robot operations "spawn", "load_environment", "get_status", "get_lidar", "set_scale", "test_navigation", "sync_with_physical", ], robot_type: Optional[str] = None, robot_id: Optional[str] = None, platform: Literal["unity", "vrchat"] = "unity", position: Optional[Dict[str, float]] = None, scale: Optional[float] = None, metadata: Optional[Dict[str, Any]] = None, model_path: Optional[str] = None, environment: Optional[str] = None, environment_path: Optional[str] = None, project_path: Optional[str] = None, include_colliders: bool = True, ) -> Dict[str, Any]: """Virtual robot lifecycle and operations portmanteau. PORTMANTEAU PATTERN: Consolidates virtual robot CRUD operations and virtual robotics operations into a single unified tool. This reduces tool explosion while maintaining full functionality for virtual robot management. CRUD OPERATIONS: - create: Create/spawn and register a new virtual robot - read: Get details of an existing virtual robot - update: Modify virtual robot properties (scale, position, metadata, etc.) - delete: Remove and unregister a virtual robot - list: List all virtual robots with optional filtering VIRTUAL ROBOT OPERATIONS: - spawn: Spawn robot in Unity/VRChat scene (alias for create) - load_environment: Load Marble/Chisel environment into scene - get_status: Get virtual robot status - get_lidar: Get virtual LiDAR scan (Unity physics raycast) - set_scale: Scale robot size (for size testing) - test_navigation: Test pathfinding in environment - sync_with_physical: Sync vbot state with physical bot Args: operation: Operation to perform (see CRUD and Virtual Robot Operations above). robot_type: Type of robot (required for create/spawn). Examples: "scout", "go2", "g1", "robbie", "custom" robot_id: Virtual robot identifier (required for read, update, delete, get_status, etc.). Auto-generated for create/spawn if not provided. platform: Target platform ("unity" or "vrchat"). Default: "unity". position: Spawn/update position (x, y, z) for create/spawn/update. scale: Size multiplier for create/spawn/update/set_scale. metadata: Additional metadata dictionary for create/update. model_path: Path to 3D model file (.glb, .fbx, .vrm) for custom robot_type. environment: Environment name (Marble-generated) for load_environment. environment_path: Path to environment file for load_environment. project_path: Unity project path (optional, auto-detected if not provided). include_colliders: Whether to import collider meshes (default: True). Returns: Dictionary containing operation result with robot details. Examples: # Create a Scout vbot result = await robot_virtual( operation="create", robot_type="scout", platform="unity", position={"x": 0.0, "y": 0.0, "z": 0.0}, scale=1.0 ) # Spawn robot (alias for create) result = await robot_virtual( operation="spawn", robot_type="scout", platform="unity" ) # Read vbot details result = await robot_virtual( operation="read", robot_id="vbot_scout_01" ) # Update vbot result = await robot_virtual( operation="update", robot_id="vbot_scout_01", scale=1.5, position={"x": 2.0, "y": 0.0, "z": 2.0} ) # Load environment result = await robot_virtual( operation="load_environment", environment="stroheckgasse_apartment", platform="unity" ) # Get LiDAR scan result = await robot_virtual( operation="get_lidar", robot_id="vbot_scout_01" ) # List all vbots result = await robot_virtual(operation="list") """ try: # Route to appropriate handler if operation in ["create", "spawn"]: return await self._handle_create(robot_type, robot_id, platform, position, scale, metadata, model_path) elif operation == "read": return await self._handle_read(robot_id) elif operation == "update": return await self._handle_update(robot_id, position, scale, metadata) elif operation == "delete": return await self._handle_delete(robot_id) elif operation == "list": return await self._handle_list(robot_type, platform) elif operation == "load_environment": return await self._handle_load_environment(environment, platform, environment_path, project_path, include_colliders) elif operation == "get_status": return await self._handle_get_status(robot_id) elif operation == "get_lidar": return await self._handle_get_lidar(robot_id) elif operation == "set_scale": return await self._handle_set_scale(robot_id, scale) elif operation == "test_navigation": return await self._handle_test_navigation(robot_id, environment) elif operation == "sync_with_physical": return await self._handle_sync_with_physical(robot_id) else: return format_error_response(f"Unknown operation: {operation}", error_type="validation_error") except Exception as e: return handle_tool_error("robot_virtual", e, operation=operation, robot_type=robot_type, robot_id=robot_id)
- Input schema for the robot_virtual tool, defining supported operations, robot parameters, and platform-specific args.async def robot_virtual( operation: Literal[ # CRUD operations "create", "read", "update", "delete", "list", # Virtual robot operations "spawn", "load_environment", "get_status", "get_lidar", "set_scale", "test_navigation", "sync_with_physical", ], robot_type: Optional[str] = None, robot_id: Optional[str] = None, platform: Literal["unity", "vrchat"] = "unity", position: Optional[Dict[str, float]] = None, scale: Optional[float] = None, metadata: Optional[Dict[str, Any]] = None, model_path: Optional[str] = None, environment: Optional[str] = None, environment_path: Optional[str] = None, project_path: Optional[str] = None, include_colliders: bool = True, ) -> Dict[str, Any]:
- src/robotics_mcp/server.py:484-485 (registration)Registration of the robot_virtual tool by instantiating RobotVirtualTool and calling its register() method in the main server.self.robot_virtual.register() # Virtual: CRUD + virtual robot operations logger.debug("Registered robot_virtual tool")
- Constant defining supported virtual robot types used in validation.SUPPORTED_ROBOT_TYPES = ["scout", "scout_e", "go2", "g1", "robbie", "custom"]
- Example helper handler for 'create'/'spawn' operations, handling validation, registration, spawning in platform (Unity/VRChat), and response formatting.async def _handle_create( self, robot_type: Optional[str], robot_id: Optional[str], platform: str, position: Optional[Dict[str, float]], scale: Optional[float], metadata: Optional[Dict[str, Any]], model_path: Optional[str], ) -> Dict[str, Any]: """Create/spawn a new virtual robot.""" if not robot_type: return format_error_response("robot_type is required for create/spawn operation", error_type="validation_error") if robot_type not in SUPPORTED_ROBOT_TYPES: return format_error_response( f"Unsupported robot_type: {robot_type}. Supported: {', '.join(SUPPORTED_ROBOT_TYPES)}", error_type="validation_error", ) if robot_type == "custom" and not model_path: return format_error_response("model_path is required for custom robot_type", error_type="validation_error") if not robot_id: robot_id = f"vbot_{robot_type}_{len(self.state_manager.list_robots(is_virtual=True)) + 1:02d}" if self.state_manager.get_robot(robot_id): return format_error_response(f"Robot {robot_id} already exists", error_type="validation_error") position = position or {"x": 0.0, "y": 0.0, "z": 0.0} scale = scale or 1.0 vbot_metadata = { "spawned": True, "platform": platform, "position": position, "scale": scale, "model_path": model_path, **(metadata or {}), } try: robot = self.state_manager.register_robot(robot_id, robot_type, platform=platform, metadata=vbot_metadata) except ValueError as e: return format_error_response(str(e), error_type="validation_error") spawn_result = await self._spawn_in_platform(robot_id, robot_type, platform, position, scale, model_path) if spawn_result.get("status") != "success": self.state_manager.unregister_robot(robot_id) return spawn_result return format_success_response( f"Virtual robot {robot_id} created successfully", data={"robot_id": robot_id, "robot_type": robot_type, "platform": platform, "position": position, "scale": scale}, robot_id=robot_id, )