Skip to content
ClaudeUnreal
GitHub

Audio & MetaSound

This content is not available in your language yet.

11 tools — 0 typed MCP · 11 via cu CLI.

  • Audio — Creation & Playback — 11 tools

Attach an AudioComponent to an actor or Blueprint

@mcp.tool()
@showcase(
"Attach an AudioComponent to an actor or Blueprint",
featured=True,
)
def add_audio_component(
ctx: Context,
target: str,
sound: str,
component_name: str = "AudioComponent",
auto_activate: bool = False,
attenuation: str = None,
sound_class: str = None,
) -> ToolResult:
"""[Audio] Add a UAudioComponent to an actor or Blueprint with a sound assigned.
Anti-patterns:
- Do not pass ``sound`` to an asset that is not a ``USoundBase`` subclass
(SoundWave/SoundCue/MetaSoundSource) — handler rejects with "Asset is
not a USoundBase".
- Do not pass ``attenuation`` or ``sound_class`` paths that don't resolve
to ``USoundAttenuation``/``USoundClass`` — handler rejects with "asset
not found".
- Do not pass ``target`` that is neither a scene actor nor a Blueprint
under ``/Game/Blueprints/`` — only those two locations are searched.
Args:
ctx: The MCP context
target: Name of a scene actor OR Blueprint name under /Game/Blueprints
sound: Path to a SoundBase asset (SoundWave, SoundCue, MetaSoundSource)
e.g. "/Game/Audio/MySound"
component_name: Component name (default "AudioComponent")
auto_activate: Whether the component should auto-play on spawn (default False)
attenuation: Optional Sound Attenuation asset path for spatial falloff
sound_class: Optional Sound Class asset path for mix grouping
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to add AudioComponent: no connection to Unreal Engine")
params: Dict[str, object] = {
"target": target,
"sound": sound,
"component_name": component_name,
"auto_activate": auto_activate,
}
if attenuation is not None:
params["attenuation"] = attenuation
if sound_class is not None:
params["sound_class"] = sound_class
response = unreal.send_command("add_audio_component", params)
if not response:
return err("Failed to add AudioComponent: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to add AudioComponent", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Added AudioComponent '{component_name}' to {target}",
target=result.get("target", target),
target_type=result.get("target_type", ""),
component_name=result.get("component_name", component_name),
sound=result.get("sound", sound),
auto_activate=result.get("auto_activate", auto_activate),
)
except Exception as e:
logger.error(f"Error adding AudioComponent: {e}")
return err("Failed to add AudioComponent", error=str(e))

Add a graph input to a MetaSound asset

@mcp.tool()
@showcase(
"Add a graph input to a MetaSound asset",
featured=False,
)
def add_metasound_input(
ctx: Context,
metasound: str,
input_name: str,
data_type: str = "Float",
default_value: str = None,
) -> ToolResult:
"""[Audio] Add a graph input (exposed parameter) to a MetaSound asset.
Creates an input node on the MetaSound graph so the exposed parameter
can be read inside the graph and driven from BP / AudioComponent via
set_metasound_parameter.
Anti-patterns:
- Do not pass ``data_type`` outside the supported set (``Float``, ``Bool``,
``Int``/``Int32``, ``String``, ``Trigger``, ``Audio``, ``Time``,
``Double``) — unknown types are passed through verbatim and the
underlying builder will reject them.
- Do not pass a ``default_value`` whose JSON type does not match
``data_type`` (e.g. ``"hello"`` for ``Float``) — only matching types are
applied; ``Trigger``/``Audio`` ignore ``default_value`` entirely.
- Do not call before ``create_metasound`` — handler rejects with
"MetaSound asset not found".
Args:
ctx: The MCP context
metasound: MetaSound asset reference — short name (resolved under
/Game/Audio) or full path (e.g. "/Game/Audio/MS_Drone")
input_name: Name of the input parameter (e.g. "Intensity")
data_type: MetaSound data type. Supported: "Float", "Bool", "Int",
"String", "Trigger", "Audio", "Time" (default "Float")
default_value: JSON-encoded default value matching the data type.
Examples: "0.5" (float), "true" (bool), "42" (int),
"\\"hello\\"" (string). Ignored for Trigger/Audio.
"""
from claude_unreal_server import get_unreal_connection
import json as _json
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to add MetaSound input: no connection to Unreal Engine")
params: Dict[str, object] = {
"metasound": metasound,
"input_name": input_name,
"data_type": data_type,
}
if default_value is not None:
try:
params["default_value"] = _json.loads(default_value)
except (ValueError, TypeError):
params["default_value"] = default_value
response = unreal.send_command("add_metasound_input", params)
if not response:
return err("Failed to add MetaSound input: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to add MetaSound input", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Added input '{input_name}' ({data_type}) to {metasound}",
metasound=result.get("metasound", metasound),
input_name=result.get("input_name", input_name),
data_type=result.get("data_type", data_type),
node_id=result.get("node_id", ""),
)
except Exception as e:
logger.error(f"Error adding MetaSound input: {e}")
return err("Failed to add MetaSound input", error=str(e))

Add a node (oscillator, math op, etc.) to a MetaSound graph

@mcp.tool()
@showcase(
"Add a node (oscillator, math op, etc.) to a MetaSound graph",
featured=False,
)
def add_metasound_node(
ctx: Context,
metasound: str,
class_name: str,
major_version: int = 1,
) -> ToolResult:
"""[Audio] Add a node instance to a MetaSound graph by its registered class name.
Anti-patterns:
- Do not pass ``class_name`` for a class that is not registered in the
MetaSound Frontend — handler rejects with "class may not be registered".
Use a verified ``Namespace.Name`` like ``UE.Sine`` or ``UE.Add.Float``.
- Do not pass ``major_version`` that does not exist for the given class —
same registration check.
Args:
ctx: The MCP context
metasound: MetaSound asset reference (short name or full path)
class_name: Dot-separated class name. Accepts:
"Name", "Namespace.Name", or "Namespace.Name.Variant".
Examples: "UE.Sine", "UE.Add.Float", "UE.Multiply.Audio"
major_version: Major version of the class to instantiate (default 1)
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to add MetaSound node: no connection to Unreal Engine")
params: Dict[str, object] = {
"metasound": metasound,
"class_name": class_name,
"major_version": major_version,
}
response = unreal.send_command("add_metasound_node", params)
if not response:
return err("Failed to add MetaSound node: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to add MetaSound node", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Added node '{class_name}' to {metasound}",
metasound=result.get("metasound", metasound),
class_name=result.get("class_name", class_name),
major_version=result.get("major_version", major_version),
node_id=result.get("node_id", ""),
)
except Exception as e:
logger.error(f"Error adding MetaSound node: {e}")
return err("Failed to add MetaSound node", error=str(e))

