How to Debug Unity MCP Connection Issues: WebSocket and HTTP Troubleshooting Guide

Unity MCP connection failures most commonly originate from invalid HTTP endpoint configurations, bind-all address resolution errors, or WebSocket lifecycle mismatches that can be isolated by inspecting TransportState.Error and validating output from HttpEndpointUtility.GetBaseUrl().

When AI assistants cannot communicate with the Unity Editor through the Model Context Protocol, the root cause typically lies in the transport layer implementation within the CoplayDev/unity-mcp repository. Understanding how TransportManager coordinates WebSocketTransportClient and how HttpEndpointUtility resolves base URLs allows you to systematically diagnose registration failures, dropped keep-alive pings, and authentication errors.

Unity MCP Transport Architecture Overview

The Unity MCP SDK implements a pluggable transport layer with distinct components responsible for connection lifecycle management.

Key Architectural Components

Connection Initialization Flow

  1. Manager Startup: TransportManager.StartAsync(TransportMode.Http) instantiates WebSocketTransportClient through its internal factory.
  2. Endpoint Resolution: The client queries HttpEndpointUtility.GetBaseUrl() to determine the target server address.
  3. URI Construction: WebSocketTransportClient.BuildWebSocketUri(baseUrl) rewrites bind-only hosts (0.0.0.0 → 127.0.0.1, :: → ::1) and appends /hub/plugin to the path.
  4. Socket Establishment: EstablishConnectionAsync iterates candidate URIs, creates ClientWebSocket, and applies API key headers from EditorPrefs.GetString(EditorPrefKeys.ApiKey).
  5. Registration: Upon successful connection, the client transmits a register payload containing project_name and project_hash, then synchronizes enabled tools.
  6. Keep-Alive: A background task pings the server every 15 seconds (keepAliveInterval); failure triggers AttemptReconnectAsync using exponential backoff (0s to 30s) followed by steady 30-second intervals.

Diagnosing Common Unity MCP Connection Problems

Connection symptoms map directly to specific failure points in the architecture. Use targeted diagnostics for each error pattern.

"Connection failed. Check that the server URL is correct…"

This error indicates HttpEndpointUtility cannot resolve a valid base URL or the server is unreachable.

  • Verify the active URL via HttpEndpointUtility.GetBaseUrl() in the Unity Console.
  • Confirm Editor > Advanced Settings matches the server's listening address and port (default: 8080).
  • For remote connections, ensure the scheme is https unless Allow Insecure Remote HTTP is explicitly enabled.

Bind-All Address Warnings (0.0.0.0 Resolution)

When the log displays "Base URL host '0.0.0.0' is bind-only; using '127.0.0.1' for client connection", the MCP server was launched with a bind-all flag that clients cannot use directly.

  • Reconfigure the server launch arguments to --bind 127.0.0.1 instead of 0.0.0.0.
  • Alternatively, enable Allow LAN Bind for HTTP Local in the Unity MCP settings to permit non-loopback addresses.
  • Check McpLog.Warn entries to confirm the host rewrite occurred in BuildWebSocketUri.

WebSocket Disconnection During Send Operations

Errors stating "WebSocket is not open" or "SendJsonAsync – WebSocket is not initialised" occur when the socket closes before a command transmission, often following a failed keep-alive ping.

  • Inspect TransportManager.GetState(TransportMode.Http).Error via a custom Editor script to retrieve the specific disconnection reason.
  • Review logs prefixed with [WebSocket] Receive loop error to identify server-side terminations.
  • Verify the MCP server process remains active and has not crashed from unhandled exceptions.

API Key Authentication Failures in Remote Mode

Remote HTTP mode requires a valid API key header injected during EstablishConnectionAsync (lines 70-73 of WebSocketTransportClient.cs).

  • Validate that EditorPrefs.GetString(EditorPrefKeys.ApiKey) returns a non-empty string matching your server configuration.
  • Connection will silently fail or return authorization errors if this preference is unset or expired.

Command Execution Timeouts

Tools that exceed DefaultCommandTimeout (30 seconds) will trigger timeout exceptions.

  • Extend the deadline by passing a larger timeout value (in seconds) within the execute message payload.
  • Optimize tool implementations to complete within the default window, or implement progress reporting to prevent keep-alive starvation.

Debugging Code Examples for Unity MCP

Use these snippets to programmatically inspect connection health and force recovery.

Manually Starting the HTTP Transport

Call this from an Editor script or test fixture to validate the full startup sequence:

