Skip to main content
Glama
BridgeControlService.cs5.06 kB
using System; using System.Threading.Tasks; using MCPForUnity.Editor.Constants; using MCPForUnity.Editor.Helpers; using MCPForUnity.Editor.Services.Transport; using MCPForUnity.Editor.Services.Transport.Transports; using UnityEditor; namespace MCPForUnity.Editor.Services { /// <summary> /// Bridges the editor UI to the active transport (HTTP with WebSocket push, or stdio). /// </summary> public class BridgeControlService : IBridgeControlService { private readonly TransportManager _transportManager; private TransportMode _preferredMode = TransportMode.Http; public BridgeControlService() { _transportManager = MCPServiceLocator.TransportManager; } private TransportMode ResolvePreferredMode() { bool useHttp = EditorPrefs.GetBool(EditorPrefKeys.UseHttpTransport, true); _preferredMode = useHttp ? TransportMode.Http : TransportMode.Stdio; return _preferredMode; } private static BridgeVerificationResult BuildVerificationResult(TransportState state, TransportMode mode, bool pingSucceeded, string messageOverride = null, bool? handshakeOverride = null) { bool handshakeValid = handshakeOverride ?? (mode == TransportMode.Stdio ? state.IsConnected : true); string transportLabel = string.IsNullOrWhiteSpace(state.TransportName) ? mode.ToString().ToLowerInvariant() : state.TransportName; string detailSuffix = string.IsNullOrWhiteSpace(state.Details) ? string.Empty : $" [{state.Details}]"; string message = messageOverride ?? state.Error ?? (state.IsConnected ? $"Transport '{transportLabel}' connected{detailSuffix}" : $"Transport '{transportLabel}' disconnected{detailSuffix}"); return new BridgeVerificationResult { Success = pingSucceeded && handshakeValid, HandshakeValid = handshakeValid, PingSucceeded = pingSucceeded, Message = message }; } public bool IsRunning { get { var mode = ResolvePreferredMode(); return _transportManager.IsRunning(mode); } } public int CurrentPort { get { var mode = ResolvePreferredMode(); var state = _transportManager.GetState(mode); if (state.Port.HasValue) { return state.Port.Value; } // Legacy fallback while the stdio bridge is still in play return StdioBridgeHost.GetCurrentPort(); } } public bool IsAutoConnectMode => StdioBridgeHost.IsAutoConnectMode(); public TransportMode? ActiveMode => ResolvePreferredMode(); public async Task<bool> StartAsync() { var mode = ResolvePreferredMode(); try { bool started = await _transportManager.StartAsync(mode); if (!started) { McpLog.Warn($"Failed to start MCP transport: {mode}"); } return started; } catch (Exception ex) { McpLog.Error($"Error starting MCP transport {mode}: {ex.Message}"); return false; } } public async Task StopAsync() { try { var mode = ResolvePreferredMode(); await _transportManager.StopAsync(mode); } catch (Exception ex) { McpLog.Warn($"Error stopping MCP transport: {ex.Message}"); } } public async Task<BridgeVerificationResult> VerifyAsync() { var mode = ResolvePreferredMode(); bool pingSucceeded = await _transportManager.VerifyAsync(mode); var state = _transportManager.GetState(mode); return BuildVerificationResult(state, mode, pingSucceeded); } public BridgeVerificationResult Verify(int port) { var mode = ResolvePreferredMode(); bool pingSucceeded = _transportManager.VerifyAsync(mode).GetAwaiter().GetResult(); var state = _transportManager.GetState(mode); if (mode == TransportMode.Stdio) { bool handshakeValid = state.IsConnected && port == CurrentPort; string message = handshakeValid ? $"STDIO transport listening on port {CurrentPort}" : $"STDIO transport port mismatch (expected {CurrentPort}, got {port})"; return BuildVerificationResult(state, mode, pingSucceeded && handshakeValid, message, handshakeValid); } return BuildVerificationResult(state, mode, pingSucceeded); } } }

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

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