Skip to content

Conversation

@dsarno
Copy link
Collaborator

@dsarno dsarno commented Nov 26, 2025

This is partial and not windows tested. It worked for claude and claude code on mac for stdio.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced automatic detection of uvx installation location across macOS, Linux, and Windows with improved fallback resolution logic.
  • Documentation

    • Added troubleshooting guidance for "spawn uvx ENOENT" errors on macOS with clear remediation steps, including manual configuration options.

✏️ Tip: You can customize this high-level summary in your review settings.

Problem:
The port discovery mechanism was failing to detect running Unity instances
because the _try_probe_unity_mcp() function was using struct.pack() and
struct.unpack() without importing the struct module, and other functions
were using os.path.basename() without importing the os module. This caused
NameError exceptions that were silently caught, preventing Unity instances
from being discovered.

Root Cause:
- struct.pack() used at line 80 to create message headers
- struct.unpack() used at line 98 to parse response headers
- os.path.basename() used at lines 217 and 247 to extract filenames
- Neither os nor struct modules were imported

Impact:
- Unity instances running on port 6400 were not discoverable
- The MCP server would fail to connect even when Unity was running
- The probe function would fail silently due to exception handling

Solution:
Added missing imports:
- import os (for os.path.basename)
- import struct (for struct.pack/unpack in the framed protocol)

Verification:
- Test script confirmed Unity is responding correctly on port 6400
- The framed protocol (8-byte header + payload) works correctly
- Once the MCP server restarts with these imports, Unity discovery will work
Claude Desktop on macOS does not inherit the user's full PATH, causing 'spawn uvx ENOENT' errors when it tries to run the server.

This change adds auto-discovery logic to find 'uvx' in common locations (like ~/.local/bin, ~/.cargo/bin, /opt/homebrew/bin) and writes the absolute path to the config.

Also updated README with troubleshooting steps.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

This PR adds automatic cross-platform discovery for the uvx executable path. A new ResolveUvx() method in ExecPath implements OS-specific lookup strategies, and PathResolverService integrates this as a fallback mechanism when no explicit path is configured. Documentation is updated with troubleshooting guidance for macOS uvx resolution issues.

Changes

Cohort / File(s) Summary
UVX Path Resolution
MCPForUnity/Editor/Helpers/ExecPath.cs, MCPForUnity/Editor/Services/PathResolverService.cs
Added new internal ResolveUvx() method implementing platform-specific lookup (macOS/Linux via Which(), Windows via Where()); integrated as fallback in GetUvxPath() after checking overrides but before defaulting to literal "uvx"
Documentation Update
MCPForUnity/README.md
Added troubleshooting section for Claude Desktop "spawn uvx ENOENT" error on macOS, explaining PATH inheritance limitations and documenting the auto-discovery fallback and manual remediation steps
Port Discovery Imports
Server/src/transport/legacy/port_discovery.py
Added os and struct module imports; no functional changes

Sequence Diagram

sequenceDiagram
    participant PR as PathResolverService
    participant EP as ExecPath
    participant OS as Operating System
    
    PR->>PR: Check for uvx path override
    alt Override exists
        PR-->>PR: Return override path
    else No override
        PR->>EP: ResolveUvx()
        rect rgb(200, 220, 255)
            note over EP: Platform-specific lookup
            alt macOS/Linux
                EP->>OS: Which("uvx")
            else Windows
                EP->>OS: Check appdata candidates
                EP->>OS: Where("uvx.exe"/"uvx")
            end
        end
        alt Path found
            EP-->>PR: Return absolute path
        else Not found
            EP-->>PR: Return null
        end
        alt Discovered path available
            PR-->>PR: Return resolved path
        else Discovery failed
            PR-->>PR: Return "uvx" (literal)
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • ExecPath.ResolveUvx(): Multiple platform-specific branches (macOS/Linux vs. Windows) with hardcoded candidate paths that should be validated for accuracy and completeness
  • PathResolverService integration: Verify the fallback order and ensure no edge cases where both resolved and literal paths could conflict
  • README documentation: Confirm accuracy of troubleshooting guidance and path examples (e.g., ~/.local/bin/uvx)

Possibly related PRs

Poem

🐰 A bunny hops through paths unknown,
On Windows, Mac, and Linux stone,
Where uvx hides, we'll seek and find,
With platform smarts and fallbacks kind—
No ENOENT shall make us frown! 🎯

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Fix/port discovery missing imports' is misleading. While the changes do add missing imports to port_discovery.py, the bulk of the changeset adds new UVX path resolution functionality across three files, which is not reflected in the title. Revise the title to reflect the primary changes, such as 'Add UVX executable auto-discovery for Claude Desktop integration' to accurately represent the scope of changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
MCPForUnity/Editor/Helpers/ExecPath.cs (1)

