diff --git a/MCPForUnity/Editor/Services/IServerManagementService.cs b/MCPForUnity/Editor/Services/IServerManagementService.cs
index f38014a88..299fad511 100644
--- a/MCPForUnity/Editor/Services/IServerManagementService.cs
+++ b/MCPForUnity/Editor/Services/IServerManagementService.cs
@@ -35,6 +35,12 @@ public interface IServerManagementService
///
bool IsLocalHttpServerRunning();
+ ///
+ /// Fast reachability check: returns true if a local TCP listener is accepting connections
+ /// for the configured local URL/port (used for UI state without process inspection).
+ ///
+ bool IsLocalHttpServerReachable();
+
///
/// Attempts to get the command that will be executed when starting the local HTTP server
///
diff --git a/MCPForUnity/Editor/Services/ServerManagementService.cs b/MCPForUnity/Editor/Services/ServerManagementService.cs
index b77bbd357..cd62258d3 100644
--- a/MCPForUnity/Editor/Services/ServerManagementService.cs
+++ b/MCPForUnity/Editor/Services/ServerManagementService.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
+using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using MCPForUnity.Editor.Constants;
@@ -600,6 +601,75 @@ public bool IsLocalHttpServerRunning()
}
}
+ public bool IsLocalHttpServerReachable()
+ {
+ try
+ {
+ string httpUrl = HttpEndpointUtility.GetBaseUrl();
+ if (!IsLocalUrl(httpUrl))
+ {
+ return false;
+ }
+
+ if (!Uri.TryCreate(httpUrl, UriKind.Absolute, out var uri) || uri.Port <= 0)
+ {
+ return false;
+ }
+
+ return TryConnectToLocalPort(uri.Host, uri.Port, timeoutMs: 50);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private static bool TryConnectToLocalPort(string host, int port, int timeoutMs)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(host))
+ {
+ host = "127.0.0.1";
+ }
+
+ var hosts = new HashSet(StringComparer.OrdinalIgnoreCase) { host };
+ if (host == "localhost" || host == "0.0.0.0")
+ {
+ hosts.Add("127.0.0.1");
+ }
+ if (host == "::" || host == "0:0:0:0:0:0:0:0")
+ {
+ hosts.Add("::1");
+ }
+
+ foreach (var target in hosts)
+ {
+ try
+ {
+ using (var client = new TcpClient())
+ {
+ var connectTask = client.ConnectAsync(target, port);
+ if (connectTask.Wait(timeoutMs) && client.Connected)
+ {
+ return true;
+ }
+ }
+ }
+ catch
+ {
+ // Ignore per-host failures.
+ }
+ }
+ }
+ catch
+ {
+ // Ignore probe failures and treat as unreachable.
+ }
+
+ return false;
+ }
+
private bool StopLocalHttpServerInternal(bool quiet, int? portOverride = null, bool allowNonLocalUrl = false)
{
string httpUrl = HttpEndpointUtility.GetBaseUrl();
diff --git a/MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs b/MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs
index 282280324..ab5c9036a 100644
--- a/MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs
+++ b/MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs
@@ -1,5 +1,4 @@
using System;
-using System.Net.Sockets;
using System.Threading.Tasks;
using MCPForUnity.Editor.Constants;
using MCPForUnity.Editor.Helpers;
@@ -482,14 +481,14 @@ private void UpdateStartHttpButtonState()
bool canStartLocalServer = httpLocalSelected && MCPServiceLocator.Server.IsLocalUrl();
bool localServerRunning = false;
- // Avoid running expensive port/PID checks every UI tick.
+ // Avoid running expensive port/PID checks every UI tick; use a fast socket probe for UI state.
if (httpLocalSelected)
{
double now = EditorApplication.timeSinceStartup;
if ((now - lastLocalServerRunningPollTime) > 0.75f || httpServerToggleInProgress)
{
lastLocalServerRunningPollTime = now;
- lastLocalServerRunning = MCPServiceLocator.Server.IsLocalHttpServerRunning();
+ lastLocalServerRunning = MCPServiceLocator.Server.IsLocalHttpServerReachable();
}
localServerRunning = lastLocalServerRunning;
}
@@ -531,7 +530,7 @@ private async void OnHttpServerToggleClicked()
try
{
// Check if a local server is running.
- bool serverRunning = IsHttpLocalSelected() && MCPServiceLocator.Server.IsLocalHttpServerRunning();
+ bool serverRunning = IsHttpLocalSelected() && MCPServiceLocator.Server.IsLocalHttpServerReachable();
if (serverRunning)
{
@@ -591,7 +590,7 @@ private async Task TryAutoStartSessionAsync()
var delay = attempt < 6 ? shortDelay : longDelay;
// Check if server is actually accepting connections
- bool serverDetected = MCPServiceLocator.Server.IsLocalHttpServerRunning();
+ bool serverDetected = MCPServiceLocator.Server.IsLocalHttpServerReachable();
if (serverDetected)
{