Connect two nodes in a MetaSound graph

@mcp.tool()
@showcase(
"Connect two nodes in a MetaSound graph",
featured=False,
)
def connect_metasound_nodes(
ctx: Context,
metasound: str,
from_node_id: str,
from_output: str,
to_node_id: str,
to_input: str,
) -> ToolResult:
"""[Audio] Connect an output pin of one MetaSound node to an input pin of another.
Use node_id values returned from add_metasound_input / add_metasound_node,
or discovered via get_metasound_info.
Anti-patterns:
- Do not pass ``from_node_id`` / ``to_node_id`` that are not valid GUIDs
— handler rejects with "Invalid 'from_node_id' guid".
- Do not pass ``from_output`` / ``to_input`` pin names that don't exist on
the respective nodes — handler rejects with "Output … not found" /
"Input … not found".
- Do not connect mismatched data types (e.g. ``Audio`` -> ``Float``) —
underlying ``ConnectNodes`` rejects with "data types may not match".
Args:
ctx: The MCP context
metasound: MetaSound asset reference (short name or full path)
from_node_id: Source node GUID (from add_metasound_* results)
from_output: Source output pin name (e.g. "Audio", "Out")
to_node_id: Destination node GUID
to_input: Destination input pin name (e.g. "Frequency", "In")
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to connect MetaSound nodes: no connection to Unreal Engine")
params: Dict[str, object] = {
"metasound": metasound,
"from_node_id": from_node_id,
"from_output": from_output,
"to_node_id": to_node_id,
"to_input": to_input,
}
response = unreal.send_command("connect_metasound_nodes", params)
if not response:
return err("Failed to connect MetaSound nodes: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to connect MetaSound nodes", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Connected {from_node_id[:8]}.{from_output}{to_node_id[:8]}.{to_input}",
metasound=result.get("metasound", metasound),
from_node_id=result.get("from_node_id", from_node_id),
from_output=result.get("from_output", from_output),
to_node_id=result.get("to_node_id", to_node_id),
to_input=result.get("to_input", to_input),
)
except Exception as e:
logger.error(f"Error connecting MetaSound nodes: {e}")
return err("Failed to connect MetaSound nodes", error=str(e))

Create a MetaSound Source or Patch asset

@mcp.tool()
@showcase(
"Create a MetaSound Source or Patch asset",
featured=True,
)
def create_metasound(
ctx: Context,
name: str,
path: str = "/Game/Audio",
type: str = "Source",
) -> ToolResult:
"""[Audio] Create a new MetaSound asset.
Anti-patterns:
- Do not pass ``type`` outside ``Source`` or ``Patch`` — anything else
silently falls back to ``Source``. Use ``Patch`` for reusable subgraphs,
``Source`` for playable assets.
- Do not pass ``path`` outside ``/Game/`` — handler rejects with "Invalid
package path".
- Requires the ``MetaSoundEngine`` plugin to be enabled.
Args:
ctx: The MCP context
name: Asset name (e.g. "MS_AmbientDrone")
path: Content path (default "/Game/Audio")
type: MetaSound type — "Source" (playable) or "Patch" (reusable graph)
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to create MetaSound: no connection to Unreal Engine")
params: Dict[str, object] = {
"name": name,
"path": path,
"type": type,
}
response = unreal.send_command("create_metasound", params)
if not response:
return err("Failed to create MetaSound: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to create MetaSound", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Created MetaSound {result.get('type', type)} '{name}' at {result.get('path', path)}",
name=result.get("name", name),
path=result.get("path", ""),
type=result.get("type", type),
)
except Exception as e:
logger.error(f"Error creating MetaSound: {e}")
return err("Failed to create MetaSound", error=str(e))

