fix: Windows Claude Desktop stdio + Codex beta/timeout config (#650)

* fix: Remove cmd.exe wrapper for Claude Desktop on Windows

The cmd.exe /c wrapper was causing stdio pipe issues on Windows,
resulting in "Server disconnected" errors in Claude Desktop. Testing
confirmed that calling uvx.exe directly works reliably.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Codex config uses centralized beta args and adds startup timeout

- Use GetBetaServerFromArgsList() for consistent --prerelease handling
- Add startup_timeout_sec = 60 to allow time for uvx package downloads

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
main
dsarno 2026-01-29 15:33:27 -08:00 committed by GitHub
parent 62c015d873
commit 13aca5fb1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 46 deletions

View File

@ -48,16 +48,16 @@ namespace MCPForUnity.Editor.Helpers
else
{
// Stdio mode: Use command and args
var (uvxPath, fromUrl, packageName) = AssetPathUtility.GetUvxCommandParts();
var (uvxPath, _, packageName) = AssetPathUtility.GetUvxCommandParts();
unityMCP["command"] = uvxPath;
var args = new TomlArray();
AddDevModeArgs(args);
if (!string.IsNullOrEmpty(fromUrl))
// Use centralized helper for beta server / prerelease args
foreach (var arg in AssetPathUtility.GetBetaServerFromArgsList())
{
args.Add(new TomlString { Value = "--from" });
args.Add(new TomlString { Value = fromUrl });
args.Add(new TomlString { Value = arg });
}
args.Add(new TomlString { Value = packageName });
args.Add(new TomlString { Value = "--transport" });
@ -73,6 +73,9 @@ namespace MCPForUnity.Editor.Helpers
envTable["SystemRoot"] = new TomlString { Value = platformService.GetSystemRoot() };
unityMCP["env"] = envTable;
}
// Allow extra time for uvx to download packages on first run
unityMCP["startup_timeout_sec"] = new TomlInteger { Value = 60 };
}
mcpServers["unityMCP"] = unityMCP;
@ -197,16 +200,16 @@ namespace MCPForUnity.Editor.Helpers
else
{
// Stdio mode: Use command and args
var (uvxPath, fromUrl, packageName) = AssetPathUtility.GetUvxCommandParts();
var (uvxPath, _, packageName) = AssetPathUtility.GetUvxCommandParts();
unityMCP["command"] = new TomlString { Value = uvxPath };
var argsArray = new TomlArray();
AddDevModeArgs(argsArray);
if (!string.IsNullOrEmpty(fromUrl))
// Use centralized helper for beta server / prerelease args
foreach (var arg in AssetPathUtility.GetBetaServerFromArgsList())
{
argsArray.Add(new TomlString { Value = "--from" });
argsArray.Add(new TomlString { Value = fromUrl });
argsArray.Add(new TomlString { Value = arg });
}
argsArray.Add(new TomlString { Value = packageName });
argsArray.Add(new TomlString { Value = "--transport" });
@ -221,6 +224,9 @@ namespace MCPForUnity.Editor.Helpers
envTable["SystemRoot"] = new TomlString { Value = platformService.GetSystemRoot() };
unityMCP["env"] = envTable;
}
// Allow extra time for uvx to download packages on first run
unityMCP["startup_timeout_sec"] = new TomlInteger { Value = 60 };
}
return unityMCP;

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MCPForUnity.Editor.Clients.Configurators;
using MCPForUnity.Editor.Constants;
using MCPForUnity.Editor.Services;
using MCPForUnity.Editor.Models;
@ -90,20 +88,8 @@ namespace MCPForUnity.Editor.Helpers
var toolArgs = BuildUvxArgs(fromUrl, packageName);
if (ShouldUseWindowsCmdShim(client))
{
unity["command"] = ResolveCmdPath();
var cmdArgs = new List<string> { "/c", uvxPath };
cmdArgs.AddRange(toolArgs);
unity["args"] = JArray.FromObject(cmdArgs.ToArray());
}
else
{
unity["command"] = uvxPath;
unity["args"] = JArray.FromObject(toolArgs.ToArray());
}
// Remove url/serverUrl if they exist from previous config
if (unity["url"] != null) unity.Remove("url");
@ -184,27 +170,5 @@ namespace MCPForUnity.Editor.Helpers
return args;
}
private static bool ShouldUseWindowsCmdShim(McpClient client)
{
if (client == null)
{
return false;
}
return Application.platform == RuntimePlatform.WindowsEditor &&
string.Equals(client.name, ClaudeDesktopConfigurator.ClientName, StringComparison.OrdinalIgnoreCase);
}
private static string ResolveCmdPath()
{
var comSpec = Environment.GetEnvironmentVariable("ComSpec");
if (!string.IsNullOrEmpty(comSpec) && File.Exists(comSpec))
{
return comSpec;
}
string system32Cmd = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
return File.Exists(system32Cmd) ? system32Cmd : "cmd.exe";
}
}
}