Skip to main content
Glama

Unreal Engine MCP Bridge

by gingerol
editor_tools.py14 kB
""" Editor Tools for Unreal MCP. This module provides tools for controlling the Unreal Editor viewport and other editor functionality. """ import logging from typing import Dict, List, Any, Optional from mcp.server.fastmcp import FastMCP, Context # Get logger logger = logging.getLogger("UnrealMCP") def register_editor_tools(mcp: FastMCP): """Register editor tools with the MCP server.""" @mcp.tool() def get_actors_in_level(ctx: Context) -> List[Dict[str, Any]]: """Get a list of all actors in the current level.""" from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.warning("Failed to connect to Unreal Engine") return [] response = unreal.send_command("get_actors_in_level", {}) if not response: logger.warning("No response from Unreal Engine") return [] # Log the complete response for debugging logger.info(f"Complete response from Unreal: {response}") # Check response format if "result" in response and "actors" in response["result"]: actors = response["result"]["actors"] logger.info(f"Found {len(actors)} actors in level") return actors elif "actors" in response: actors = response["actors"] logger.info(f"Found {len(actors)} actors in level") return actors logger.warning(f"Unexpected response format: {response}") return [] except Exception as e: logger.error(f"Error getting actors: {e}") return [] @mcp.tool() def find_actors_by_name(ctx: Context, pattern: str) -> List[str]: """Find actors by name pattern.""" from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.warning("Failed to connect to Unreal Engine") return [] response = unreal.send_command("find_actors_by_name", { "pattern": pattern }) if not response: return [] return response.get("actors", []) except Exception as e: logger.error(f"Error finding actors: {e}") return [] @mcp.tool() def spawn_actor( ctx: Context, name: str, type: str, location: List[float] = [0.0, 0.0, 0.0], rotation: List[float] = [0.0, 0.0, 0.0] ) -> Dict[str, Any]: """Create a new actor in the current level. Args: ctx: The MCP context name: The name to give the new actor (must be unique) type: The type of actor to create (e.g. StaticMeshActor, PointLight) location: The [x, y, z] world location to spawn at rotation: The [pitch, yaw, roll] rotation in degrees Returns: Dict containing the created actor's properties """ from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} # Ensure all parameters are properly formatted params = { "name": name, "type": type.upper(), # Make sure type is uppercase "location": location, "rotation": rotation } # Validate location and rotation formats for param_name in ["location", "rotation"]: param_value = params[param_name] if not isinstance(param_value, list) or len(param_value) != 3: logger.error(f"Invalid {param_name} format: {param_value}. Must be a list of 3 float values.") return {"success": False, "message": f"Invalid {param_name} format. Must be a list of 3 float values."} # Ensure all values are float params[param_name] = [float(val) for val in param_value] logger.info(f"Creating actor '{name}' of type '{type}' with params: {params}") response = unreal.send_command("spawn_actor", params) if not response: logger.error("No response from Unreal Engine") return {"success": False, "message": "No response from Unreal Engine"} # Log the complete response for debugging logger.info(f"Actor creation response: {response}") # Handle error responses correctly if response.get("status") == "error": error_message = response.get("error", "Unknown error") logger.error(f"Error creating actor: {error_message}") return {"success": False, "message": error_message} return response except Exception as e: error_msg = f"Error creating actor: {e}" logger.error(error_msg) return {"success": False, "message": error_msg} @mcp.tool() def delete_actor(ctx: Context, name: str) -> Dict[str, Any]: """Delete an actor by name.""" from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} response = unreal.send_command("delete_actor", { "name": name }) return response or {} except Exception as e: logger.error(f"Error deleting actor: {e}") return {} @mcp.tool() def set_actor_transform( ctx: Context, name: str, location: List[float] = None, rotation: List[float] = None, scale: List[float] = None ) -> Dict[str, Any]: """Set the transform of an actor.""" from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} params = {"name": name} if location is not None: params["location"] = location if rotation is not None: params["rotation"] = rotation if scale is not None: params["scale"] = scale response = unreal.send_command("set_actor_transform", params) return response or {} except Exception as e: logger.error(f"Error setting transform: {e}") return {} @mcp.tool() def get_actor_properties(ctx: Context, name: str) -> Dict[str, Any]: """Get all properties of an actor.""" from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} response = unreal.send_command("get_actor_properties", { "name": name }) return response or {} except Exception as e: logger.error(f"Error getting properties: {e}") return {} @mcp.tool() def set_actor_property( ctx: Context, name: str, property_name: str, property_value, ) -> Dict[str, Any]: """ Set a property on an actor. Args: name: Name of the actor property_name: Name of the property to set property_value: Value to set the property to Returns: Dict containing response from Unreal with operation status """ from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} response = unreal.send_command("set_actor_property", { "name": name, "property_name": property_name, "property_value": property_value }) if not response: logger.error("No response from Unreal Engine") return {"success": False, "message": "No response from Unreal Engine"} logger.info(f"Set actor property response: {response}") return response except Exception as e: error_msg = f"Error setting actor property: {e}" logger.error(error_msg) return {"success": False, "message": error_msg} # @mcp.tool() commented out because it's buggy def focus_viewport( ctx: Context, target: str = None, location: List[float] = None, distance: float = 1000.0, orientation: List[float] = None ) -> Dict[str, Any]: """ Focus the viewport on a specific actor or location. Args: target: Name of the actor to focus on (if provided, location is ignored) location: [X, Y, Z] coordinates to focus on (used if target is None) distance: Distance from the target/location orientation: Optional [Pitch, Yaw, Roll] for the viewport camera Returns: Response from Unreal Engine """ from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} params = {} if target: params["target"] = target elif location: params["location"] = location if distance: params["distance"] = distance if orientation: params["orientation"] = orientation response = unreal.send_command("focus_viewport", params) return response or {} except Exception as e: logger.error(f"Error focusing viewport: {e}") return {"status": "error", "message": str(e)} @mcp.tool() def spawn_blueprint_actor( ctx: Context, blueprint_name: str, actor_name: str, location: List[float] = [0.0, 0.0, 0.0], rotation: List[float] = [0.0, 0.0, 0.0] ) -> Dict[str, Any]: """Spawn an actor from a Blueprint. Args: ctx: The MCP context blueprint_name: Name of the Blueprint to spawn from actor_name: Name to give the spawned actor location: The [x, y, z] world location to spawn at rotation: The [pitch, yaw, roll] rotation in degrees Returns: Dict containing the spawned actor's properties """ from unreal_mcp_server import get_unreal_connection try: unreal = get_unreal_connection() if not unreal: logger.error("Failed to connect to Unreal Engine") return {"success": False, "message": "Failed to connect to Unreal Engine"} # Ensure all parameters are properly formatted params = { "blueprint_name": blueprint_name, "actor_name": actor_name, "location": location or [0.0, 0.0, 0.0], "rotation": rotation or [0.0, 0.0, 0.0] } # Validate location and rotation formats for param_name in ["location", "rotation"]: param_value = params[param_name] if not isinstance(param_value, list) or len(param_value) != 3: logger.error(f"Invalid {param_name} format: {param_value}. Must be a list of 3 float values.") return {"success": False, "message": f"Invalid {param_name} format. Must be a list of 3 float values."} # Ensure all values are float params[param_name] = [float(val) for val in param_value] logger.info(f"Spawning blueprint actor with params: {params}") response = unreal.send_command("spawn_blueprint_actor", params) if not response: logger.error("No response from Unreal Engine") return {"success": False, "message": "No response from Unreal Engine"} logger.info(f"Spawn blueprint actor response: {response}") return response except Exception as e: error_msg = f"Error spawning blueprint actor: {e}" logger.error(error_msg) return {"success": False, "message": error_msg} logger.info("Editor tools registered successfully")

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/gingerol/UnrealEngine-ai-mcp'

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