diff --git a/UnityMcpBridge/Editor/Tools/ManageGameObject.cs b/UnityMcpBridge/Editor/Tools/ManageGameObject.cs index c3357ed..4c11f34 100644 --- a/UnityMcpBridge/Editor/Tools/ManageGameObject.cs +++ b/UnityMcpBridge/Editor/Tools/ManageGameObject.cs @@ -155,6 +155,18 @@ namespace MCPForUnity.Editor.Tools ); // Pass the includeNonPublicSerialized flag here return GetComponentsFromTarget(getCompTarget, searchMethod, includeNonPublicSerialized); + case "get_component": + string getSingleCompTarget = targetToken?.ToString(); + if (getSingleCompTarget == null) + return Response.Error( + "'target' parameter required for get_component." + ); + string componentName = @params["componentName"]?.ToString(); + if (string.IsNullOrEmpty(componentName)) + return Response.Error( + "'componentName' parameter required for get_component." + ); + return GetSingleComponentFromTarget(getSingleCompTarget, searchMethod, componentName, includeNonPublicSerialized); case "add_component": return AddComponentToTarget(@params, targetToken, searchMethod); case "remove_component": @@ -1008,6 +1020,70 @@ namespace MCPForUnity.Editor.Tools } } + private static object GetSingleComponentFromTarget(string target, string searchMethod, string componentName, bool includeNonPublicSerialized = true) + { + GameObject targetGo = FindObjectInternal(target, searchMethod); + if (targetGo == null) + { + return Response.Error( + $"Target GameObject ('{target}') not found using method '{searchMethod ?? "default"}'." + ); + } + + try + { + // Try to find the component by name + Component targetComponent = targetGo.GetComponent(componentName); + + // If not found directly, try to find by type name (handle namespaces) + if (targetComponent == null) + { + Component[] allComponents = targetGo.GetComponents(); + foreach (Component comp in allComponents) + { + if (comp != null) + { + string typeName = comp.GetType().Name; + string fullTypeName = comp.GetType().FullName; + + if (typeName == componentName || fullTypeName == componentName) + { + targetComponent = comp; + break; + } + } + } + } + + if (targetComponent == null) + { + return Response.Error( + $"Component '{componentName}' not found on GameObject '{targetGo.name}'." + ); + } + + var componentData = Helpers.GameObjectSerializer.GetComponentData(targetComponent, includeNonPublicSerialized); + + if (componentData == null) + { + return Response.Error( + $"Failed to serialize component '{componentName}' on GameObject '{targetGo.name}'." + ); + } + + return Response.Success( + $"Retrieved component '{componentName}' from '{targetGo.name}'.", + componentData + ); + } + catch (Exception e) + { + return Response.Error( + $"Error getting component '{componentName}' from '{targetGo.name}': {e.Message}" + ); + } + } + private static object AddComponentToTarget( JObject @params, JToken targetToken, diff --git a/UnityMcpBridge/UnityMcpServer~/src/tools/manage_gameobject.py b/UnityMcpBridge/UnityMcpServer~/src/tools/manage_gameobject.py index eb766ff..41d4a1c 100644 --- a/UnityMcpBridge/UnityMcpServer~/src/tools/manage_gameobject.py +++ b/UnityMcpBridge/UnityMcpServer~/src/tools/manage_gameobject.py @@ -9,11 +9,11 @@ from unity_connection import send_command_with_retry def register_manage_gameobject_tools(mcp: FastMCP): """Register all GameObject management tools with the MCP server.""" - @mcp.tool(name="manage_gameobject", description="Manage GameObjects. Note: for 'get_components', the `data` field contains a dictionary of component names and their serialized properties.") + @mcp.tool(name="manage_gameobject", description="Manage GameObjects. Note: for 'get_components', the `data` field contains a dictionary of component names and their serialized properties. For 'get_component', specify 'component_name' to retrieve only that component's serialized data.") @telemetry_tool("manage_gameobject") def manage_gameobject( ctx: Context, - action: Annotated[Literal["create", "modify", "delete", "find", "add_component", "remove_component", "set_component_property", "get_components"], "Perform CRUD operations on GameObjects and components."], + action: Annotated[Literal["create", "modify", "delete", "find", "add_component", "remove_component", "set_component_property", "get_components", "get_component"], "Perform CRUD operations on GameObjects and components."], target: Annotated[str, "GameObject identifier by name or path for modify/delete/component actions"] | None = None, search_method: Annotated[Literal["by_id", "by_name", "by_path", "by_tag", "by_layer", "by_component"],