Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions MCPForUnity/Editor/Dependencies/DependencyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public static DependencyCheckResult CheckAllDependencies()
var uvStatus = detector.DetectUv();
result.Dependencies.Add(uvStatus);

// Check git (optional: Package Manager Git-URL installs only)
result.Dependencies.Add(detector.DetectGit());

// Generate summary and recommendations
result.GenerateSummary();
GenerateRecommendations(result, detector);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public interface IPlatformDetector
/// </summary>
DependencyStatus DetectUv();

/// <summary>
/// Detect git on this platform. Optional: only the Package Manager's Git-URL install path needs it.
/// </summary>
DependencyStatus DetectGit();

/// <summary>
/// Get platform-specific installation recommendations
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,67 @@ public virtual DependencyStatus DetectUv()
}


// Git is not needed to run the bridge, only to add or update the package from a Git URL
// in the Package Manager, which is the install path most users take (issue #1216). It is
// reported as optional so a missing git never blocks setup, but the row tells the user why
// "Error when executing git command" appeared and how to clear it.
public const string GitInstallUrl = "https://git-scm.com/downloads";

public virtual DependencyStatus DetectGit()
{
var status = new DependencyStatus("Git", isRequired: false)
{
InstallationHint = GitInstallUrl
};

try
{
if (!TryFindInPath("git", out string gitPath))
{
status.ErrorMessage = "git not found";
status.Details = "Only needed to add or update MCP for Unity from a Git URL in the Package Manager.";
return status;
}

if (ExecPath.TryRun(gitPath, "--version", null, out string stdout, out string stderr, 5000)
&& TryParseGitVersion(string.IsNullOrWhiteSpace(stdout) ? stderr : stdout, out string version))
{
status.IsAvailable = true;
status.Version = version;
status.Path = gitPath;
status.Details = "If the Package Manager still reports 'not in a git directory', git is refusing a folder "
+ "owned by another user: run git config --global --add safe.directory <project folder>";
return status;
}

status.ErrorMessage = "git found but did not report a version";
status.Path = gitPath;
}
catch (Exception ex)
{
status.ErrorMessage = $"Error detecting git: {ex.Message}";
}

return status;
}

/// <summary>Parses "git version 2.45.1.windows.1" or "git version 2.39.5 (Apple Git-154)" into "2.45.1.windows.1" / "2.39.5".</summary>
internal static bool TryParseGitVersion(string output, out string version)
{
version = null;
string line = (output ?? string.Empty).Trim();
const string prefix = "git version ";
if (!line.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
return false;
}

string rest = line.Substring(prefix.Length).Trim();
int end = rest.IndexOfAny(new[] { ' ', '\r', '\n' });
version = end >= 0 ? rest.Substring(0, end) : rest;
return version.Length > 0 && char.IsDigit(version[0]);
}

protected bool TryParseVersion(string version, out int major, out int minor)
{
major = 0;
Expand Down
21 changes: 19 additions & 2 deletions MCPForUnity/Editor/Windows/MCPSetupWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public class MCPSetupWindow : EditorWindow
private VisualElement uvIndicator;
private Label uvVersion;
private Label uvDetails;
private VisualElement gitIndicator;
private Label gitVersion;
private Label gitDetails;
private Label statusMessage;
private VisualElement installationSection;
private Label installationInstructions;
Expand Down Expand Up @@ -88,6 +91,9 @@ public void CreateGUI()
uvIndicator = rootVisualElement.Q<VisualElement>("uv-indicator");
uvVersion = rootVisualElement.Q<Label>("uv-version");
uvDetails = rootVisualElement.Q<Label>("uv-details");
gitIndicator = rootVisualElement.Q<VisualElement>("git-indicator");
gitVersion = rootVisualElement.Q<Label>("git-version");
gitDetails = rootVisualElement.Q<Label>("git-details");
statusMessage = rootVisualElement.Q<Label>("status-message");
installationSection = rootVisualElement.Q<VisualElement>("installation-section");
installationInstructions = rootVisualElement.Q<Label>("installation-instructions");
Expand Down Expand Up @@ -328,6 +334,13 @@ private void UpdateUI()
UpdateDependencyStatus(uvIndicator, uvVersion, uvDetails, uvDep);
}

// Update git status (optional dependency: never blocks readiness)
var gitDep = _dependencyResult.Dependencies.Find(d => d.Name == "Git");
if (gitDep != null)
{
UpdateDependencyStatus(gitIndicator, gitVersion, gitDetails, gitDep);
}