using MCPForUnity.Editor.Services;
using MCPForUnity.Editor.Services.Transport;
using System.Threading.Tasks;
using UnityEngine;

public static async Task<bool> ValidateMcpConnectionAsync()
{
    var manager = new TransportManager();
    bool isConnected = await manager.StartAsync(TransportMode.Http);
    
    if (!isConnected)
    {
        var state = manager.GetState(TransportMode.Http);
        Debug.LogError($"MCP HTTP start failed: {state.Error}");
    }
    
    return isConnected;
}

Forcing Reconnection After Network Outage

When the socket enters a stale state, force a clean restart:

public static async Task RecoverConnectionAsync()
{
    var manager = new TransportManager();
    
    // Terminates the existing client without graceful close
    manager.ForceStop(TransportMode.Http);
    
    // Re-runs the full connection and registration flow
    await manager.StartAsync(TransportMode.Http);
}

Inspecting Current Endpoint Configuration

Debug endpoint resolution and security scope:

using MCPForUnity.Editor.Helpers;
using UnityEngine;

public static void DiagnoseEndpoint()
{
    string baseUrl = HttpEndpointUtility.GetBaseUrl();
    bool isRemote = HttpEndpointUtility.IsRemoteScope();
    
    Debug.Log($"MCP endpoint ({(isRemote ? "remote" : "local")}): {baseUrl}");
    
    if (isRemote && baseUrl.StartsWith("http://"))
    {
        Debug.LogWarning("Insecure remote HTTP detected. Enable 'AllowInsecureRemoteHttp' or switch to HTTPS.");
    }
}

Adjusting Keep-Alive Intervals (Advanced)

Modify the ping frequency before calling StartAsync() using reflection:

var client = new WebSocketTransportClient();
var field = client.GetType().GetField(
    "_keepAliveInterval", 
    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
);

field?.SetValue(client, System.TimeSpan.FromSeconds(30));
await client.StartAsync();

Reading Transport State and Logs

All WebSocket activity logs use the [WebSocket] prefix, categorized by severity through McpLog. To surface runtime diagnostics:

  1. Query TransportManager.GetState(TransportMode.Http) to access TransportState.IsConnected and TransportState.Error.
  2. Enable verbose logging in the Unity Console to capture McpLog.Debug messages containing raw JSON payloads in ReceiveLoopAsync.
  3. Monitor BridgeControlService (MCPForUnity/Editor/Services/BridgeControlService.cs) for UI-level connection indicators in the Editor toolbar.

Summary

  • Validate endpoints first: Use HttpEndpointUtility.GetBaseUrl() to confirm the client targets the correct server address and scheme.
  • Handle bind-all addresses: Replace 0.0.0.0 with 127.0.0.1 in server configuration or enable LAN binding to prevent connection refusals.
  • Inspect TransportState: TransportManager.GetState(mode).Error provides the definitive reason for disconnection.
  • Check authentication: Remote mode requires EditorPrefKeys.ApiKey to be set before EstablishConnectionAsync executes.
  • Force recovery: Use ForceStop followed by StartAsync to clear stale sockets and trigger fresh registration when automatic reconnection stalls.

Frequently Asked Questions

Why does Unity MCP show "Connection failed. Check that the server URL is correct…"?

This error appears when HttpEndpointUtility resolves a base URL that is unreachable or malformed. Verify the URL in Editor > Advanced Settings matches your MCP server's listening address, ensure the port is correct (default 8080), and confirm remote URLs use HTTPS unless AllowInsecureRemoteHttp is enabled.

How do I fix the "Base URL host '0.0.0.0' is bind-only" warning?

The warning indicates your MCP server launched with --bind 0.0.0.0, which accepts connections on all interfaces but cannot be used as a client destination. Configure the server to bind specifically to 127.0.0.1 for local development, or enable Allow LAN Bind for HTTP Local in Unity MCP settings to permit the client to connect to non-loopback addresses.

What does "WebSocket is not open" mean and how do I resolve it?

This error occurs when WebSocketTransportClient attempts to send data while the underlying ClientWebSocket is closed or null, typically due to a failed keep-alive ping or server termination. Check TransportState.Error for the specific failure reason, verify the server process is running, and use ForceStop followed by StartAsync to reset the connection state if the automatic reconnection loop has stalled.

How can I check the current connection status programmatically?

Call TransportManager.GetState(TransportMode.Http) to retrieve a TransportState object containing IsConnected, SessionId, and Error properties. This immutable snapshot reflects the live status of the WebSocket transport and can be polled in Editor scripts or displayed in custom debugging windows to monitor MCP health in real-time.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →