blueprint_tools.py•17.2 kB
"""
Blueprint Tools for Unreal MCP.
This module provides tools for creating and manipulating Blueprint assets in Unreal Engine.
"""
import logging
from typing import Dict, List, Any
from mcp.server.fastmcp import FastMCP, Context
# Get logger
logger = logging.getLogger("UnrealMCP")
def register_blueprint_tools(mcp: FastMCP):
"""Register Blueprint tools with the MCP server."""
@mcp.tool()
def create_blueprint(
ctx: Context,
name: str,
parent_class: str
) -> Dict[str, Any]:
"""Create a new Blueprint class."""
# Import inside function to avoid circular imports
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("create_blueprint", {
"name": name,
"parent_class": parent_class
})
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Blueprint creation response: {response}")
return response or {}
except Exception as e:
error_msg = f"Error creating blueprint: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def add_component_to_blueprint(
ctx: Context,
blueprint_name: str,
component_type: str,
component_name: str,
location: List[float] = [],
rotation: List[float] = [],
scale: List[float] = [],
component_properties: Dict[str, Any] = {}
) -> Dict[str, Any]:
"""
Add a component to a Blueprint.
Args:
blueprint_name: Name of the target Blueprint
component_type: Type of component to add (use component class name without U prefix)
component_name: Name for the new component
location: [X, Y, Z] coordinates for component's position
rotation: [Pitch, Yaw, Roll] values for component's rotation
scale: [X, Y, Z] values for component's scale
component_properties: Additional properties to set on the component
Returns:
Information about the added component
"""
from unreal_mcp_server import get_unreal_connection
try:
# Ensure all parameters are properly formatted
params = {
"blueprint_name": blueprint_name,
"component_type": component_type,
"component_name": component_name,
"location": location or [0.0, 0.0, 0.0],
"rotation": rotation or [0.0, 0.0, 0.0],
"scale": scale or [1.0, 1.0, 1.0]
}
# Add component_properties if provided
if component_properties and len(component_properties) > 0:
params["component_properties"] = component_properties
# Validate location, rotation, and scale formats
for param_name in ["location", "rotation", "scale"]:
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]
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"}
logger.info(f"Adding component to blueprint with params: {params}")
response = unreal.send_command("add_component_to_blueprint", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Component addition response: {response}")
return response
except Exception as e:
error_msg = f"Error adding component to blueprint: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def set_static_mesh_properties(
ctx: Context,
blueprint_name: str,
component_name: str,
static_mesh: str = "/Engine/BasicShapes/Cube.Cube"
) -> Dict[str, Any]:
"""
Set static mesh properties on a StaticMeshComponent.
Args:
blueprint_name: Name of the target Blueprint
component_name: Name of the StaticMeshComponent
static_mesh: Path to the static mesh asset (e.g., "/Engine/BasicShapes/Cube.Cube")
Returns:
Response indicating success or failure
"""
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 = {
"blueprint_name": blueprint_name,
"component_name": component_name,
"static_mesh": static_mesh
}
logger.info(f"Setting static mesh properties with params: {params}")
response = unreal.send_command("set_static_mesh_properties", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Set static mesh properties response: {response}")
return response
except Exception as e:
error_msg = f"Error setting static mesh properties: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def set_component_property(
ctx: Context,
blueprint_name: str,
component_name: str,
property_name: str,
property_value,
) -> Dict[str, Any]:
"""Set a property on a component in a Blueprint."""
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 = {
"blueprint_name": blueprint_name,
"component_name": component_name,
"property_name": property_name,
"property_value": property_value
}
logger.info(f"Setting component property with params: {params}")
response = unreal.send_command("set_component_property", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Set component property response: {response}")
return response
except Exception as e:
error_msg = f"Error setting component property: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def set_physics_properties(
ctx: Context,
blueprint_name: str,
component_name: str,
simulate_physics: bool = True,
gravity_enabled: bool = True,
mass: float = 1.0,
linear_damping: float = 0.01,
angular_damping: float = 0.0
) -> Dict[str, Any]:
"""Set physics properties on a component."""
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 = {
"blueprint_name": blueprint_name,
"component_name": component_name,
"simulate_physics": simulate_physics,
"gravity_enabled": gravity_enabled,
"mass": float(mass),
"linear_damping": float(linear_damping),
"angular_damping": float(angular_damping)
}
logger.info(f"Setting physics properties with params: {params}")
response = unreal.send_command("set_physics_properties", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Set physics properties response: {response}")
return response
except Exception as e:
error_msg = f"Error setting physics properties: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def compile_blueprint(
ctx: Context,
blueprint_name: str
) -> Dict[str, Any]:
"""Compile a Blueprint."""
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 = {
"blueprint_name": blueprint_name
}
logger.info(f"Compiling blueprint: {blueprint_name}")
response = unreal.send_command("compile_blueprint", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Compile blueprint response: {response}")
return response
except Exception as e:
error_msg = f"Error compiling blueprint: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
@mcp.tool()
def set_blueprint_property(
ctx: Context,
blueprint_name: str,
property_name: str,
property_value
) -> Dict[str, Any]:
"""
Set a property on a Blueprint class default object.
Args:
blueprint_name: Name of the target Blueprint
property_name: Name of the property to set
property_value: Value to set the property to
Returns:
Response indicating success or failure
"""
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 = {
"blueprint_name": blueprint_name,
"property_name": property_name,
"property_value": property_value
}
logger.info(f"Setting blueprint property with params: {params}")
response = unreal.send_command("set_blueprint_property", params)
if not response:
logger.error("No response from Unreal Engine")
return {"success": False, "message": "No response from Unreal Engine"}
logger.info(f"Set blueprint property response: {response}")
return response
except Exception as e:
error_msg = f"Error setting blueprint property: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
# @mcp.tool() commented out, just use set_component_property instead
def set_pawn_properties(
ctx: Context,
blueprint_name: str,
auto_possess_player: str = "",
use_controller_rotation_yaw: bool = None,
use_controller_rotation_pitch: bool = None,
use_controller_rotation_roll: bool = None,
can_be_damaged: bool = None
) -> Dict[str, Any]:
"""
Set common Pawn properties on a Blueprint.
This is a utility function that sets multiple pawn-related properties at once.
Args:
blueprint_name: Name of the target Blueprint (must be a Pawn or Character)
auto_possess_player: Auto possess player setting (None, "Disabled", "Player0", "Player1", etc.)
use_controller_rotation_yaw: Whether the pawn should use the controller's yaw rotation
use_controller_rotation_pitch: Whether the pawn should use the controller's pitch rotation
use_controller_rotation_roll: Whether the pawn should use the controller's roll rotation
can_be_damaged: Whether the pawn can be damaged
Returns:
Response indicating success or failure with detailed results for each property
"""
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"}
# Define the properties to set
properties = {}
if auto_possess_player and auto_possess_player != "":
properties["auto_possess_player"] = auto_possess_player
# Only include boolean properties if they were explicitly set
if use_controller_rotation_yaw is not None:
properties["bUseControllerRotationYaw"] = use_controller_rotation_yaw
if use_controller_rotation_pitch is not None:
properties["bUseControllerRotationPitch"] = use_controller_rotation_pitch
if use_controller_rotation_roll is not None:
properties["bUseControllerRotationRoll"] = use_controller_rotation_roll
if can_be_damaged is not None:
properties["bCanBeDamaged"] = can_be_damaged
if not properties:
logger.warning("No properties specified to set")
return {"success": True, "message": "No properties specified to set", "results": {}}
# Set each property using the generic set_blueprint_property function
results = {}
overall_success = True
for prop_name, prop_value in properties.items():
params = {
"blueprint_name": blueprint_name,
"property_name": prop_name,
"property_value": prop_value
}
logger.info(f"Setting pawn property {prop_name} to {prop_value}")
response = unreal.send_command("set_blueprint_property", params)
if not response:
logger.error(f"No response from Unreal Engine for property {prop_name}")
results[prop_name] = {"success": False, "message": "No response from Unreal Engine"}
overall_success = False
continue
results[prop_name] = response
if not response.get("success", False):
overall_success = False
return {
"success": overall_success,
"message": "Pawn properties set" if overall_success else "Some pawn properties failed to set",
"results": results
}
except Exception as e:
error_msg = f"Error setting pawn properties: {e}"
logger.error(error_msg)
return {"success": False, "message": error_msg}
logger.info("Blueprint tools registered successfully")