135-183: Clarify the comment to match implementation.

The comment states "Pref → env → common locations → PATH" but the implementation only checks common locations and PATH. EditorPrefs (pref) is handled by the caller (PathResolverService.GetUvxPath()), and no environment variable is checked (unlike ResolveClaude() which checks CLAUDE_CLI).

Consider either:

  1. Updating the comment to reflect the actual flow: // Resolve uvx absolute path. Common locations -> PATH.
  2. Adding an environment variable check (e.g., UVX_PATH) for consistency with ResolveClaude().

Apply this diff to update the comment:

-        // Resolve uvx absolute path. Pref -> env -> common locations -> PATH.
+        // Resolve uvx absolute path. Common locations -> PATH.
MCPForUnity/README.md (1)

85-88: Clear troubleshooting guidance.

The documentation accurately describes the new auto-discovery behavior and provides helpful remediation steps for users encountering PATH issues with Claude Desktop on macOS.

Optionally, you can refine line 87 to avoid the split infinitive:

-  - The MCP for Unity plugin attempts to automatically resolve the absolute path to `uvx`.
+  - The MCP for Unity plugin automatically attempts to resolve the absolute path to `uvx`.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b25f7c and d463aa5.

📒 Files selected for processing (4)
  • MCPForUnity/Editor/Helpers/ExecPath.cs (1 hunks)
  • MCPForUnity/Editor/Services/PathResolverService.cs (1 hunks)
  • MCPForUnity/README.md (1 hunks)
  • Server/src/transport/legacy/port_discovery.py (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-05T16:22:04.960Z
Learnt from: dsarno
Repo: CoplayDev/unity-mcp PR: 265
File: README.md:204-204
Timestamp: 2025-09-05T16:22:04.960Z
Learning: In the Unity MCP project, the ServerInstaller.cs creates a symlink from ~/Library/AppSupport to ~/Library/Application Support on macOS to mitigate argument parsing and quoting issues in some MCP clients. The README documentation should use the shortened AppSupport path, not the full "Application Support" path with spaces.

Applied to files:

  • MCPForUnity/README.md
📚 Learning: 2025-09-05T16:22:04.960Z
Learnt from: dsarno
Repo: CoplayDev/unity-mcp PR: 265
File: README.md:204-204
Timestamp: 2025-09-05T16:22:04.960Z
Learning: In the Unity MCP project, the ServerInstaller.cs creates a symlink from ~/Library/AppSupport to ~/Library/Application Support on macOS to avoid spaces in paths that can cause arg parsing and quoting issues in some MCP clients. The README documentation should use the shortened AppSupport path, not the full "Application Support" path.

Applied to files:

  • MCPForUnity/README.md
📚 Learning: 2025-09-03T16:00:55.839Z
Learnt from: dsarno
Repo: CoplayDev/unity-mcp PR: 0
File: :0-0
Timestamp: 2025-09-03T16:00:55.839Z
Learning: ComponentResolver in UnityMcpBridge/Editor/Tools/ManageGameObject.cs is a nested static class within ManageGameObject, not a sibling type. The `using static MCPForUnity.Editor.Tools.ManageGameObject;` import is required to access ComponentResolver methods directly without the outer class qualifier.

Applied to files:

  • MCPForUnity/Editor/Helpers/ExecPath.cs
🧬 Code graph analysis (1)
MCPForUnity/Editor/Services/PathResolverService.cs (1)
MCPForUnity/Editor/Helpers/ExecPath.cs (2)
  • ExecPath (12-322)
  • ResolveUvx (136-183)
🪛 LanguageTool
MCPForUnity/README.md

[style] ~87-~87: Try moving the adverb to make the sentence clearer.
Context: ...ll's PATH. - The MCP for Unity plugin attempts to automatically resolve the absolute path to uvx. - If this fails, use the "C...

(SPLIT_INFINITIVE)

🔇 Additional comments (2)
Server/src/transport/legacy/port_discovery.py (1)

17-18: LGTM! Critical bug fix.

These imports are required by the existing code: struct is used for binary framing protocol operations (lines 80, 98) and os is used for path operations (lines 217, 247). Without these imports, the module would fail at runtime.

MCPForUnity/Editor/Services/PathResolverService.cs (1)

37-42: LGTM! Clean auto-discovery integration.

The fallback chain (override → auto-discovery → default) follows good defensive programming practices and mirrors the pattern used in GetClaudeCliPath(). This should resolve PATH inheritance issues on macOS while maintaining backward compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant