diff --git a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
index d8aa8e3f5..498034767 100644
--- a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
+++ b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
@@ -71,5 +71,7 @@ internal static class EditorPrefKeys
internal const string LogRecordEnabled = "MCPForUnity.LogRecordEnabled";
internal const string ExecuteCodeCompiler = "MCPForUnity.ExecuteCode.Compiler";
+
+ internal const string MacOSTerminalApp = "MCPForUnity.MacOSTerminalApp";
}
}
diff --git a/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs b/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs
index 49ec84817..69f0dd21c 100644
--- a/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs
+++ b/MCPForUnity/Editor/Services/Server/TerminalLauncher.cs
@@ -1,6 +1,8 @@
using System;
using System.IO;
+using MCPForUnity.Editor.Constants;
using MCPForUnity.Editor.Helpers;
+using UnityEditor;
using UnityEngine;
namespace MCPForUnity.Editor.Services.Server
@@ -25,6 +27,21 @@ public string GetProjectRootPath()
}
}
+ ///
+ /// Resolves the macOS terminal application name, falling back to "Terminal"
+ /// when the configured value is unset, empty, or whitespace-only.
+ ///
+ internal static string ResolveMacTerminalApp(string configuredApp)
+ => string.IsNullOrWhiteSpace(configuredApp) ? "Terminal" : configuredApp.Trim();
+
+ ///
+ /// Builds the argument string for /usr/bin/open to launch the given
+ /// script in the configured macOS terminal application. The app name is quoted
+ /// so values containing spaces (e.g. "iTerm 2") resolve correctly.
+ ///
+ internal static string BuildMacOpenArguments(string configuredApp, string scriptPath)
+ => $"-a \"{ResolveMacTerminalApp(configuredApp)}\" \"{scriptPath}\"";
+
///
public System.Diagnostics.ProcessStartInfo CreateTerminalProcessStartInfo(string command)
{
@@ -45,10 +62,11 @@ public System.Diagnostics.ProcessStartInfo CreateTerminalProcessStartInfo(string
"clear\n" +
$"{command}\n");
ExecPath.TryRun("/bin/chmod", $"+x \"{scriptPath}\"", Application.dataPath, out _, out _, 3000);
+ string configuredApp = EditorPrefs.GetString(EditorPrefKeys.MacOSTerminalApp, "Terminal");
return new System.Diagnostics.ProcessStartInfo
{
FileName = "/usr/bin/open",
- Arguments = $"-a Terminal \"{scriptPath}\"",
+ Arguments = BuildMacOpenArguments(configuredApp, scriptPath),
UseShellExecute = false,
CreateNoWindow = true
};
diff --git a/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs
index b683a21a5..f11d80409 100644
--- a/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs
+++ b/MCPForUnity/Editor/Windows/EditorPrefs/EditorPrefsWindow.cs
@@ -77,6 +77,7 @@ public class EditorPrefsWindow : EditorWindow
{ EditorPrefKeys.LastLocalHttpServerPidArgsHash, EditorPrefType.String },
{ EditorPrefKeys.LastLocalHttpServerPidFilePath, EditorPrefType.String },
{ EditorPrefKeys.LastLocalHttpServerInstanceToken, EditorPrefType.String },
+ { EditorPrefKeys.MacOSTerminalApp, EditorPrefType.String },
};
// Templates
diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs
index 4d1b629bc..c2affe15e 100644
--- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs
+++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs
@@ -181,6 +181,65 @@ public void TerminalLauncher_CanBeUsedViaInterface()
#endregion
+ #region macOS Terminal App Resolution Tests
+
+ [Test]
+ public void ResolveMacTerminalApp_NullOrEmpty_FallsBackToTerminal()
+ {
+ Assert.AreEqual("Terminal", TerminalLauncher.ResolveMacTerminalApp(null));
+ Assert.AreEqual("Terminal", TerminalLauncher.ResolveMacTerminalApp(string.Empty));
+ }
+
+ [Test]
+ public void ResolveMacTerminalApp_WhitespaceOnly_FallsBackToTerminal()
+ {
+ Assert.AreEqual("Terminal", TerminalLauncher.ResolveMacTerminalApp(" "));
+ Assert.AreEqual("Terminal", TerminalLauncher.ResolveMacTerminalApp("\t\n"));
+ }
+
+ [Test]
+ public void ResolveMacTerminalApp_CustomValue_IsUsed()
+ {
+ Assert.AreEqual("iTerm", TerminalLauncher.ResolveMacTerminalApp("iTerm"));
+ Assert.AreEqual("Warp", TerminalLauncher.ResolveMacTerminalApp("Warp"));
+ }
+
+ [Test]
+ public void ResolveMacTerminalApp_TrimsSurroundingWhitespace()
+ {
+ Assert.AreEqual("iTerm", TerminalLauncher.ResolveMacTerminalApp(" iTerm "));
+ }
+
+ [Test]
+ public void BuildMacOpenArguments_DefaultsToTerminal_WhenUnset()
+ {
+ string args = TerminalLauncher.BuildMacOpenArguments("", "/tmp/mcp-terminal.command");
+ Assert.AreEqual("-a \"Terminal\" \"/tmp/mcp-terminal.command\"", args);
+ }
+
+ [Test]
+ public void BuildMacOpenArguments_QuotesCustomApp()
+ {
+ string args = TerminalLauncher.BuildMacOpenArguments("iTerm", "/tmp/mcp-terminal.command");
+ Assert.AreEqual("-a \"iTerm\" \"/tmp/mcp-terminal.command\"", args);
+ }
+
+ [Test]
+ public void BuildMacOpenArguments_QuotingHandlesAppNameWithSpaces()
+ {
+ string args = TerminalLauncher.BuildMacOpenArguments("iTerm 2", "/tmp/mcp-terminal.command");
+ Assert.AreEqual("-a \"iTerm 2\" \"/tmp/mcp-terminal.command\"", args);
+ }
+
+ [Test]
+ public void BuildMacOpenArguments_QuotingHandlesScriptPathWithSpaces()
+ {
+ string args = TerminalLauncher.BuildMacOpenArguments("Terminal", "/Users/me/My Project/mcp-terminal.command");
+ Assert.AreEqual("-a \"Terminal\" \"/Users/me/My Project/mcp-terminal.command\"", args);
+ }
+
+ #endregion
+
#region Platform-Specific Behavior Tests
[Test]