Skip to main content
Glama
MCPEditorWindow.cs13.7 kB
using UnityEngine; using UnityEditor; using System; namespace UnityMCP { /// <summary> /// Unity MCP Control Panel /// Clean UI for managing MCP server and viewing status /// </summary> public class MCPEditorWindow : EditorWindow { private MCPConfig config; private Vector2 scrollPosition; private bool showServerSettings = true; private bool showFeatures = false; private bool showAdvanced = false; private bool showTools = false; private DateTime lastStatusCheck; private ConnectionStatus connectionStatus = ConnectionStatus.Unknown; private string lastError = ""; private enum ConnectionStatus { Unknown, Connected, Connecting, Disconnected, Error } [MenuItem("Tools/Unity MCP/Control Panel", false, 0)] public static void ShowWindow() { var window = GetWindow<MCPEditorWindow>("MCP Control Panel"); window.minSize = new Vector2(400, 500); window.Show(); } private void OnEnable() { config = MCPConfig.GetOrCreate(); EditorApplication.update += CheckConnectionStatus; } private void OnDisable() { EditorApplication.update -= CheckConnectionStatus; } private void CheckConnectionStatus() { // Check every 2 seconds if ((DateTime.Now - lastStatusCheck).TotalSeconds < 2) return; lastStatusCheck = DateTime.Now; try { if (MCPWebSocketServer.IsRunning()) { connectionStatus = ConnectionStatus.Connected; lastError = ""; } else if (MCPWebSocketServer.IsStarting()) { connectionStatus = ConnectionStatus.Connecting; } else { connectionStatus = ConnectionStatus.Disconnected; } } catch (Exception e) { connectionStatus = ConnectionStatus.Error; lastError = e.Message; } Repaint(); } private void OnGUI() { scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); // Header DrawHeader(); EditorGUILayout.Space(10); // Connection Status DrawConnectionStatus(); EditorGUILayout.Space(10); // Server Controls DrawServerControls(); EditorGUILayout.Space(10); // Collapsible Sections DrawServerSettings(); DrawFeatures(); DrawToolsOverview(); DrawAdvancedSettings(); EditorGUILayout.Space(20); // Footer DrawFooter(); EditorGUILayout.EndScrollView(); } private void DrawHeader() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Label("Unity MCP Control Panel", EditorStyles.boldLabel); GUILayout.Label("AI-Powered Unity Editor Automation", EditorStyles.miniLabel); EditorGUILayout.EndVertical(); } private void DrawConnectionStatus() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); string statusEmoji = GetStatusEmoji(); string statusText = GetStatusText(); Color statusColor = GetStatusColor(); GUIStyle statusStyle = new GUIStyle(EditorStyles.label); statusStyle.fontSize = 14; statusStyle.normal.textColor = statusColor; GUILayout.Label($"{statusEmoji} Status: {statusText}", statusStyle); if (connectionStatus == ConnectionStatus.Connected) { GUILayout.Label($"Server running on ws://localhost:{config.websocketPort}", EditorStyles.miniLabel); } else if (connectionStatus == ConnectionStatus.Error) { EditorGUILayout.HelpBox($"Error: {lastError}", MessageType.Error); } EditorGUILayout.EndVertical(); } private void DrawServerControls() { EditorGUILayout.BeginHorizontal(); GUI.enabled = connectionStatus != ConnectionStatus.Connected; if (GUILayout.Button("▶ Start Server", GUILayout.Height(30))) { MCPWebSocketServer.StartServer(); connectionStatus = ConnectionStatus.Connecting; } GUI.enabled = connectionStatus == ConnectionStatus.Connected; if (GUILayout.Button("■ Stop Server", GUILayout.Height(30))) { MCPWebSocketServer.StopServer(); connectionStatus = ConnectionStatus.Disconnected; } GUI.enabled = true; if (GUILayout.Button("↻ Restart", GUILayout.Height(30))) { MCPWebSocketServer.StopServer(); System.Threading.Thread.Sleep(500); MCPWebSocketServer.StartServer(); } EditorGUILayout.EndHorizontal(); } private void DrawServerSettings() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); showServerSettings = EditorGUILayout.Foldout(showServerSettings, "⚙️ Server Settings", true); if (showServerSettings) { EditorGUI.BeginChangeCheck(); config.websocketPort = EditorGUILayout.IntSlider("Port", config.websocketPort, 1024, 65535); config.autoStart = EditorGUILayout.Toggle("Auto-start on Load", config.autoStart); config.requestTimeout = EditorGUILayout.IntSlider("Request Timeout (s)", config.requestTimeout, 1, 60); config.allowRemoteConnections = EditorGUILayout.Toggle("Allow Remote Connections", config.allowRemoteConnections); if (config.allowRemoteConnections) { EditorGUILayout.HelpBox("⚠️ Remote connections are not recommended for security reasons!", MessageType.Warning); } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(config); AssetDatabase.SaveAssets(); } } EditorGUILayout.EndVertical(); } private void DrawFeatures() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); showFeatures = EditorGUILayout.Foldout(showFeatures, "✨ Features", true); if (showFeatures) { EditorGUI.BeginChangeCheck(); config.enableConsoleMonitoring = EditorGUILayout.Toggle("Console Monitoring", config.enableConsoleMonitoring); if (config.enableConsoleMonitoring) { EditorGUI.indentLevel++; config.maxConsoleLogs = EditorGUILayout.IntSlider("Max Logs", config.maxConsoleLogs, 100, 5000); EditorGUI.indentLevel--; } config.autoRefreshAssets = EditorGUILayout.Toggle("Auto Refresh Assets", config.autoRefreshAssets); config.verboseLogging = EditorGUILayout.Toggle("Verbose Logging", config.verboseLogging); if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(config); AssetDatabase.SaveAssets(); } } EditorGUILayout.EndVertical(); } private void DrawToolsOverview() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); showTools = EditorGUILayout.Foldout(showTools, "🔧 Simplified Architecture (8 Essential Tools)", true); if (showTools) { EditorGUILayout.LabelField("⭐ The Killer Tool", EditorStyles.boldLabel); EditorGUILayout.LabelField("• execute_csharp - Execute ANY Unity operation with full API access", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.Space(3); EditorGUILayout.LabelField(" This single tool can replace dozens of specialized tools!", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.LabelField(" Examples: select, transform, create, delete, modify components, etc.", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.Space(5); EditorGUILayout.LabelField("Scene Operations", EditorStyles.boldLabel); EditorGUILayout.LabelField("• get_scene_hierarchy - Complete scene structure", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.LabelField("• load_scene - Load scenes by name or index", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.LabelField("• save_scene - Save current or all scenes", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.Space(5); EditorGUILayout.LabelField("Console & Logging", EditorStyles.boldLabel); EditorGUILayout.LabelField("• get_console_logs - Retrieve and filter Unity logs", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.Space(5); EditorGUILayout.LabelField("Play Mode Testing", EditorStyles.boldLabel); EditorGUILayout.LabelField("• enter_playmode - Start gameplay testing", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.LabelField("• exit_playmode - Return to Edit Mode", EditorStyles.wordWrappedMiniLabel); EditorGUILayout.LabelField("• get_playmode_status - Check play mode state", EditorStyles.wordWrappedMiniLabel); } EditorGUILayout.EndVertical(); } private void DrawAdvancedSettings() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); showAdvanced = EditorGUILayout.Foldout(showAdvanced, "⚡ Advanced Settings", true); if (showAdvanced) { EditorGUI.BeginChangeCheck(); config.enableUndo = EditorGUILayout.Toggle("Enable Undo/Redo", config.enableUndo); config.autoBackupScenes = EditorGUILayout.Toggle("Auto-backup Scenes", config.autoBackupScenes); if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(config); AssetDatabase.SaveAssets(); } EditorGUILayout.Space(5); if (GUILayout.Button("Reset to Defaults")) { if (EditorUtility.DisplayDialog("Reset Settings", "Are you sure you want to reset all settings to defaults?", "Reset", "Cancel")) { config.websocketPort = 8090; config.autoStart = true; config.requestTimeout = 30; config.allowRemoteConnections = false; config.verboseLogging = false; config.enableConsoleMonitoring = true; config.autoRefreshAssets = true; config.maxConsoleLogs = 1000; config.enableUndo = true; config.autoBackupScenes = false; EditorUtility.SetDirty(config); AssetDatabase.SaveAssets(); } } } EditorGUILayout.EndVertical(); } private void DrawFooter() { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Label("Unity MCP v2.3.0 - Simplified Architecture | Made with ❤️ for Game Devs", EditorStyles.centeredGreyMiniLabel); EditorGUILayout.EndVertical(); } private string GetStatusEmoji() { return connectionStatus switch { ConnectionStatus.Connected => "🟢", ConnectionStatus.Connecting => "🟠", ConnectionStatus.Disconnected => "⚪", ConnectionStatus.Error => "🔴", _ => "⚫" }; } private string GetStatusText() { return connectionStatus switch { ConnectionStatus.Connected => "Connected", ConnectionStatus.Connecting => "Starting...", ConnectionStatus.Disconnected => "Disconnected", ConnectionStatus.Error => "Error", _ => "Unknown" }; } private Color GetStatusColor() { return connectionStatus switch { ConnectionStatus.Connected => Color.green, ConnectionStatus.Connecting => new Color(1f, 0.6f, 0f), // Orange ConnectionStatus.Disconnected => Color.gray, ConnectionStatus.Error => Color.red, _ => Color.white }; } } }

Latest Blog Posts

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/muammar-yacoob/unity-mcp'

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