Merge pull request #210 from dsarno/fix/config-stability

Config stability: preserve user configs, prefer installed server, safer uv resolution, XDG paths (Linux)
main
dsarno 2025-08-13 19:21:02 -07:00 committed by GitHub
commit cf8f5d4dd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 414 additions and 159 deletions

85
CursorHelp.md Normal file
View File

@ -0,0 +1,85 @@
### Cursor/VSCode/Windsurf: UV path issue on Windows (diagnosis and fix)
#### The issue
- Some Windows machines have multiple `uv.exe` locations. Our auto-config sometimes picked a less stable path, causing the MCP client to fail to launch the Unity MCP Server or for the path to be auto-rewritten on repaint/restart.
#### Typical symptoms
- Cursor shows the UnityMCP server but never connects or reports it “cant start.”
- Your `%USERPROFILE%\\.cursor\\mcp.json` flips back to a different `command` path when Unity or the Unity MCP window refreshes.
#### Real-world example
- Wrong/fragile path (auto-picked):
- `C:\Users\mrken.local\bin\uv.exe` (malformed, not standard)
- `C:\Users\mrken\AppData\Local\Microsoft\WinGet\Packages\astral-sh.uv_Microsoft.Winget.Source_8wekyb3d8bbwe\uv.exe`
- Correct/stable path (works with Cursor):
- `C:\Users\mrken\AppData\Local\Microsoft\WinGet\Links\uv.exe`
#### Quick fix (recommended)
1) In Unity: `Window > Unity MCP` → select your MCP client (Cursor or Windsurf)
2) If you see “uv Not Found,” click “Choose UV Install Location” and browse to:
- `C:\Users\<YOU>\AppData\Local\Microsoft\WinGet\Links\uv.exe`
3) If uv is already found but wrong, still click “Choose UV Install Location” and select the `Links\uv.exe` path above. This saves a persistent override.
4) Click “Auto Configure” (or re-open the client) and restart Cursor.
This sets an override stored in the Editor (key: `UnityMCP.UvPath`) so UnityMCP wont auto-rewrite the config back to a different `uv.exe` later.
#### Verify the fix
- Confirm global Cursor config is at: `%USERPROFILE%\\.cursor\\mcp.json`
- You should see something like:
```json
{
"mcpServers": {
"unityMCP": {
"command": "C:\\Users\\YOU\\AppData\\Local\\Microsoft\\WinGet\\Links\\uv.exe",
"args": [
"--directory",
"C:\\Users\\YOU\\AppData\\Local\\Programs\\UnityMCP\\UnityMcpServer\\src",
"run",
"server.py"
]
}
}
}
```
- Manually run the same command in PowerShell to confirm it launches:
```powershell
"C:\Users\YOU\AppData\Local\Microsoft\WinGet\Links\uv.exe" --directory "C:\Users\YOU\AppData\Local\Programs\UnityMCP\UnityMcpServer\src" run server.py
```
If that runs without error, restart Cursor and it should connect.
#### Why this happens
- On Windows, multiple `uv.exe` can exist (WinGet Packages path, a WinGet Links shim, Python Scripts, etc.). The Links shim is the most stable target for GUI apps to launch.
- Prior versions of the auto-config could pick the first found path and re-write config on refresh. Choosing a path via the MCP window pins a knowngood absolute path and prevents auto-rewrites.
#### Extra notes
- Restart Cursor after changing `mcp.json`; it doesnt always hot-reload that file.
- If you also have a project-scoped `.cursor\\mcp.json` in your Unity project folder, that file overrides the global one.
### Why pin the WinGet Links shim (and not the Packages path)
- Windows often has multiple `uv.exe` installs and GUI clients (Cursor/Windsurf/VSCode) may launch with a reduced `PATH`. Using an absolute path is safer than `"command": "uv"`.
- WinGet publishes stable launch shims in these locations:
- User scope: `%LOCALAPPDATA%\Microsoft\WinGet\Links\uv.exe`
- Machine scope: `C:\Program Files\WinGet\Links\uv.exe`
These shims survive upgrades and are intended as the portable entrypoints. See the WinGet notes: [discussion](https://github.com/microsoft/winget-pkgs/discussions/184459) • [how to find installs](https://superuser.com/questions/1739292/how-to-know-where-winget-installed-a-program)
- The `Packages` root is where payloads live and can change across updates, so avoid pointing your config at it.
Recommended practice
- Prefer the WinGet Links shim paths above. If present, select one via “Choose UV Install Location”.
- If the unity window keeps rewriting to a different `uv.exe`, pick the Links shim again; Unity MCP saves a pinned override and will stop auto-rewrites.
- If neither Links path exists, a reasonable fallback is `~/.local/bin/uv.exe` (uv tools bin) or a Scoop shim, but Links is preferred for stability.
References
- WinGet portable Links: [GitHub discussion](https://github.com/microsoft/winget-pkgs/discussions/184459)
- WinGet install locations: [Super User](https://superuser.com/questions/1739292/how-to-know-where-winget-installed-a-program)
- GUI client PATH caveats (Cursor): [Cursor community thread](https://forum.cursor.com/t/mcp-feature-client-closed-fix/54651?page=4)
- uv tools install location (`~/.local/bin`): [Astral docs](https://docs.astral.sh/uv/concepts/tools/)

View File

@ -71,8 +71,7 @@ namespace UnityMcpBridge.Editor.Data
), ),
linuxConfigPath = Path.Combine( linuxConfigPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Library", ".config",
"Application Support",
"Claude", "Claude",
"claude_desktop_config.json" "claude_desktop_config.json"
), ),
@ -91,8 +90,7 @@ namespace UnityMcpBridge.Editor.Data
), ),
linuxConfigPath = Path.Combine( linuxConfigPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Library", ".config",
"Application Support",
"Code", "Code",
"User", "User",
"mcp.json" "mcp.json"

View File

@ -88,7 +88,7 @@ namespace UnityMcpBridge.Editor.Helpers
// Use Application Support for a stable, user-writable location // Use Application Support for a stable, user-writable location
return Path.Combine( return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"UnityMCP" RootFolder
); );
} }
throw new Exception("Unsupported operating system."); throw new Exception("Unsupported operating system.");
@ -126,6 +126,7 @@ namespace UnityMcpBridge.Editor.Helpers
return ServerPathResolver.TryFindEmbeddedServerSource(out srcPath); return ServerPathResolver.TryFindEmbeddedServerSource(out srcPath);
} }
private static readonly string[] _skipDirs = { ".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".git" };
private static void CopyDirectoryRecursive(string sourceDir, string destinationDir) private static void CopyDirectoryRecursive(string sourceDir, string destinationDir)
{ {
Directory.CreateDirectory(destinationDir); Directory.CreateDirectory(destinationDir);
@ -140,8 +141,15 @@ namespace UnityMcpBridge.Editor.Helpers
foreach (string dirPath in Directory.GetDirectories(sourceDir)) foreach (string dirPath in Directory.GetDirectories(sourceDir))
{ {
string dirName = Path.GetFileName(dirPath); string dirName = Path.GetFileName(dirPath);
foreach (var skip in _skipDirs)
{
if (dirName.Equals(skip, StringComparison.OrdinalIgnoreCase))
goto NextDir;
}
try { if ((File.GetAttributes(dirPath) & FileAttributes.ReparsePoint) != 0) continue; } catch { }
string destSubDir = Path.Combine(destinationDir, dirName); string destSubDir = Path.Combine(destinationDir, dirName);
CopyDirectoryRecursive(dirPath, destSubDir); CopyDirectoryRecursive(dirPath, destSubDir);
NextDir: ;
} }
} }
@ -270,7 +278,6 @@ namespace UnityMcpBridge.Editor.Helpers
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty; string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty; string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty; string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;
string programData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) ?? string.Empty; // optional fallback
// Fast path: resolve from PATH first // Fast path: resolve from PATH first
try try
@ -301,10 +308,9 @@ namespace UnityMcpBridge.Editor.Helpers
candidates = new[] candidates = new[]
{ {
// Preferred: WinGet Links shims (stable entrypoints) // Preferred: WinGet Links shims (stable entrypoints)
// Per-user shim (LOCALAPPDATA) → machine-wide shim (Program Files\WinGet\Links)
Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"), Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
Path.Combine(programFiles, "WinGet", "Links", "uv.exe"), Path.Combine(programFiles, "WinGet", "Links", "uv.exe"),
// Optional low-priority fallback for atypical images
Path.Combine(programData, "Microsoft", "WinGet", "Links", "uv.exe"),
// Common per-user installs // Common per-user installs
Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"), Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),

View File

@ -630,15 +630,29 @@ namespace UnityMcpBridge.Editor.Windows
if (unity == null) return false; if (unity == null) return false;
var args = unity.args; var args = unity.args;
if (args == null) return false; if (args == null) return false;
foreach (var a in args) // Prefer exact extraction of the --directory value and compare normalized paths
string[] strArgs = ((System.Collections.Generic.IEnumerable<object>)args)
.Select(x => x?.ToString() ?? string.Empty)
.ToArray();
string dir = ExtractDirectoryArg(strArgs);
if (string.IsNullOrEmpty(dir)) return false;
return PathsEqual(dir, pythonDir);
}
catch { return false; }
}
private static bool PathsEqual(string a, string b)
{
if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) return false;
try
{
string na = System.IO.Path.GetFullPath(a.Trim());
string nb = System.IO.Path.GetFullPath(b.Trim());
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{ {
string s = (string)a; return string.Equals(na, nb, StringComparison.OrdinalIgnoreCase);
if (!string.IsNullOrEmpty(s) && s.Contains(pythonDir, StringComparison.Ordinal))
{
return true;
}
} }
return false; return string.Equals(na, nb, StringComparison.Ordinal);
} }
catch { return false; } catch { return false; }
} }
@ -883,7 +897,7 @@ namespace UnityMcpBridge.Editor.Windows
unityMCP = new unityMCP = new
{ {
command = uvPath, command = uvPath,
args = new[] { "--directory", pythonDir, "run", "server.py" } args = new[] { "run", "--directory", pythonDir, "server.py" }
} }
} }
} }
@ -931,24 +945,65 @@ namespace UnityMcpBridge.Editor.Windows
Repaint(); Repaint();
} }
private string WriteToConfig(string pythonDir, string configPath, McpClient mcpClient = null) private static bool IsValidUv(string path)
{ {
string uvPath = FindUvPath(); return !string.IsNullOrEmpty(path)
if (uvPath == null) && System.IO.Path.IsPathRooted(path)
{ && System.IO.File.Exists(path);
return "UV package manager not found. Please install UV first."; }
}
// Create configuration object for unityMCP private static bool ValidateUvBinarySafe(string path)
McpConfigServer unityMCPConfig = new() {
{ try
command = uvPath, {
args = new[] { "--directory", pythonDir, "run", "server.py" }, if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path)) return false;
}; var psi = new System.Diagnostics.ProcessStartInfo
if (mcpClient?.mcpType == McpTypes.VSCode) {
{ FileName = path,
unityMCPConfig.type = "stdio"; Arguments = "--version",
} UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var p = System.Diagnostics.Process.Start(psi);
if (p == null) return false;
if (!p.WaitForExit(3000)) { try { p.Kill(); } catch { } return false; }
if (p.ExitCode != 0) return false;
string output = p.StandardOutput.ReadToEnd().Trim();
return output.StartsWith("uv ");
}
catch { return false; }
}
private static string ExtractDirectoryArg(string[] args)
{
if (args == null) return null;
for (int i = 0; i < args.Length - 1; i++)
{
if (string.Equals(args[i], "--directory", StringComparison.OrdinalIgnoreCase))
{
return args[i + 1];
}
}
return null;
}
private static bool ArgsEqual(string[] a, string[] b)
{
if (a == null || b == null) return a == b;
if (a.Length != b.Length) return false;
for (int i = 0; i < a.Length; i++)
{
if (!string.Equals(a[i], b[i], StringComparison.Ordinal)) return false;
}
return true;
}
private string WriteToConfig(string pythonDir, string configPath, McpClient mcpClient = null)
{
// 0) Respect explicit lock (hidden pref or UI toggle)
try { if (UnityEditor.EditorPrefs.GetBool("UnityMCP.LockCursorConfig", false)) return "Skipped (locked)"; } catch { }
JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented }; JsonSerializerSettings jsonSettings = new() { Formatting = Formatting.Indented };
@ -989,123 +1044,88 @@ namespace UnityMcpBridge.Editor.Windows
existingConfig = new Newtonsoft.Json.Linq.JObject(); existingConfig = new Newtonsoft.Json.Linq.JObject();
} }
// Handle different client types with a switch statement // Determine existing entry references (command/args)
//Comments: Interestingly, VSCode has mcp.servers.unityMCP while others have mcpServers.unityMCP, which is why we need to prevent this string existingCommand = null;
switch (mcpClient?.mcpType) string[] existingArgs = null;
{ bool isVSCode = (mcpClient?.mcpType == McpTypes.VSCode);
case McpTypes.VSCode: try
// VSCode-specific configuration (top-level "servers") {
if (existingConfig.servers == null) if (isVSCode)
{ {
existingConfig.servers = new Newtonsoft.Json.Linq.JObject(); existingCommand = existingConfig?.servers?.unityMCP?.command?.ToString();
} existingArgs = existingConfig?.servers?.unityMCP?.args?.ToObject<string[]>();
}
else
{
existingCommand = existingConfig?.mcpServers?.unityMCP?.command?.ToString();
existingArgs = existingConfig?.mcpServers?.unityMCP?.args?.ToObject<string[]>();
}
}
catch { }
// Add/update UnityMCP server in VSCode mcp.json // 1) Start from existing, only fill gaps
existingConfig.servers.unityMCP = string uvPath = (ValidateUvBinarySafe(existingCommand) ? existingCommand : FindUvPath());
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>( if (uvPath == null) return "UV package manager not found. Please install UV first.";
JsonConvert.SerializeObject(unityMCPConfig)
);
break;
default: string serverSrc = ExtractDirectoryArg(existingArgs);
// Standard MCP configuration (Claude Desktop, Cursor, etc.) bool serverValid = !string.IsNullOrEmpty(serverSrc)
// Ensure mcpServers object exists && System.IO.File.Exists(System.IO.Path.Combine(serverSrc, "server.py"));
if (existingConfig.mcpServers == null) if (!serverValid)
{ {
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject(); serverSrc = ResolveServerSrc();
} }
// Add/update UnityMCP server in standard MCP settings // Hard-block PackageCache on Windows unless dev override is set
existingConfig.mcpServers.unityMCP = if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>( && serverSrc.IndexOf(@"\Library\PackageCache\", StringComparison.OrdinalIgnoreCase) >= 0
JsonConvert.SerializeObject(unityMCPConfig) && !UnityEditor.EditorPrefs.GetBool("UnityMCP.UseEmbeddedServer", false))
); {
break; serverSrc = ServerInstaller.GetServerPath();
} }
// If config already has a working absolute uv path, avoid rewriting it on refresh // 2) Canonical args order
try var newArgs = new[] { "run", "--directory", serverSrc, "server.py" };
{
if (mcpClient?.mcpType != McpTypes.ClaudeCode)
{
// Inspect existing command for stability (Windows absolute path that exists)
string existingCommand = null;
if (mcpClient?.mcpType == McpTypes.VSCode)
{
existingCommand = existingConfig?.servers?.unityMCP?.command?.ToString();
}
else
{
existingCommand = existingConfig?.mcpServers?.unityMCP?.command?.ToString();
}
if (!string.IsNullOrEmpty(existingCommand)) // 3) Only write if changed
{ bool changed = !string.Equals(existingCommand, uvPath, StringComparison.Ordinal)
bool keep = false; || !ArgsEqual(existingArgs, newArgs);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (!changed)
{ {
// Consider absolute, existing paths as stable; prefer WinGet Links return "Configured successfully"; // nothing to do
if (Path.IsPathRooted(existingCommand) && File.Exists(existingCommand)) }
{
keep = true;
}
}
else
{
// On Unix, keep absolute existing path as well
if (Path.IsPathRooted(existingCommand) && File.Exists(existingCommand))
{
keep = true;
}
}
if (keep) // 4) Ensure containers exist and write back minimal changes
{ if (isVSCode)
// Merge without replacing the existing command {
if (mcpClient?.mcpType == McpTypes.VSCode) if (existingConfig.servers == null) existingConfig.servers = new Newtonsoft.Json.Linq.JObject();
{ if (existingConfig.servers.unityMCP == null) existingConfig.servers.unityMCP = new Newtonsoft.Json.Linq.JObject();
if (existingConfig.servers == null) existingConfig.servers.unityMCP.command = uvPath;
{ existingConfig.servers.unityMCP.args = Newtonsoft.Json.Linq.JArray.FromObject(newArgs);
existingConfig.servers = new Newtonsoft.Json.Linq.JObject(); existingConfig.servers.unityMCP.type = "stdio";
} }
if (existingConfig.servers.unityMCP == null) else
{ {
existingConfig.servers.unityMCP = new Newtonsoft.Json.Linq.JObject(); if (existingConfig.mcpServers == null) existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
} if (existingConfig.mcpServers.unityMCP == null) existingConfig.mcpServers.unityMCP = new Newtonsoft.Json.Linq.JObject();
existingConfig.servers.unityMCP.args = existingConfig.mcpServers.unityMCP.command = uvPath;
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>( existingConfig.mcpServers.unityMCP.args = Newtonsoft.Json.Linq.JArray.FromObject(newArgs);
JsonConvert.SerializeObject(unityMCPConfig.args) }
);
}
else
{
if (existingConfig.mcpServers == null)
{
existingConfig.mcpServers = new Newtonsoft.Json.Linq.JObject();
}
if (existingConfig.mcpServers.unityMCP == null)
{
existingConfig.mcpServers.unityMCP = new Newtonsoft.Json.Linq.JObject();
}
existingConfig.mcpServers.unityMCP.args =
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JToken>(
JsonConvert.SerializeObject(unityMCPConfig.args)
);
}
string mergedKeep = JsonConvert.SerializeObject(existingConfig, jsonSettings);
File.WriteAllText(configPath, mergedKeep);
return "Configured successfully";
}
}
}
}
catch { /* fall back to normal write */ }
// Write the merged configuration back to file string mergedJson = JsonConvert.SerializeObject(existingConfig, jsonSettings);
string mergedJson = JsonConvert.SerializeObject(existingConfig, jsonSettings); string tmp = configPath + ".tmp";
File.WriteAllText(configPath, mergedJson); System.IO.File.WriteAllText(tmp, mergedJson, System.Text.Encoding.UTF8);
if (System.IO.File.Exists(configPath))
System.IO.File.Replace(tmp, configPath, null);
else
System.IO.File.Move(tmp, configPath);
try
{
if (IsValidUv(uvPath)) UnityEditor.EditorPrefs.SetString("UnityMCP.UvPath", uvPath);
UnityEditor.EditorPrefs.SetString("UnityMCP.ServerSrc", serverSrc);
}
catch { }
return "Configured successfully"; return "Configured successfully";
} }
private void ShowManualConfigurationInstructions( private void ShowManualConfigurationInstructions(
@ -1147,7 +1167,7 @@ namespace UnityMcpBridge.Editor.Windows
unityMCP = new unityMCP = new
{ {
command = uvPathManual, command = uvPathManual,
args = new[] { "--directory", pythonDir, "run", "server.py" }, args = new[] { "run", "--directory", pythonDir, "server.py" },
type = "stdio" type = "stdio"
} }
} }
@ -1171,7 +1191,7 @@ namespace UnityMcpBridge.Editor.Windows
unityMCP = new McpConfigServer unityMCP = new McpConfigServer
{ {
command = uvPath, command = uvPath,
args = new[] { "--directory", pythonDir, "run", "server.py" }, args = new[] { "run", "--directory", pythonDir, "server.py" },
}, },
}, },
}; };
@ -1182,9 +1202,38 @@ namespace UnityMcpBridge.Editor.Windows
ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient); ManualConfigEditorWindow.ShowWindow(configPath, manualConfigJson, mcpClient);
} }
private string FindPackagePythonDirectory() private static string ResolveServerSrc()
{
try
{
string remembered = UnityEditor.EditorPrefs.GetString("UnityMCP.ServerSrc", string.Empty);
if (!string.IsNullOrEmpty(remembered) && File.Exists(Path.Combine(remembered, "server.py")))
{
return remembered;
}
ServerInstaller.EnsureServerInstalled();
string installed = ServerInstaller.GetServerPath();
if (File.Exists(Path.Combine(installed, "server.py")))
{
return installed;
}
bool useEmbedded = UnityEditor.EditorPrefs.GetBool("UnityMCP.UseEmbeddedServer", false);
if (useEmbedded && ServerPathResolver.TryFindEmbeddedServerSource(out string embedded)
&& File.Exists(Path.Combine(embedded, "server.py")))
{
return embedded;
}
return installed;
}
catch { return ServerInstaller.GetServerPath(); }
}
private string FindPackagePythonDirectory()
{ {
string pythonDir = ServerInstaller.GetServerPath(); string pythonDir = ResolveServerSrc();
try try
{ {
@ -1211,17 +1260,25 @@ namespace UnityMcpBridge.Editor.Windows
} }
} }
// Resolve via shared helper (handles local registry and older fallback) // Resolve via shared helper (handles local registry and older fallback) only if dev override on
if (ServerPathResolver.TryFindEmbeddedServerSource(out string embedded)) if (UnityEditor.EditorPrefs.GetBool("UnityMCP.UseEmbeddedServer", false))
{ {
return embedded; if (ServerPathResolver.TryFindEmbeddedServerSource(out string embedded))
} {
return embedded;
}
}
// If still not found, return the placeholder path // Log only if the resolved path does not actually contain server.py
if (debugLogsEnabled) if (debugLogsEnabled)
{ {
UnityEngine.Debug.LogWarning("Could not find Python directory, using placeholder path"); bool hasServer = false;
} try { hasServer = File.Exists(Path.Combine(pythonDir, "server.py")); } catch { }
if (!hasServer)
{
UnityEngine.Debug.LogWarning("Could not find Python directory with server.py; falling back to installed path");
}
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -1354,7 +1411,7 @@ namespace UnityMcpBridge.Editor.Windows
unityMCP = new McpConfigServer unityMCP = new McpConfigServer
{ {
command = uvPath, command = uvPath,
args = new[] { "--directory", pythonDir, "run", "server.py" }, args = new[] { "run", "--directory", pythonDir, "server.py" },
}, },
}, },
}; };

