Skip to main content
Glama
Singtaa
by Singtaa
McpServerWindow.cs11.5 kB
using System; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace UnityMcp { /// <summary> /// Editor window for managing and monitoring the Unity MCP Server. /// </summary> public class McpServerWindow : EditorWindow { // UI elements Label _statusLabel; VisualElement _statusIndicator; Label _serverStatusLabel; Label _bridgeStatusLabel; Label _clientIdLabel; Label _uptimeLabel; Label _callsLabel; Button _startButton; Button _stopButton; Button _reconnectButton; Button _copyTokenButton; IntegerField _httpPortField; IntegerField _ipcPortField; Toggle _autoStartToggle; Toggle _autoConnectToggle; Toggle _authEnabledToggle; Foldout _toolsFoldout; Foldout _resourcesFoldout; [MenuItem("Window/Unity MCP Server")] public static void ShowWindow() { var window = GetWindow<McpServerWindow>(); window.titleContent = new GUIContent("MCP Server"); window.minSize = new Vector2(350, 500); } void CreateGUI() { var root = rootVisualElement; root.style.paddingLeft = 10; root.style.paddingRight = 10; root.style.paddingTop = 10; root.style.paddingBottom = 10; // Status header var statusHeader = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, marginBottom = 15 } }; _statusIndicator = new VisualElement { style = { width = 12, height = 12, borderTopLeftRadius = 6, borderTopRightRadius = 6, borderBottomLeftRadius = 6, borderBottomRightRadius = 6, marginRight = 8, backgroundColor = Color.gray } }; statusHeader.Add(_statusIndicator); _statusLabel = new Label("Checking...") { style = { fontSize = 14, unityFontStyleAndWeight = FontStyle.Bold } }; statusHeader.Add(_statusLabel); root.Add(statusHeader); // Server section root.Add(CreateSection("Node Server", out var serverContent)); serverContent.Add(CreateLabelRow("Status:", out _serverStatusLabel)); serverContent.Add(CreateLabelRow("Port:", out var portLabel)); portLabel.text = McpSettings.HttpPort.ToString(); var serverButtons = new VisualElement { style = { flexDirection = FlexDirection.Row, marginTop = 8 } }; _startButton = new Button(OnStartServer) { text = "Start", style = { flexGrow = 1 } }; _stopButton = new Button(OnStopServer) { text = "Stop", style = { flexGrow = 1 } }; _copyTokenButton = new Button(OnCopyToken) { text = "Copy Token", style = { flexGrow = 1 } }; serverButtons.Add(_startButton); serverButtons.Add(_stopButton); serverButtons.Add(_copyTokenButton); serverContent.Add(serverButtons); // Bridge section root.Add(CreateSection("Unity Bridge", out var bridgeContent)); bridgeContent.Add(CreateLabelRow("Status:", out _bridgeStatusLabel)); bridgeContent.Add(CreateLabelRow("Client ID:", out _clientIdLabel)); bridgeContent.Add(CreateLabelRow("Uptime:", out _uptimeLabel)); bridgeContent.Add(CreateLabelRow("Calls:", out _callsLabel)); var bridgeButtons = new VisualElement { style = { flexDirection = FlexDirection.Row, marginTop = 8 } }; _reconnectButton = new Button(OnReconnect) { text = "Reconnect", style = { flexGrow = 1 } }; bridgeButtons.Add(_reconnectButton); bridgeContent.Add(bridgeButtons); // Tools foldout _toolsFoldout = new Foldout { text = "Tools (loading...)", style = { marginTop = 10 } }; root.Add(_toolsFoldout); // Resources foldout _resourcesFoldout = new Foldout { text = "Resources (loading...)", style = { marginTop = 5 } }; root.Add(_resourcesFoldout); // Settings section root.Add(CreateSection("Settings", out var settingsContent)); _httpPortField = new IntegerField("HTTP Port") { value = McpSettings.HttpPort }; _httpPortField.RegisterValueChangedCallback(evt => McpSettings.HttpPort = evt.newValue); settingsContent.Add(_httpPortField); _ipcPortField = new IntegerField("IPC Port") { value = McpSettings.IpcPort }; _ipcPortField.RegisterValueChangedCallback(evt => McpSettings.IpcPort = evt.newValue); settingsContent.Add(_ipcPortField); _autoStartToggle = new Toggle("Auto-start server") { value = McpSettings.AutoStart }; _autoStartToggle.RegisterValueChangedCallback(evt => McpSettings.AutoStart = evt.newValue); settingsContent.Add(_autoStartToggle); _autoConnectToggle = new Toggle("Auto-connect bridge") { value = McpSettings.AutoConnect }; _autoConnectToggle.RegisterValueChangedCallback(evt => McpSettings.AutoConnect = evt.newValue); settingsContent.Add(_autoConnectToggle); _authEnabledToggle = new Toggle("Auth enabled") { value = McpSettings.AuthEnabled }; _authEnabledToggle.RegisterValueChangedCallback(evt => McpSettings.AuthEnabled = evt.newValue); settingsContent.Add(_authEnabledToggle); // Start periodic refresh EditorApplication.update += RefreshUI; // Initial refresh RefreshUI(); PopulateToolsList(); PopulateResourcesList(); } void OnDestroy() { EditorApplication.update -= RefreshUI; } VisualElement CreateSection(string title, out VisualElement content) { var section = new VisualElement { style = { marginTop = 10, marginBottom = 5, paddingLeft = 10, paddingRight = 10, paddingTop = 8, paddingBottom = 8, backgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.3f), borderTopLeftRadius = 4, borderTopRightRadius = 4, borderBottomLeftRadius = 4, borderBottomRightRadius = 4 } }; var header = new Label(title) { style = { fontSize = 12, unityFontStyleAndWeight = FontStyle.Bold, marginBottom = 8, color = new Color(0.8f, 0.8f, 0.8f) } }; section.Add(header); content = new VisualElement(); section.Add(content); return section; } VisualElement CreateLabelRow(string label, out Label valueLabel) { var row = new VisualElement { style = { flexDirection = FlexDirection.Row, marginBottom = 4 } }; var labelElement = new Label(label) { style = { width = 80, color = new Color(0.7f, 0.7f, 0.7f) } }; row.Add(labelElement); valueLabel = new Label("—") { style = { flexGrow = 1 } }; row.Add(valueLabel); return row; } void RefreshUI() { if (_statusLabel == null) return; var serverRunning = NodeProcessManager.IsRunning; var bridgeConnected = McpBridge.IsConnected; // Overall status if (serverRunning && bridgeConnected) { _statusLabel.text = "Connected"; _statusIndicator.style.backgroundColor = new Color(0.2f, 0.8f, 0.2f); } else if (serverRunning) { _statusLabel.text = "Server Running (Bridge Disconnected)"; _statusIndicator.style.backgroundColor = new Color(0.8f, 0.8f, 0.2f); } else { _statusLabel.text = "Server Stopped"; _statusIndicator.style.backgroundColor = new Color(0.8f, 0.2f, 0.2f); } // Server status _serverStatusLabel.text = serverRunning ? "Running" : (NodeProcessManager.IsStarting ? "Starting..." : "Stopped"); // Bridge status _bridgeStatusLabel.text = bridgeConnected ? "Connected" : "Disconnected"; _clientIdLabel.text = McpBridge.ClientId ?? "—"; // Uptime var uptime = McpBridge.Uptime; if (uptime.TotalSeconds > 0) { if (uptime.TotalHours >= 1) { _uptimeLabel.text = $"{(int)uptime.TotalHours}h {uptime.Minutes}m"; } else if (uptime.TotalMinutes >= 1) { _uptimeLabel.text = $"{(int)uptime.TotalMinutes}m {uptime.Seconds}s"; } else { _uptimeLabel.text = $"{(int)uptime.TotalSeconds}s"; } } else { _uptimeLabel.text = "—"; } _callsLabel.text = McpBridge.TotalCalls.ToString(); // Button states _startButton.SetEnabled(!serverRunning && !NodeProcessManager.IsStarting); _stopButton.SetEnabled(serverRunning); _reconnectButton.SetEnabled(serverRunning); } void PopulateToolsList() { _toolsFoldout.Clear(); var toolNames = ToolRegistry.GetToolNames(); var count = 0; foreach (var name in toolNames) { var label = new Label($" • {name}") { style = { fontSize = 11, color = new Color(0.7f, 0.7f, 0.7f) } }; _toolsFoldout.Add(label); count++; } _toolsFoldout.text = $"Tools ({count})"; } void PopulateResourcesList() { _resourcesFoldout.Clear(); var resourceNames = ResourceRegistry.GetResourceNames(); var count = 0; foreach (var name in resourceNames) { var label = new Label($" • {name}") { style = { fontSize = 11, color = new Color(0.7f, 0.7f, 0.7f) } }; _resourcesFoldout.Add(label); count++; } _resourcesFoldout.text = $"Resources ({count})"; } async void OnStartServer() { await NodeProcessManager.EnsureServerRunning(); } void OnStopServer() { NodeProcessManager.StopServer(); } void OnReconnect() { McpBridge.Reconnect(); } void OnCopyToken() { EditorGUIUtility.systemCopyBuffer = McpSettings.AuthToken; Debug.Log("[UnityMcp] Auth token copied to clipboard"); } } }

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/Singtaa/UnityMCP'

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