Create a Sound Attenuation asset for spatial audio falloff

@mcp.tool()
@showcase(
"Create a Sound Attenuation asset for spatial audio falloff",
featured=False,
)
def create_sound_attenuation(
ctx: Context,
name: str,
path: str = "/Game/Audio",
falloff_distance: float = None,
attenuation_distance: float = None,
) -> ToolResult:
"""[Audio] Create a Sound Attenuation asset.
Args:
ctx: The MCP context
name: Asset name (e.g. "Att_3DFalloff")
path: Content path (default "/Game/Audio")
falloff_distance: Optional falloff distance in cm (distance over which
attenuation happens from inner radius to silence)
attenuation_distance: Optional inner attenuation radius in cm
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to create Sound Attenuation: no connection to Unreal Engine")
params: Dict[str, object] = {"name": name, "path": path}
if falloff_distance is not None:
params["falloff_distance"] = falloff_distance
if attenuation_distance is not None:
params["attenuation_distance"] = attenuation_distance
response = unreal.send_command("create_sound_attenuation", params)
if not response:
return err("Failed to create Sound Attenuation: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to create Sound Attenuation", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Created Sound Attenuation '{name}' at {result.get('path', path)}",
name=result.get("name", name),
path=result.get("path", ""),
falloff_distance=result.get("falloff_distance", 0.0),
)
except Exception as e:
logger.error(f"Error creating Sound Attenuation: {e}")
return err("Failed to create Sound Attenuation", error=str(e))

Create a Sound Class asset for mix grouping

@mcp.tool()
@showcase(
"Create a Sound Class asset for mix grouping",
featured=False,
)
def create_sound_class(
ctx: Context,
name: str,
path: str = "/Game/Audio",
volume: float = None,
pitch: float = None,
) -> ToolResult:
"""[Audio] Create a Sound Class asset used to group sounds for mixing.
Args:
ctx: The MCP context
name: Asset name (e.g. "SC_Ambient")
path: Content path (default "/Game/Audio")
volume: Optional default class volume multiplier
pitch: Optional default class pitch multiplier
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to create Sound Class: no connection to Unreal Engine")
params: Dict[str, object] = {"name": name, "path": path}
if volume is not None:
params["volume"] = volume
if pitch is not None:
params["pitch"] = pitch
response = unreal.send_command("create_sound_class", params)
if not response:
return err("Failed to create Sound Class: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to create Sound Class", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Created Sound Class '{name}' at {result.get('path', path)}",
name=result.get("name", name),
path=result.get("path", ""),
volume=result.get("volume", 1.0),
pitch=result.get("pitch", 1.0),
)
except Exception as e:
logger.error(f"Error creating Sound Class: {e}")
return err("Failed to create Sound Class", error=str(e))

