diff --git a/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs b/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs index 764c82f6d..0d2c23616 100644 --- a/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs +++ b/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs @@ -42,10 +42,13 @@ public System.Diagnostics.ProcessStartInfo CreateHeadlessProcessStartInfo(string } #if UNITY_EDITOR_WIN - // cmd.exe /c " >> "" 2>&1" + // cmd.exe /c " < NUL >> "" 2>&1" // The whole payload after /c is wrapped in one outer pair of quotes; cmd strips the // outermost quotes, so inner quotes around the log path survive for paths with spaces. - string winRedirect = $"{command} >> \"{logFilePath}\" 2>&1"; + // stdin is redirected from NUL because the Editor is a console-less GUI process: with + // CreateNoWindow and no console handle, uvx.exe would inherit an invalid stdin and die + // with "The handle is invalid. (os error 6)" before launching the server. + string winRedirect = $"{command} < NUL >> \"{logFilePath}\" 2>&1"; return new System.Diagnostics.ProcessStartInfo { FileName = "cmd.exe", diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs index 8426643d5..63f17071b 100644 --- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs +++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs @@ -212,6 +212,19 @@ public void CreateHeadlessProcessStartInfo_RedirectsOutputToLogFile() StringAssert.Contains(">>", startInfo.Arguments, "output should be appended to the log via >>"); } +#if UNITY_EDITOR_WIN + [Test] + public void CreateHeadlessProcessStartInfo_RedirectsStdinFromNul() + { + // Regression guard for #1279: the Editor is a console-less GUI process, so a child + // launched with CreateNoWindow inherits an invalid stdin and uvx.exe fails with + // "The handle is invalid. (os error 6)". stdin must come from NUL instead. + var startInfo = _launcher.CreateHeadlessProcessStartInfo("uvx run-server", LogPath()); + + StringAssert.Contains("< NUL", startInfo.Arguments, "stdin should be redirected from NUL"); + } +#endif + [Test] public void CreateHeadlessProcessStartInfo_LogPathWithSpaces_IsQuoted() {