Skip to main content
Glama

Union Unity MCP Server

by nurture-tech
ViewService.cs7.45 kB
#if !NO_MCP using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using System.Threading.Tasks; using ModelContextProtocol; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; using UnityEditor; using UnityEngine; namespace Nurture.MCP.Editor.Services { [McpServerToolType] public static class ViewService { [McpServerTool( Destructive = false, Idempotent = true, OpenWorld = false, ReadOnly = false, Title = "Unity Focus on Game Object", Name = "focus_game_object" )] [Description("Focus on a game object in the scene view.")] internal static Task<string> FocusOnGameObject( SynchronizationContext context, CancellationToken cancellationToken, [Description("The path to the game object to focus on.")] string gameObjectHierarchyPath, [Description("Whether to hide all other game objects in the scene.")] bool isolated = false ) { return context.Run( async () => { // Get the last active scene view var sceneView = SceneView.lastActiveSceneView ?? throw new McpException("No active scene view found"); sceneView.Focus(); var gameObject = GameObject.Find(gameObjectHierarchyPath) ?? throw new McpException("Game object not found"); if (Selection.activeGameObject != gameObject) { Selection.activeGameObject = gameObject; } if (isolated) { SceneVisibilityManager.instance.Isolate(gameObject, true); } // Wait for the selection to be active await Task.Delay(500); // FIXME: Doing this twice focuses inside the object sceneView.FrameSelected(false, true); // Wait for focus to animate await Task.Delay(500); sceneView.Focus(); return $"Focused on {gameObjectHierarchyPath}"; }, cancellationToken ); } [McpServerTool( Destructive = false, Idempotent = true, OpenWorld = false, ReadOnly = true, Title = "Unity Take Scene View Screenshot", Name = "screenshot" )] [Description(@"Retrieve a preview of what is focused in the scene view.")] internal static async Task<ImageContentBlock> TakeScreenshot( SynchronizationContext context, CancellationToken cancellationToken, [Description( "The path to the camera to render. If null, it will use the editor scene view camera." )] string cameraHierarchyPath = "" ) { return await context.Run( async () => { string screenshotBase64 = null; Camera camera = null; if (cameraHierarchyPath?.Length > 0) { camera = GameObject.Find(cameraHierarchyPath)?.GetComponent<Camera>(); // If camera object is null or doesn't have a camera, just use the scene view camera // Some LLMs hallucinate a value here because they can't help setting some argument } if (camera != null) { // Create a new texture with the scene view's dimensions var texture = new Texture2D( (int)camera.pixelRect.width, (int)camera.pixelRect.height, TextureFormat.RGB24, false ); RenderTexture renderTexture = RenderTexture.GetTemporary( texture.width, texture.height, 24 ); // Store the current render texture and set our new one RenderTexture previousRenderTexture = camera.targetTexture; camera.targetTexture = renderTexture; // Render the scene view camera.Render(); // Store the active render texture and set our new one RenderTexture previousActiveTexture = RenderTexture.active; RenderTexture.active = renderTexture; // Read the pixels from the render texture to our texture texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); texture.Apply(); // Restore the previous render textures camera.targetTexture = previousRenderTexture; RenderTexture.active = previousActiveTexture; // Clean up RenderTexture.ReleaseTemporary(renderTexture); // Convert the texture to base64 screenshotBase64 = texture.GetPngBase64(); UnityEngine.Object.DestroyImmediate(texture); } else { // Get the last active scene view var sceneView = SceneView.lastActiveSceneView ?? throw new McpException("No active scene view found"); await EditorExtensions.FocusSceneView(cancellationToken); int width = Mathf.RoundToInt(sceneView.position.width); int height = Mathf.RoundToInt(sceneView.position.height); if (width <= 0 || height <= 0) { throw new McpException( $"Invalid Scene View dimensions: {width}x{height}" ); } Color[] pixels = UnityEditorInternal.InternalEditorUtility.ReadScreenPixel( sceneView.position.min, width, height ); var texture = new Texture2D(width, height, TextureFormat.RGB24, false); texture.SetPixels(pixels); texture.Apply(); screenshotBase64 = texture.GetPngBase64(); UnityEngine.Object.DestroyImmediate(texture); } return new ImageContentBlock() { Data = screenshotBase64, MimeType = "image/png", }; }, cancellationToken ); } } } #endif

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/nurture-tech/unity-mcp-server'

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