Create a Sound Mix with per-SoundClass adjusters

@mcp.tool()
@showcase(
"Create a Sound Mix with per-SoundClass adjusters",
featured=False,
)
def create_sound_mix(
ctx: Context,
name: str,
path: str = "/Game/Audio",
class_adjusters: List[Dict[str, str]] = None,
) -> ToolResult:
"""[Audio] Create a Sound Mix asset with optional per-SoundClass adjusters.
Args:
ctx: The MCP context
name: Asset name (e.g. "SM_Duck")
path: Content path (default "/Game/Audio")
class_adjusters: Optional list of dicts describing per-class adjustments.
Each dict accepts: sound_class (asset path, required),
volume (float), pitch (float).
Example: [{"sound_class": "/Game/Audio/SC_Music",
"volume": 0.3, "pitch": 1.0}]
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to create Sound Mix: no connection to Unreal Engine")
params: Dict[str, object] = {"name": name, "path": path}
if class_adjusters is not None:
params["class_adjusters"] = class_adjusters
response = unreal.send_command("create_sound_mix", params)
if not response:
return err("Failed to create Sound Mix: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to create Sound Mix", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Created Sound Mix '{name}' at {result.get('path', path)}",
name=result.get("name", name),
path=result.get("path", ""),
num_class_adjusters=result.get("num_class_adjusters", 0),
)
except Exception as e:
logger.error(f"Error creating Sound Mix: {e}")
return err("Failed to create Sound Mix", error=str(e))

Inspect a MetaSound graph — list inputs, outputs, and nodes

@mcp.tool()
@showcase(
"Inspect a MetaSound graph — list inputs, outputs, and nodes",
featured=False,
)
def get_metasound_info(
ctx: Context,
metasound: str,
) -> ToolResult:
"""[Audio] Get the inputs, outputs, and node list of a MetaSound asset.
Useful for discovering existing node IDs and pin names before calling
connect_metasound_nodes.
Args:
ctx: The MCP context
metasound: MetaSound asset reference (short name or full path)
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to get MetaSound info: no connection to Unreal Engine")
params: Dict[str, object] = {"metasound": metasound}
response = unreal.send_command("get_metasound_info", params)
if not response:
return err("Failed to get MetaSound info: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to get MetaSound info", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"MetaSound {metasound}: {result.get('num_nodes', 0)} nodes, "
f"{result.get('num_inputs', 0)} inputs, {result.get('num_outputs', 0)} outputs",
metasound=result.get("metasound", metasound),
inputs=result.get("inputs", []),
outputs=result.get("outputs", []),
nodes=result.get("nodes", []),
num_inputs=result.get("num_inputs", 0),
num_outputs=result.get("num_outputs", 0),
num_nodes=result.get("num_nodes", 0),
)
except Exception as e:
logger.error(f"Error getting MetaSound info: {e}")
return err("Failed to get MetaSound info", error=str(e))

Adjust runtime audio parameters on a placed AudioComponent

