Skip to content

Conversation

@Jordonh18
Copy link
Contributor

@Jordonh18 Jordonh18 commented Dec 4, 2025

This pull request introduces a new configurator for VSCode Insiders GitHub Copilot and improves project ID resolution logic in the server, along with several documentation updates and bug fixes. The main changes are the addition of VSCodeInsidersConfigurator, enhanced fallback logic for reading the package version, improved project hash mapping for Unity instances, and more robust boolean handling in prefab management.

VSCode Insiders configurator and documentation updates:

  • Added a new VSCodeInsidersConfigurator class to support configuration of GitHub Copilot in VSCode Insiders, with Insider-specific config file paths and installation instructions. [1] [2]
  • Updated documentation in MCP_CLIENT_CONFIGURATORS.md to include VSCode Insiders in lists, examples, and instructions for adding configurators. [1] [2] [3]

Server improvements and bug fixes:

  • Improved fallback logic for reading the package version: now searches parent directories for pyproject.toml instead of assuming its location.
  • Enhanced project ID resolution for Unity instances: added mapping from project hash to project ID using get_project_id_for_hash, improving tool registration and lookup. [1] [2]
  • Improved boolean parameter handling in manage_prefabs.py by introducing a _coerce_bool function to robustly coerce values to booleans before sending to Unity.
  • Fixed a bug in script_apply_edits.py by making the call to async_send_command_with_retry awaitable, ensuring proper async behavior.
    This pull request introduces support for configuring the VSCode Insiders GitHub Copilot client in MCP for Unity, improves project ID resolution for custom tools, enhances boolean parameter handling in prefab management, and fixes a bug in script edit application. Documentation is also updated to reflect the new configurator and its usage.

VSCode Insiders client support:

  • Added VSCodeInsidersConfigurator class to support configuration for VSCode Insiders GitHub Copilot, with platform-specific config paths and installation steps. (MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs, MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs.meta) [1] [2]
  • Updated documentation to include VSCode Insiders configurator in guides and examples. (docs/MCP_CLIENT_CONFIGURATORS.md) [1] [2] [3]

Custom tool project ID resolution:

  • Improved mapping of Unity instance hashes to project IDs in custom tool service, allowing for more robust identification. (Server/src/services/custom_tool_service.py) [1] [2]

Prefab management improvements:

  • Enhanced boolean parameter handling in manage_prefabs tool by introducing a _coerce_bool helper for more reliable type conversion. (Server/src/services/tools/manage_prefabs.py)

Bug fixes:

  • Fixed a bug in script edit application by awaiting the async_send_command_with_retry call for reading scripts. (Server/src/services/tools/script_apply_edits.py)

Miscellaneous:

  • Improved fallback logic for reading pyproject.toml in telemetry to search ancestor directories. (Server/src/core/telemetry.py)
  • Refactored UVX/UV path handling in server management service for reliability. (MCPForUnity/Editor/Services/ServerManagementService.cs) [1] [2] [3]

Summary by CodeRabbit

  • New Features

    • Added a VS Code Insiders configurator with clear, user-facing installation steps.
  • Documentation

    • Updated MCP configurator docs to cover VS Code Insiders and guidance.
  • Refactor

    • Centralized boolean coercion into a shared utility and updated callers.
    • Consolidated internal editor executable path resolution.
  • Bug Fixes / Reliability

    • Improved package-version discovery via ancestor search.
    • Made an editor read operation properly asynchronous.
    • Added a lookup to map project hashes to project IDs.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Walkthrough

Adds a VS Code Insiders MCP configurator and Unity .meta; centralizes UV executable path reconstruction; improves pyproject.toml discovery by searching ancestor directories; adds hash→project mapping and uses it in project resolution; introduces a shared coerce_bool utility used by several tool handlers; awaits one async script read; and updates configurator documentation.

Changes