View File

@ -1,6 +1,6 @@
version = 1 version = 1
revision = 1 revision = 1
requires-python = ">=3.12" requires-python = ">=3.10"
[[package]] [[package]]
name = "annotated-types" name = "annotated-types"
@ -16,6 +16,7 @@ name = "anyio"
version = "4.9.0" version = "4.9.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "idna" }, { name = "idna" },
{ name = "sniffio" }, { name = "sniffio" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" },
@ -55,6 +56,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
] ]
[[package]]
name = "exceptiongroup"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674 },
]
[[package]] [[package]]
name = "h11" name = "h11"
version = "0.14.0" version = "0.14.0"
@ -179,6 +192,33 @@ dependencies = [
] ]
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938 },
{ url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684 },
{ url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169 },
{ url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227 },
{ url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695 },
{ url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662 },
{ url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370 },
{ url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813 },
{ url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287 },
{ url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414 },
{ url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301 },
{ url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685 },
{ url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876 },
{ url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 },
{ url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 },
{ url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 },
{ url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 },
{ url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 },
{ url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 },
{ url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 },
{ url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 },
{ url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 },
{ url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 },
{ url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 },
{ url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 },
{ url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 },
{ url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 },
{ url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 },
{ url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 },
{ url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 },
@ -207,6 +247,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
{ url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159 },
{ url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331 },
{ url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467 },
{ url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797 },
{ url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839 },
{ url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861 },
{ url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582 },
{ url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985 },
{ url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715 },
] ]
[[package]] [[package]]
@ -247,6 +296,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "markdown-it-py" }, { name = "markdown-it-py" },
{ name = "pygments" }, { name = "pygments" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
wheels = [ wheels = [
@ -342,6 +392,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "click" }, { name = "click" },
{ name = "h11" }, { name = "h11" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 }
wheels = [ wheels = [

View File

@ -1,6 +1,6 @@
{ {
"name": "com.coplaydev.unity-mcp", "name": "com.coplaydev.unity-mcp",
"version": "2.1.0", "version": "2.1.1",
"displayName": "Unity MCP Bridge", "displayName": "Unity MCP Bridge",
"description": "A bridge that manages and communicates with the sister application, Unity MCP Server, which allows for communications with MCP Clients like Claude Desktop or Cursor.", "description": "A bridge that manages and communicates with the sister application, Unity MCP Server, which allows for communications with MCP Clients like Claude Desktop or Cursor.",
"unity": "2020.3", "unity": "2020.3",

51
claude-chunk.md Normal file
View File

@ -0,0 +1,51 @@
### macOS: Claude CLI fails to start (dyld ICU library not loaded)
- Symptoms
- Unity MCP error: “Failed to start Claude CLI. dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.71.dylib …”
- Running `claude` in Terminal fails with missing `libicui18n.xx.dylib`.
- Cause
- Homebrew Node (or the `claude` binary) was linked against an ICU version thats no longer installed; dyld cant find that dylib.
- Fix options (pick one)
- Reinstall Homebrew Node (relinks to current ICU), then reinstall CLI:
```bash
brew update
brew reinstall node
npm uninstall -g @anthropic-ai/claude-code
npm install -g @anthropic-ai/claude-code
```
- Use NVM Node (avoids Homebrew ICU churn):
```bash
nvm install --lts
nvm use --lts
npm install -g @anthropic-ai/claude-code
# Unity MCP → Claude Code → Choose Claude Location → ~/.nvm/versions/node/<ver>/bin/claude
```
- Use the native installer (puts claude in a stable path):
```bash
# macOS/Linux
curl -fsSL https://claude.ai/install.sh | bash
# Unity MCP → Claude Code → Choose Claude Location → /opt/homebrew/bin/claude or ~/.local/bin/claude
```
- After fixing
- In Unity MCP (Claude Code), click “Choose Claude Location” and select the working `claude` binary, then Register again.
- More details
- See: Troubleshooting Unity MCP and Claude Code
---
### FAQ (Claude Code)
- Q: Unity cant find `claude` even though Terminal can.
- A: macOS apps launched from Finder/Hub dont inherit your shell PATH. In the Unity MCP window, click “Choose Claude Location” and select the absolute path (e.g., `/opt/homebrew/bin/claude` or `~/.nvm/versions/node/<ver>/bin/claude`).
- Q: I installed via NVM; where is `claude`?
- A: Typically `~/.nvm/versions/node/<ver>/bin/claude`. Our UI also scans NVM versions and you can browse to it via “Choose Claude Location”.
- Q: The Register button says “Claude Not Found”.
- A: Install the CLI or set the path. Click the orange “[HELP]” link in the Unity MCP window for stepbystep install instructions, then choose the binary location.

6
package-lock.json generated Normal file
View File

@ -0,0 +1,6 @@
{
"name": "unity-mcp",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

1
package.json Normal file
View File

@ -0,0 +1 @@
{}