@mcp.tool()
@showcase(
"Adjust runtime audio parameters on a placed AudioComponent",
featured=False,
)
def set_audio_parameter(
ctx: Context,
actor_name: str,
component_name: str = "",
volume: float = None,
pitch: float = None,
low_pass_frequency: float = None,
) -> ToolResult:
"""[Audio] Set runtime audio parameters on an AudioComponent attached to an actor.
Anti-patterns:
- Do not call this against an actor with no ``UAudioComponent`` — handler
rejects with "Actor … has no AudioComponent". Add one via
``add_audio_component`` first.
- Do not call with all of ``volume``/``pitch``/``low_pass_frequency``
unset — the call succeeds but applies nothing.
Args:
ctx: The MCP context
actor_name: Name of the actor carrying the AudioComponent
component_name: Optional specific component name (defaults to the first
AudioComponent on the actor if empty)
volume: Optional volume multiplier (0.0 - 1.0 typical, can go higher)
pitch: Optional pitch multiplier (0.5 - 2.0 typical range)
low_pass_frequency: Optional low-pass filter cutoff in Hz (e.g. 2000).
Enables the filter when set.
"""
from claude_unreal_server import get_unreal_connection
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to set audio parameter: no connection to Unreal Engine")
params: Dict[str, object] = {"actor_name": actor_name}
if component_name:
params["component_name"] = component_name
if volume is not None:
params["volume"] = volume
if pitch is not None:
params["pitch"] = pitch
if low_pass_frequency is not None:
params["low_pass_frequency"] = low_pass_frequency
response = unreal.send_command("set_audio_parameter", params)
if not response:
return err("Failed to set audio parameter: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to set audio parameter", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Updated audio parameters on '{actor_name}'",
actor_name=result.get("actor_name", actor_name),
component_name=result.get("component_name", component_name),
applied=result.get("applied", {}),
)
except Exception as e:
logger.error(f"Error setting audio parameter: {e}")
return err("Failed to set audio parameter", error=str(e))

Set a MetaSound input parameter on a playing AudioComponent

@mcp.tool()
@showcase(
"Set a MetaSound input parameter on a playing AudioComponent",
featured=False,
)
def set_metasound_parameter(
ctx: Context,
actor_name: str,
parameter_name: str,
value: str,
component_name: str = "",
) -> ToolResult:
"""[Audio] Set a MetaSound input parameter on an AudioComponent playing a MetaSound.
The value type is auto-detected: numbers map to float, "true"/"false"
map to bool. Runs against a live AudioComponent so the MetaSound must be
playing (e.g. during PIE) for the value to take effect immediately.
Anti-patterns:
- Do not pass a JSON-encoded string ``value`` — ``UAudioComponent`` exposes
no ``SetStringParameter``, handler rejects with "String parameters not
supported … (use float/int/bool)".
- Do not call this when no AudioComponent is on the actor — handler
rejects with "no AudioComponent".
- Do not pass ``parameter_name`` that does not match a graph input on the
playing MetaSound — the underlying call silently no-ops.
- Do not call outside PIE expecting an immediate audible change — the
MetaSound must be actively playing.
Args:
ctx: The MCP context
actor_name: Name of the actor carrying the AudioComponent
parameter_name: MetaSound input name (e.g. "Intensity", "Pitch")
value: JSON-encoded value. Examples: "0.75" (float), "true" (bool),
"42" (int mapped to float)
component_name: Optional specific AudioComponent name
"""
from claude_unreal_server import get_unreal_connection
import json as _json
try:
unreal = get_unreal_connection()
if not unreal:
return err("Failed to set MetaSound parameter: no connection to Unreal Engine")
try:
parsed_value = _json.loads(value)
except (ValueError, TypeError):
parsed_value = value
params: Dict[str, object] = {
"actor_name": actor_name,
"parameter_name": parameter_name,
"value": parsed_value,
}
if component_name:
params["component_name"] = component_name
response = unreal.send_command("set_metasound_parameter", params)
if not response:
return err("Failed to set MetaSound parameter: no response from Unreal Engine")
if response.get("status") == "error":
return err("Failed to set MetaSound parameter", error=response.get("error", "Unknown error"))
result = response.get("result", response)
return ok(
f"Set '{parameter_name}' on '{actor_name}'",
actor_name=result.get("actor_name", actor_name),
component_name=result.get("component_name", component_name),
parameter_name=result.get("parameter_name", parameter_name),
parameter_type=result.get("parameter_type", ""),
)
except Exception as e:
logger.error(f"Error setting MetaSound parameter: {e}")
return err("Failed to set MetaSound parameter", error=str(e))