Cohort / File(s) Summary
VSCode Insiders Configurator
MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs, MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs.meta
New public VSCodeInsidersConfigurator (extends JsonFileMcpConfigurator) with cross-platform McpClient setup and overridden GetInstallationSteps(); added Unity .meta asset file.
Client UV Path Resolution
MCPForUnity/Editor/Services/ServerManagementService.cs
Replaced inline uvxPath.Remove(...) uses with new private helper BuildUvPathFromUvx(string) and applied it in ClearUvxCache and ExecuteUvCommand.
Python package discovery
Server/src/core/telemetry.py
Added PACKAGE_NAME constant and replaced fixed-path pyproject fallback with _version_from_local_pyproject() that walks ancestors to locate pyproject.toml and extract version.
Custom Tool Service mapping
Server/src/services/custom_tool_service.py
Added `get_project_id_for_hash(project_hash: str
Boolean coercion utility
Server/src/services/tools/utils.py
New module exporting `coerce_bool(value: Any, default: bool
Tools updated to use shared coercion
Server/src/services/tools/manage_prefabs.py, Server/src/services/tools/manage_editor.py, Server/src/services/tools/manage_gameobject.py
Replaced local/inlined boolean coercion with imported coerce_bool; include coerced values conditionally where appropriate.
Async script read
Server/src/services/tools/script_apply_edits.py
Converted the Unity script read operation to await async_send_command_with_retry(...) to properly await coroutine result.
Documentation
docs/MCP_CLIENT_CONFIGURATORS.md
Added VSCode Insiders references, examples, path guidance, and installation steps for the new configurator.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect BuildUvPathFromUvx() for correct filename/extension handling across platforms (Windows .exe preservation).
  • Verify pyproject.toml upward traversal stops at a sensible root and error behavior is appropriate.
  • Confirm get_project_id_for_hash() mapping and fallback behavior in resolve_project_id_for_unity_instance() (error swallowing and return semantics).
  • Review coerce_bool() string mappings and call sites for None/default propagation and conditional parameter inclusion.
  • Check the awaited call in script_apply_edits.py preserves exception propagation and integrates with surrounding async flow.

Possibly related issues

Possibly related PRs

Suggested reviewers

  • Scriptwonder

Poem

🐰 I nibbled through configs, paths, and docs with care,
swapped muddled uvx for tidy uv hair,
chased pyproject upwards through tree and root,
taught booleans manners and made awaits commute,
now I hop off, satisfied — carrot-earned flair.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary changes: adding VSCode Insiders support and including robustness improvements and bug fixes, which accurately reflects the main objectives and changes in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65bdb91 and 230f062.

📒 Files selected for processing (1)
  • Server/src/services/tools/manage_gameobject.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Server/src/services/tools/manage_gameobject.py

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: 1

🧹 Nitpick comments (3)
Server/src/core/telemetry.py (1)

51-61: Ancestor pyproject discovery looks solid; consider simplifying the error path and narrowing the try scope

The parent-walk to find pyproject.toml is a good robustness improvement and should behave well across layouts. One minor clean-up: FileNotFoundError is raised at Line 59 only to be immediately caught by the surrounding except Exception and converted to "unknown". You could instead:

  • Return "unknown" (or log + return) when pyproject_path is None before entering the try that does file I/O/parsing, and
  • Restrict the inner try/except to open() + tomli.load() + dict access.

This avoids using exceptions for local control flow, keeps the search logic outside the broad except, and should clear the Ruff TRY301/TRY003 hints without changing behavior.

Server/src/services/custom_tool_service.py (2)

262-275: Duplicate _safe_response definitions can be collapsed

_safe_response is defined twice with identical bodies (lines 262-268 and 269-274). The second definition simply overwrites the first, so it’s harmless but adds noise.

You can safely drop one of the definitions to keep the class slimmer:

-    def _safe_response(self, response):
-        if isinstance(response, dict):
-            return response
-        if response is None:
-            return None
-        return {"message": str(response)}
-
     def _safe_response(self, response):
         if isinstance(response, dict):
             return response
         if response is None:
             return None
         return {"message": str(response)}

240-260: Unreachable second dict-handling branch in _normalize_response

After the early if isinstance(response, dict): return MCPResponse(...) at lines 231-238, the later if isinstance(response, dict): ... block at lines 245-255 is never reached. This looks like a leftover from an earlier refactor.

Consider simplifying _normalize_response to a single dict-handling path to reduce cognitive load and avoid future confusion:

     def _normalize_response(self, response) -> MCPResponse:
         if isinstance(response, MCPResponse):
             return response
-        if isinstance(response, dict):
-            return MCPResponse(
-                success=response.get("success", True),
-                message=response.get("message"),
-                error=response.get("error"),
-                data=response.get(
-                    "data", response) if "data" not in response else response["data"],
-            )
-
-        success = True
-        message = None
-        error = None
-        data = None
-
-        if isinstance(response, dict):
-            success = response.get("success", True)
-            if "_mcp_status" in response and response["_mcp_status"] == "error":
-                success = False
-            message = str(response.get("message")) if response.get(
-                "message") else None
-            error = str(response.get("error")) if response.get(
-                "error") else None
-            data = response.get("data")
-            if "success" not in response and "_mcp_status" not in response:
-                data = response
-        else:
-            success = False
-            message = str(response)
-
-        return MCPResponse(success=success, message=message, error=error, data=data)
+        if isinstance(response, dict):
+            success = response.get("success", True)
+            if response.get("_mcp_status") == "error":
+                success = False
+            message = str(response.get("message")) if response.get("message") else None
+            error = str(response.get("error")) if response.get("error") else None
+            data = response.get("data")
+            if "success" not in response and "_mcp_status" not in response:
+                data = response
+            return MCPResponse(success=success, message=message, error=error, data=data)
+
+        return MCPResponse(success=False, message=str(response), error=None, data=None)

(Adjust exact shape as needed to match your intended semantics.)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa47838 and 993ca32.

📒 Files selected for processing (8)
  • MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs (1 hunks)
  • MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs.meta (1 hunks)
  • MCPForUnity/Editor/Services/ServerManagementService.cs (3 hunks)
  • Server/src/core/telemetry.py (1 hunks)
  • Server/src/services/custom_tool_service.py (2 hunks)
  • Server/src/services/tools/manage_prefabs.py (1 hunks)
  • Server/src/services/tools/script_apply_edits.py (1 hunks)
  • docs/MCP_CLIENT_CONFIGURATORS.md (3 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 401
File: MCPForUnity/Editor/Clients/Configurators/VSCodeConfigurator.cs:10-18
Timestamp: 2025-11-27T21:09:35.011Z
Learning: VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory: %APPDATA%\Code\User\mcp.json on Windows, ~/Library/Application Support/Code/User/mcp.json on macOS, and ~/.config/Code/User/mcp.json on Linux. This is in addition to workspace-scoped .vscode/mcp.json files.
📚 Learning: 2025-11-27T21:09:35.011Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 401
File: MCPForUnity/Editor/Clients/Configurators/VSCodeConfigurator.cs:10-18
Timestamp: 2025-11-27T21:09:35.011Z
Learning: VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory: %APPDATA%\Code\User\mcp.json on Windows, ~/Library/Application Support/Code/User/mcp.json on macOS, and ~/.config/Code/User/mcp.json on Linux. This is in addition to workspace-scoped .vscode/mcp.json files.

Applied to files:

  • MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs
  • docs/MCP_CLIENT_CONFIGURATORS.md
📚 Learning: 2025-10-24T14:09:08.615Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 348
File: MCPForUnity/Editor/Helpers/ConfigJsonBuilder.cs:71-79
Timestamp: 2025-10-24T14:09:08.615Z
Learning: The SystemRoot environment variable on Windows is only required for Codex MCP client configurations due to a Codex bug. Other MCP clients (VSCode, Cursor, Windsurf, Kiro) do not need this environment variable. Codex configurations use TOML format (CodexConfigHelper.cs), while other clients use JSON format (ConfigJsonBuilder.cs).

Applied to files:

  • docs/MCP_CLIENT_CONFIGURATORS.md
🧬 Code graph analysis (4)
MCPForUnity/Editor/Services/ServerManagementService.cs (1)
MCPForUnity/Editor/Helpers/AssetPathUtility.cs (1)
  • uvxPath (169-176)
MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs (1)
MCPForUnity/Editor/Models/McpClient.cs (1)
  • McpClient (5-55)
Server/src/services/tools/script_apply_edits.py (1)
Server/src/transport/legacy/unity_connection.py (1)
  • async_send_command_with_retry (753-785)
Server/src/services/tools/manage_prefabs.py (2)
Server/src/services/tools/manage_editor.py (1)
  • _coerce_bool (30-41)
Server/src/services/tools/manage_gameobject.py (1)
  • _coerce_bool (75-86)
🪛 Ruff (0.14.7)
Server/src/core/telemetry.py

59-59: Abstract raise to an inner function

(TRY301)


59-59: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (13)
Server/src/services/tools/script_apply_edits.py (1)

602-610: Awaiting async_send_command_with_retry correctly fixes the async bug

Changing the read call to await async_send_command_with_retry(...) brings it in line with the rest of the async flow and ensures read_resp is the actual response object rather than a coroutine. The surrounding success/error handling remains consistent and looks correct.

Please run the existing tests (or a manual end‑to‑end check of script_apply_edits with a real Unity instance) to confirm the read path now behaves as expected under asyncio scheduling.

MCPForUnity/Editor/Services/ServerManagementService.cs (3)

102-116: Well-structured helper for path transformation.

The BuildUvPathFromUvx method cleanly centralizes the logic to derive the uv executable path from the uvx path. The implementation correctly handles:

  • Null/whitespace input (returns as-is)
  • Preserves the directory and extension
  • Handles the case where directory is empty (bare filename)

24-25: LGTM!

The call site correctly uses the new helper to build the UV path from the UVX path, improving readability over inline string manipulation.


75-76: LGTM!

Consistent usage of the centralized helper method.

MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs.meta (1)

1-11: Standard Unity meta file.

The meta file follows the expected format for a MonoImporter asset with a valid GUID.

docs/MCP_CLIENT_CONFIGURATORS.md (3)

7-7: LGTM!

Documentation correctly lists VSCode Insiders among the supported JSON-file clients.


93-93: LGTM!

The description accurately reflects the implementation: IsVsCodeLayout = true with Insider-specific Code - Insiders/User/mcp.json paths.


222-222: LGTM!

VSCodeInsidersConfigurator is properly included in the list of example configurators for reference.

MCPForUnity/Editor/Clients/Configurators/VSCodeInsidersConfigurator.cs (2)

8-18: Well-implemented configurator following established patterns.

The configurator correctly:

  • Extends JsonFileMcpConfigurator
  • Sets IsVsCodeLayout = true for VS Code-style config structure
  • Uses the correct Insider-specific paths (Code - Insiders folder) that mirror the standard VS Code paths

Based on learnings, VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory, and this pattern applies to VS Code Insiders with Code - Insiders/User/mcp.json.


20-26: LGTM!

The installation steps are clear and consistent with other VS Code-family configurators.

Server/src/services/tools/manage_prefabs.py (1)

53-63: LGTM! Robust boolean parameter handling.

The coercion and conditional inclusion pattern correctly normalizes boolean inputs from various sources (bool, string representations, etc.) and only includes them in the params dictionary when explicitly provided. This prevents unintended default values from being sent to Unity.

Server/src/services/custom_tool_service.py (2)

149-152: Hash→project lookup helper is correct and aligned with registration path

This helper cleanly mirrors how _hash_to_project is populated (lowercased keys) and safely handles falsy input, giving you a simple, typed accessor instead of exposing the dict. No issues from my side here.


325-334: Project-hash mapping with graceful fallback looks solid

Parsing hash_part, normalizing to lowercase, then preferentially resolving via CustomToolService.get_project_id_for_hash (while safely swallowing a missing service) and falling back to the lowered hash preserves existing behavior while enabling canonical project IDs when available. This should make HTTP/WS flows more robust without breaking prior callers.

@Jordonh18
Copy link
Contributor Author

Will fix that duplication now.

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: 3

♻️ Duplicate comments (2)
Server/src/services/tools/manage_gameobject.py (1)

104-109: Good refactoring to centralize boolean coercion.

Successfully replaces the local _coerce_bool helper with the shared utility, addressing the duplication flagged in past reviews.

Server/src/services/tools/manage_prefabs.py (1)

41-51: Excellent refactoring with improved conditional parameter handling.

This successfully addresses the past review comment by using the centralized coerce_bool utility. The pattern of checking if value is not None before adding to params is a good practice—it avoids sending explicit False values when parameters weren't provided.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 993ca32 and 853b153.

📒 Files selected for processing (4)
  • Server/src/services/tools/manage_editor.py (2 hunks)
  • Server/src/services/tools/manage_gameobject.py (2 hunks)
  • Server/src/services/tools/manage_prefabs.py (2 hunks)
  • Server/src/services/tools/utils.py (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 401
File: MCPForUnity/Editor/Clients/Configurators/VSCodeConfigurator.cs:10-18
Timestamp: 2025-11-27T21:09:35.011Z
Learning: VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory: %APPDATA%\Code\User\mcp.json on Windows, ~/Library/Application Support/Code/User/mcp.json on macOS, and ~/.config/Code/User/mcp.json on Linux. This is in addition to workspace-scoped .vscode/mcp.json files.
📚 Learning: 2025-11-05T18:23:12.349Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 368
File: MCPForUnity/UnityMcpServer~/src/resources/menu_items.py:15-15
Timestamp: 2025-11-05T18:23:12.349Z
Learning: In Unity MCP, the `name` parameter in the `mcp_for_unity_resource` decorator is the external API name exposed to MCP clients (LLMs, AI agents). The command string passed to `async_send_command_with_retry` or `async_send_with_unity_instance` (e.g., "get_menu_items") is the internal command identifier that must match the C# side. These are decoupled, allowing external API naming to evolve independently of internal command routing.

Applied to files:

  • Server/src/services/tools/manage_prefabs.py
  • Server/src/services/tools/manage_gameobject.py
  • Server/src/services/tools/manage_editor.py
📚 Learning: 2025-10-13T13:41:00.086Z
Learnt from: JohanHoltby
Repo: CoplayDev/unity-mcp PR: 309
File: MCPForUnity/Editor/Helpers/ServerInstaller.cs:478-508
Timestamp: 2025-10-13T13:41:00.086Z
Learning: In the MCPForUnityTools feature (MCPForUnity/Editor/Helpers/ServerInstaller.cs), the design intentionally forces users to have only one .py file per MCPForUnityTools folder to keep file tracking simple. Package-style tools (subdirectories with __init__.py) are not supported.

Applied to files:

  • Server/src/services/tools/manage_prefabs.py
  • Server/src/services/tools/manage_gameobject.py
  • Server/src/services/tools/manage_editor.py
🧬 Code graph analysis (3)
Server/src/services/tools/manage_prefabs.py (1)
Server/src/services/tools/utils.py (1)
  • coerce_bool (12-24)
Server/src/services/tools/manage_gameobject.py (1)
Server/src/services/tools/utils.py (1)
  • coerce_bool (12-24)
Server/src/services/tools/manage_editor.py (1)
Server/src/services/tools/utils.py (1)
  • coerce_bool (12-24)
🔇 Additional comments (2)
Server/src/services/tools/utils.py (1)

12-24: LGTM! Well-structured boolean coercion utility.

The implementation correctly handles None, boolean, and string inputs, with sensible fallback to Python's truthiness rules for other types. The use of sets for truthy/falsy string matching is efficient.

Server/src/services/tools/manage_editor.py (1)

30-30: Good refactoring to use centralized boolean coercion.

This change successfully addresses the past review comment about duplicated _coerce_bool helpers across multiple files.

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 (1)
Server/src/services/tools/manage_editor.py (1)

13-19: Centralized boolean coercion is good; consider aligning docs with behavior

Using coerce_bool(wait_for_completion) keeps waitForCompletion handling consistent with other tools while still yielding bool | None so the later None-filtering in params continues to work as before.

One small follow‑up: coerce_bool appears to accept a wider range of truthy/falsy string values than just 'true'/'false'. You may want to tweak the parameter description (and/or decorator description) to either:

  • Explicitly document the broader accepted forms, or
  • Clarify that only 'true'/'false' are officially supported, even if additional forms are currently interpreted.

Also applies to: 30-30

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 853b153 and 42648fe.

📒 Files selected for processing (3)
  • Server/src/services/tools/manage_editor.py (2 hunks)
  • Server/src/services/tools/manage_gameobject.py (2 hunks)
  • Server/src/services/tools/manage_prefabs.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • Server/src/services/tools/manage_prefabs.py
  • Server/src/services/tools/manage_gameobject.py
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 401
File: MCPForUnity/Editor/Clients/Configurators/VSCodeConfigurator.cs:10-18
Timestamp: 2025-11-27T21:09:35.011Z
Learning: VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory: %APPDATA%\Code\User\mcp.json on Windows, ~/Library/Application Support/Code/User/mcp.json on macOS, and ~/.config/Code/User/mcp.json on Linux. This is in addition to workspace-scoped .vscode/mcp.json files.
📚 Learning: 2025-11-05T18:23:12.349Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 368
File: MCPForUnity/UnityMcpServer~/src/resources/menu_items.py:15-15
Timestamp: 2025-11-05T18:23:12.349Z
Learning: In Unity MCP, the `name` parameter in the `mcp_for_unity_resource` decorator is the external API name exposed to MCP clients (LLMs, AI agents). The command string passed to `async_send_command_with_retry` or `async_send_with_unity_instance` (e.g., "get_menu_items") is the internal command identifier that must match the C# side. These are decoupled, allowing external API naming to evolve independently of internal command routing.

Applied to files:

  • Server/src/services/tools/manage_editor.py
🧬 Code graph analysis (1)
Server/src/services/tools/manage_editor.py (1)
Server/src/services/tools/utils.py (1)
  • coerce_bool (12-24)
🔇 Additional comments (1)
Server/src/services/tools/manage_editor.py (1)

9-9: Importing coerce_bool from shared utils looks correct

The import path is consistent with other services.* imports and correctly reuses the shared boolean coercion helper.

@dsarno
Copy link
Collaborator

dsarno commented Dec 4, 2025

@Jordonh18 would you mind fixing the merge conflicts? I think @Scriptwonder beat you to the punch on manage_gameobject.py update. Also a couple little notes while you're at it:

  • For an unrecognized string, coerce_bool() falls back to bool(value) — meaning any non-empty unknown string becomes True.
    For “destructive-ish” flags (overwrite/delete), a safer posture is: if value is a str but not in truthy/falsy sets → return default (often None) or raise/return an error. That prevents "disabled" / "nah" / "f" from silently meaning True.

  • finding pyproject.toml by walking parents The mild “best practice” concern is accidentally picking up an unexpected pyproject.toml in a higher-level directory in odd packaging/layout scenarios — that generally only impacts reported version, not runtime behavior.

@dsarno
Copy link
Collaborator

dsarno commented Dec 4, 2025

@Jordonh18 otherwise I tested and reviewed this and looking great, thanks for all the improvements!

@Jordonh18
Copy link
Contributor Author

Yep will look into all of that now! Thanks for the feedback. Fairly new to contributing in general so feels good to get stuck in!

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)
Server/src/services/tools/utils.py (1)

12-14: Consider documenting the exact coercion rules in the docstring

To make future usage unambiguous, consider expanding the docstring to briefly spell out the behavior (None → default, known truthy/falsy strings → True/False, unknown strings → default, everything else → bool(value)). This will help callers choose appropriate default values and avoid surprises.

Server/src/core/telemetry.py (1)

37-63: Version discovery helper looks solid; consider minor polish on search bounds and message

The parent-walk + name check is a nice improvement over a fixed path, and handling both [project] and [tool.poetry] covers common layouts. Two small nits you might consider (optional):

  • To avoid mismatches if the distribution name ever changes, you could reuse PACKAGE_NAME in the error message instead of hard-coding the string:
-    raise FileNotFoundError("pyproject.toml not found for MCPForUnityServer")
+    raise FileNotFoundError(f"pyproject.toml not found for {PACKAGE_NAME}")
  • For unusual monorepo layouts where multiple pyproject.toml files share the same name, walking all the way to filesystem root could still pick up an unexpected parent. In practice this is low-risk, but if it ever bites you, a future refinement could be to stop the search at a known project root (e.g., a detected VCS root or Server/ boundary).

Overall, the helper is correct and robust as written.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42648fe and f72e696.

📒 Files selected for processing (2)
  • Server/src/core/telemetry.py (2 hunks)
  • Server/src/services/tools/utils.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 401
File: MCPForUnity/Editor/Clients/Configurators/VSCodeConfigurator.cs:10-18
Timestamp: 2025-11-27T21:09:35.011Z
Learning: VS Code GitHub Copilot MCP configuration supports mcp.json files placed directly in the Code/User directory: %APPDATA%\Code\User\mcp.json on Windows, ~/Library/Application Support/Code/User/mcp.json on macOS, and ~/.config/Code/User/mcp.json on Linux. This is in addition to workspace-scoped .vscode/mcp.json files.
Learnt from: JohanHoltby
Repo: CoplayDev/unity-mcp PR: 309
File: MCPForUnity/Editor/Helpers/ServerInstaller.cs:478-508
Timestamp: 2025-10-13T13:41:00.086Z
Learning: In the MCPForUnityTools feature (MCPForUnity/Editor/Helpers/ServerInstaller.cs), the design intentionally forces users to have only one .py file per MCPForUnityTools folder to keep file tracking simple. Package-style tools (subdirectories with __init__.py) are not supported.
🪛 Ruff (0.14.7)
Server/src/core/telemetry.py

63-63: Avoid specifying long messages outside the exception class

(TRY003)


75-75: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (2)
Server/src/services/tools/utils.py (1)

8-25: coerce_bool semantics are safe for strings; verify non‑string call sites

The updated logic correctly returns default for unknown strings instead of using bool(value), which avoids accidentally treating arbitrary values like "disabled" as True. However, the fallback to bool(value) for non-string types should be verified at call sites to ensure this behavior aligns with intended usage patterns.

Server/src/core/telemetry.py (1)

66-80: Robust version resolution; just ensure package name alignment is intentional

Using a single PACKAGE_NAME constant for both metadata.version() and the pyproject name check keeps things consistent and makes the fallback behave predictably. The broad except Exception blocks are justified here since MCP_VERSION is computed at import time and server startup should never break due to telemetry version resolution.

Confirm that the distribution name in pyproject.toml (under [project].name or [tool.poetry].name) exactly matches the PACKAGE_NAME constant value in this file, including any hyphens/underscores. If they differ, the fallback will never match and editable/dev installs will always return "unknown".

@Jordonh18
Copy link
Contributor Author

Jordonh18 commented Dec 4, 2025

i believe that's been resolved correctly.

@dsarno
Copy link
Collaborator

dsarno commented Dec 4, 2025

@Jordonh18 Thanks again, good stuff! Let us know if there are any other improvements or features you want to work on.

@dsarno dsarno merged commit bf81319 into CoplayDev:main Dec 4, 2025
1 check passed
@dsarno
Copy link
Collaborator

dsarno commented Dec 4, 2025

@Jordonh18 I gave you a shoutout in our unity-mcp / coplay discord. Thanks again!

https://discord.com/channels/1330955894296543364/1403548315445891192/1446251610513735914

@Jordonh18
Copy link
Contributor Author

thank you!

@Jordonh18 Jordonh18 deleted the feat/code-insiders-autoconfig branch December 5, 2025 01:11
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.

2 participants