// Offer the one-click uv installer only when uv is actually missing
bool uvMissing = uvDep != null && !uvDep.IsAvailable;
if (installUvButton != null)
Expand Down Expand Up @@ -367,8 +380,12 @@ private void UpdateDependencyStatus(VisualElement indicator, Label versionLabel,
indicator.RemoveFromClassList("valid");
indicator.AddToClassList("invalid");
versionLabel.text = "Not Found";
Comment on lines 380 to 382
detailsLabel.text = dep.ErrorMessage ?? "Not available";
detailsLabel.style.color = new StyleColor(Color.red);
// A missing optional dependency is information, not a blocker: show what it is
// for in the neutral colour instead of the red used for required ones.
detailsLabel.text = dep.IsRequired
? dep.ErrorMessage ?? "Not available"
: dep.Details ?? dep.ErrorMessage ?? "Not available";
detailsLabel.style.color = new StyleColor(dep.IsRequired ? Color.red : Color.gray);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion MCPForUnity/Editor/Windows/MCPSetupWindow.uxml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ui:VisualElement class="section">
<ui:Label text="System Requirements" class="section-title" />
<ui:VisualElement class="section-content">
<ui:Label text="MCP for Unity requires Python 3.10+ and UV package manager to function." class="help-text description-text" />
<ui:Label text="MCP for Unity requires Python 3.10+ and UV package manager to function. Git is only needed to install or update the package from a Git URL." class="help-text description-text" />

<!-- Dependency Status -->
<ui:VisualElement name="dependency-list">
Expand All @@ -34,6 +34,16 @@
</ui:VisualElement>
<ui:Label name="uv-details" class="help-text dependency-details" />
</ui:VisualElement>

<!-- Git Status (optional) -->
<ui:VisualElement class="dependency-item">
<ui:VisualElement class="dependency-row">
<ui:Label text="Git (optional)" class="dependency-name" />
<ui:Label name="git-version" text="..." class="setting-value" />
<ui:VisualElement name="git-indicator" class="status-indicator-small" />
</ui:VisualElement>
<ui:Label name="git-details" class="help-text dependency-details" />
</ui:VisualElement>
</ui:VisualElement>

<!-- Overall Status Message -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Linq;
using MCPForUnity.Editor.Dependencies;
using MCPForUnity.Editor.Dependencies.Models;
using MCPForUnity.Editor.Dependencies.PlatformDetectors;
using NUnit.Framework;

namespace MCPForUnityTests.Editor
{
public class GitDetectionTests
{
[TestCase("git version 2.45.1.windows.1", "2.45.1.windows.1")]
[TestCase("git version 2.39.5 (Apple Git-154)", "2.39.5")]
[TestCase(" git version 2.43.0\n", "2.43.0")]
public void TryParseGitVersion_ExtractsTheVersionToken(string output, string expected)
{
Assert.IsTrue(PlatformDetectorBase.TryParseGitVersion(output, out string version));
Assert.AreEqual(expected, version);
}

[TestCase("")]
[TestCase(null)]
[TestCase("'git' is not recognized as an internal or external command")]
[TestCase("git version ")]
[TestCase("git version beta")]
public void TryParseGitVersion_RejectsAnythingThatIsNotAGitVersionLine(string output)
{
Assert.IsFalse(PlatformDetectorBase.TryParseGitVersion(output, out _));
}

[Test]
public void CheckAllDependencies_ReportsGitAsOptional()
{
var result = DependencyManager.CheckAllDependencies();
var git = result.Dependencies.FirstOrDefault(d => d.Name == "Git");

Assert.IsNotNull(git, "The dependency check should always include a Git row");
Assert.IsFalse(git.IsRequired, "Git must never block setup; only Git-URL installs need it");
Assert.AreEqual(PlatformDetectorBase.GitInstallUrl, git.InstallationHint);
if (git.IsAvailable)
{
Assert.IsFalse(string.IsNullOrEmpty(git.Version));
Assert.IsFalse(string.IsNullOrEmpty(git.Path));
}
else
{
Assert.IsFalse(string.IsNullOrEmpty(git.ErrorMessage));
}
}

[Test]
public void MissingGit_DoesNotMakeTheSystemNotReady()
{
// Mirrors what the setup window computes: Python and uv present, git absent.
var result = new DependencyCheckResult();
result.Dependencies.Add(new DependencyStatus("Python") { IsAvailable = true, Version = "3.12.0" });
result.Dependencies.Add(new DependencyStatus("uv Package Manager") { IsAvailable = true, Version = "0.8.0" });
result.Dependencies.Add(new DependencyStatus("Git", isRequired: false) { IsAvailable = false, ErrorMessage = "git not found" });

result.GenerateSummary();

Assert.IsTrue(result.IsSystemReady);
Assert.IsTrue(result.HasMissingOptional);
Assert.IsEmpty(result.GetMissingRequired());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions website/docs/getting-started/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Three install paths are supported. Pick one. **Git URL** is the fastest if you j

## Option 1 — Git URL (fastest)

This path needs `git` on your PATH (the Package Manager runs it). If it reports `Error when executing git command`, see [troubleshooting](../guides/troubleshooting.md#package-manager-error-when-executing-git-command--not-in-a-git-directory).

In Unity, open **Window → Package Manager**, click the **`+`** button, choose **Add package from git URL...**, and paste:

```text
Expand Down
17 changes: 17 additions & 0 deletions website/docs/guides/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,23 @@ This is a Unity bug (UUM-132096), not an MCP for Unity one.

---

## Package Manager: "Error when executing git command" / "not in a git directory"

Adding the package from a Git URL makes the Package Manager shell out to `git`. Two things make that fail:

1. **git is not installed or not on PATH.** Install it from [git-scm.com](https://git-scm.com/downloads) and restart Unity so the Editor picks up the new PATH. The setup window (**Window → MCP for Unity → Local Setup Window**) shows a **Git (optional)** row so you can confirm the Editor sees it.
2. **git refuses the folder.** Newer git versions decline to run inside a directory owned by a different user account (external drives, shared folders, projects created by another account). The Package Manager surfaces this as `fatal: not in a git directory`. Tell git the folder is yours:

```bash
git config --global --add safe.directory "/path/to/the/parent/folder"
```

Trusting the parent folder covers every project inside it. Restart Unity and add the package again.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

Git is only needed for this install path; the bridge itself does not use it, so a missing git never blocks setup.

*Reported by [@Cherrymocha](https://github.com/CoplayDev/unity-mcp/issues/1216).*

## Codex: `resources/read failed: unknown MCP server`

The `mcpforunity://` URI names the *resource*, not the server. Some clients take a separate server key on a resource read.
Expand Down
Loading