Skip to content

Conversation

@Scriptwonder
Copy link
Collaborator

@Scriptwonder Scriptwonder commented Dec 3, 2025

Tested object generation/modification with batch, and it works perfectly! A feature we discussed a long time ago, but finally had an initial tryout at this.

Description: This is a new tool called batch_execute that can aggregate multiple commands together (to a max_number of 25 defined by both the Python server and C# side) and send them at once to achieve a more transparent and efficient (user-side) execution. In the tool description, LLM is explicitly told to work in a batch and sequence way to divide tasks and then process them sequentially.
image
Here is an example using Claude Desktop on Windows:
image

Some notes:
1: The current batching is a custom tool that tries to aggregate all the commands together and send them at once. It does not save tokens, and I doubt it will save many tokens even if we divide the batch into each tool (For example, have the manage_gameobject tool accept multiple parameters about multiple objects to do batch). It would definitely be useful when trying to perform redundant tasks, such as generating hundreds of similar pieces, but I also struggle to think of a way to save or optimize the token beyond the current scope.

2: I tried both VS Copilot and Claude Desktop. Claude Desktop works, but VS Copilot does not due to the nested structure of the batch. Will look into it more, but it is more likely to be a VS Copilot limitation based on previous integration issues back at July.

3: About Multi-thread: The original plan is to implement a multi-threaded option, but this seems to be limited to not only read-only tools, but also only a small portion of them (Multi-thread in Unity in my journey has always been a pain:( ). So I discard the changes of multi-thread and let it run on the main thread as of current moment. Happy to discuss about this.
image

CC'ing @msanatan and @dsarno here, let me know if you have any feedback!

Summary by CodeRabbit

  • New Features

    • Batch command execution tool to run up to 25 commands in a single request.
    • New Tools section in the editor with per-tool toggles, Built-in/Custom grouping, bulk Enable All / Disable All, Rescan, and a tools tab in the main window.
  • Improvements

    • Accepts camelCase and snake_case parameter keys for better compatibility.
    • Tool enablement now persists and tools registered to clients reflect per-tool settings.
  • Removals

    • Removed the Python-based Roslyn runtime compilation tool and its documentation.

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

* Update the .Bat file to include runtime folder
* Fix the inconsistent EditorPrefs variable so the GUI change on Script Validation could cause real change.
String to Int for consistency
Allows users to generate/compile codes during Playmode
Upload the unity_claude_skill that can be uploaded to Claude for a combo of unity-mcp-skill.
1. Fix Original Roslyn Compilation Custom Tool to fit the V8 standard
2. Add a new panel in the GUI to see and toggle/untoggle the tools. The toggle feature will be implemented in the future, right now its implemented here to discuss with the team if this is a good feature to add;
3. Add few missing summary in certain tools
Merge and use the previous PR's solution to solve the windows issue.
Fix the layout problem of manage_script in the panel
To comply with the current server setting
Tested object generation/modification with batch and it works perfectly! We should push and let users test for a while and see

PS: I tried both VS Copilot and Claude Desktop. Claude Desktop works but VS Copilot does not due to the nested structure of batch. Will look into it more.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

Adds a batch command tool and UI/tooling to discover and enable/disable tools. Introduces BatchExecute (editor and server), per-tool enablement preferences and UI, CommandRegistry.InvokeCommandAsync, and supporting editor window, styles, and transport changes.

Changes

Cohort / File(s) Summary
Batch execution (Editor)
MCPForUnity/Editor/Tools/BatchExecute.cs, MCPForUnity/Editor/Tools/BatchExecute.cs.meta
New static BatchExecute tool with HandleCommand(JObject) to accept up to 25 commands, recursively normalize params to camelCase, call CommandRegistry.InvokeCommandAsync, collect per-command success/error results, and return structured SuccessResponse/ErrorResponse.
Batch execution (Server)
Server/src/services/tools/batch_execute.py
New exported batch_execute tool that validates command list and flags (parallel, failFast, maxParallelism), constructs payload, and sends batch_execute to Unity via async transport with retry.
Command invocation helper
MCPForUnity/Editor/Tools/CommandRegistry.cs
Adds public static Task<object> InvokeCommandAsync(string commandName, JObject @params) to invoke registered handlers uniformly for sync/async handlers and return raw results.
Tool discovery & prefs
MCPForUnity/Editor/Services/*
MCPForUnity/Editor/Constants/EditorPrefKeys.cs
ToolMetadata gains AssemblyName, AssetPath, IsBuiltIn; IToolDiscoveryService adds GetEnabledTools/IsToolEnabled/SetToolEnabled; ToolDiscoveryService implements per-tool EditorPrefs, discovery caching, asset path resolution, built-in detection, and summary extraction. New EditorPref keys added.
Editor transport registration
MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs
Tool registration now uses GetEnabledTools() (only enabled tools registered) and logs count.
Editor UI — Tools section
MCPForUnity/Editor/Windows/Components/Tools/*
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.*
New McpToolsSection UXML, USS, C# component and meta files: UI to list Built-in/Custom tools, per-tool toggles, Enable All / Disable All / Rescan actions, persistent foldouts, and summary of tools to register.
Main editor window & tabs
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.*
Adds Tools tab/panel, wiring to load McpToolsSection, tab toolbar, panel switching, panel persistence via EditorPrefs, and helpers to manage open MCP windows. Updates UXML/USS layout.
Minor editor tools/docs/styling
MCPForUnity/Editor/Tools/ManageAsset.cs, .../ManageScript.cs, .../ExecuteMenuItem.cs, .../Prefabs/ManagePrefabs.cs, Common.uss, other metadata files
Accepts snake_case asset_type fallback for asset creation; XML doc edits for several tools; styling additions for tools UI in Common.uss; various .meta guid/metadata updates.
Roslyn runtime tooling removed/updated
CustomTools/RoslynRuntimeCompilation/*
Python runtime_compilation_tool.py and RoslynRuntime.md removed; ManageRuntimeCompilation C# updated to use explicit SuccessResponse/ErrorResponse and adjusted behavior (assembly handling, responses); Sanitize helper removed.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server
    participant BatchExecuteEditor as BatchExecute (Editor)
    participant CommandRegistry
    participant ToolHandler as Command

    Client->>Server: batch_execute RPC (commands, flags)
    Server->>BatchExecuteEditor: send_with_unity_instance("batch_execute", payload)
    BatchExecuteEditor->>BatchExecuteEditor: Validate payload (<=25), normalize params
    loop per command
        BatchExecuteEditor->>CommandRegistry: InvokeCommandAsync(toolName, params)
        CommandRegistry->>ToolHandler: Execute (sync/async)
        ToolHandler-->>CommandRegistry: result / error
        CommandRegistry-->>BatchExecuteEditor: Task result
        BatchExecuteEditor->>BatchExecuteEditor: collect per-command result
    end
    BatchExecuteEditor->>Server: aggregate results (success/failure counts, per-command data)
    Server-->>Client: return batch response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing careful review:
    • BatchExecute: recursive normalization, key conversion edge cases, and async coordination with CommandRegistry.
    • CommandRegistry.InvokeCommandAsync: correctness for both sync and async handlers and exception propagation.
    • ToolDiscoveryService changes: asset-path resolution, EditorPrefs behavior, and built-in detection heuristics.
    • UI wiring: McpToolsSection lifecycle, persistence, and integration into MCPForUnityEditorWindow.
    • Server batch_execute: input validation and transport retry/invocation correctness.

Possibly related PRs

Suggested reviewers

  • msanatan
  • dsarno

Poem

🐰 I hop through batches, keys in a row,
CamelCase carrots all in a row,
Twenty-five hops, commands take flight,
Results return in morning light,
A tidy trail of success and error—hop!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.64% 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 '[FEATURE] Batch Commands' directly reflects the main addition: a new batch_execute tool that enables aggregating and executing multiple commands in sequence. The title is concise, clear, and accurately represents the primary change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 (1)
MCPForUnity/Editor/Tools/BatchExecute.cs (1)

173-203: Consider handling edge cases in ToCamelCase.

The current implementation doesn't explicitly handle edge cases like:

  • Consecutive underscores: "asset__type""assetType" (works due to RemoveEmptyEntries)
  • Leading underscores: "_asset_type""AssetType" (first part is empty, might behave unexpectedly)
  • Trailing underscores: "asset_type_""assetType" (works due to RemoveEmptyEntries)

While most edge cases are handled by StringSplitOptions.RemoveEmptyEntries, leading underscores could produce unexpected capitalization. Consider adding a comment or explicit handling if this is intentional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84f7b85 and 318c824.

⛔ Files ignored due to path filters (1)
  • Server/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • MCPForUnity/Editor/Tools/BatchExecute.cs (1 hunks)
  • MCPForUnity/Editor/Tools/BatchExecute.cs.meta (1 hunks)
  • MCPForUnity/Editor/Tools/ManageAsset.cs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
MCPForUnity/Editor/Tools/BatchExecute.cs (3)
MCPForUnity/Editor/Tools/ManageAsset.cs (2)
  • McpForUnityTool (25-1511)
  • HandleCommand (46-127)
MCPForUnity/Editor/Helpers/McpLog.cs (2)
  • McpLog (7-52)
  • Warn (43-46)
MCPForUnity/Editor/Tools/CommandRegistry.cs (1)
  • CommandRegistry (37-407)
🔇 Additional comments (8)
MCPForUnity/Editor/Tools/BatchExecute.cs (7)

21-24: LGTM: Proper null validation.

The null check for @params is appropriate and provides a clear error message.


26-35: LGTM: Batch size validation is properly enforced.

The code correctly validates that:

  1. The commands array exists and is not empty
  2. The batch size does not exceed the maximum of 25 commands

This aligns with the PR objectives and prevents potential resource exhaustion.


121-135: LGTM: Result aggregation and response handling are well-structured.

The final response correctly:

  1. Determines overall success based on whether any command failed
  2. Includes comprehensive metadata (results, counts, parallel flags)
  3. Returns appropriate response type (SuccessResponse or ErrorResponse with data)

This provides excellent observability for debugging batch operations.


137-161: LGTM: Parameter normalization logic is well-structured.

The recursive normalization correctly handles:

  1. JObject → normalizes all property keys to camelCase
  2. JArray → normalizes all elements
  3. Other tokens → deep clones to preserve immutability

This ensures consistent parameter format across all batched commands.


14-14: Verify AutoRegister = false is intentional and manual registration is configured.

The batch_execute tool is marked with AutoRegister = false, which means it will not be automatically discovered and registered by the CommandRegistry. Confirm that:

  1. This is intentional design rather than an oversight
  2. Manual registration of batch_execute is properly implemented elsewhere in the codebase

93-93: Verify that CommandRegistry.InvokeCommandAsync is defined.

Line 93 calls CommandRegistry.InvokeCommandAsync(toolName, commandParams), but this method is not present in the provided CommandRegistry.cs code snippet. Only GetHandler(string commandName) and ExecuteCommand(string commandName, JObject @params, TaskCompletionSource<string> tcs) are shown. Confirm the method exists and returns a Task<string> or similar awaitable type, otherwise this will fail to compile.


173-203: Potential compatibility issue with AsSpan on .NET Standard 2.0.

Line 198 uses part.AsSpan(1), which is part of the System.Memory API available natively in .NET Standard 2.1+ and .NET Core 2.1+. Unity versions prior to 2021.2 target .NET Standard 2.0, where this API is unavailable in the BCL. This will cause compilation errors unless the project includes the System.Memory NuGet package as a dependency.

If the project targets .NET Standard 2.0 without System.Memory, replace with:

-                builder.Append(char.ToUpperInvariant(part[0]));
-                if (part.Length > 1)
-                {
-                    builder.Append(part.AsSpan(1));
-                }
+                builder.Append(char.ToUpperInvariant(part[0]));
+                if (part.Length > 1)
+                {
+                    builder.Append(part.Substring(1));
+                }
MCPForUnity/Editor/Tools/ManageAsset.cs (1)

166-168: Clarify the necessity of this snake_case fallback.

The inline comment indicates this fallback is for "snake_case payloads from batched commands," but BatchExecute.cs (line 72) already normalizes parameter keys to camelCase via NormalizeParameterKeys before invoking tools. This suggests the fallback might be redundant for batched commands.

Is there another code path where asset_type (snake_case) reaches ManageAsset directly without normalization? If not, consider removing this fallback to avoid maintaining unnecessary compatibility code.

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

🧹 Nitpick comments (14)
MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs (1)

13-15: Doc summary is accurate and helpful

The XML summary accurately reflects the class responsibilities (managing prefab stages and creating prefabs from GameObjects) and improves discoverability in tooling. Optionally, you could mention the supported actions (open_stage, close_stage, save_open_stage, create_from_gameobject) for even clearer API docs, but it’s not required.

MCPForUnity/Editor/Tools/ManageScript.cs (1)

54-55: Consider adding a description to McpForUnityTool

For better MCP client compatibility and tool discovery, consider updating the attribute to include a description argument (e.g., description = "Manage C# scripts (create/read/update/delete/apply edits/validate).").
Based on learnings, all Unity MCP tools should include description in the decorator.

CustomTools/RoslynRuntimeCompilation/ManageRuntimeCompilation.cs (1)

126-126: Consider explicit FileAccess for clarity.

While FileMode.Create defaults to appropriate access flags, explicitly specifying FileAccess.Write and FileShare.None would make the intent clearer and more defensive.

-                using (var stream = new FileStream(dllPath, FileMode.Create))
+                using (var stream = new FileStream(dllPath, FileMode.Create, FileAccess.Write, FileShare.None))
MCPForUnity/Editor/Tools/ExecuteMenuItem.cs (1)

9-13: Move XML summary above the attribute so it reliably binds to the class

To ensure the XML doc comment is emitted for ExecuteMenuItem (and picked up by your built‑in tool metadata extractor), it’s safer to place the /// summary above the [McpForUnityTool] attribute:

/// <summary>
/// Tool to execute a Unity Editor menu item by its path.
/// </summary>
[McpForUnityTool("execute_menu_item", AutoRegister = false)]
public static class ExecuteMenuItem
{
    ...
}

This avoids any ambiguity in how the compiler associates the doc comment.

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

13-71: Solid validation and payload shaping; consider documenting the cross‑language batch size constant

The batch_execute tool’s validation and normalization look good: you enforce a non‑empty list, cap at 25 commands, ensure each item has a string tool and dict params, and shape the payload (commands, parallel, failFast, maxParallelism) to match the Unity BatchExecute expectations. The proxy call via "batch_execute" is consistent with the Unity command registry.

Two small, optional nits:

  • You now have MAX_COMMANDS_PER_BATCH = 25 here and a matching limit on the Unity side. A short comment referencing the Unity counterpart (or a shared config constant if you ever introduce one) would help avoid drift if the limit changes later.
  • Ruff’s TRY003/TRY004 suggestions (ValueError vs TypeError, long messages) are stylistic; given this is user input validation, your current choice of ValueError with descriptive messages is reasonable. Adjust only if you want to strictly satisfy those lints.
MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs (1)

424-425: Registering only enabled tools aligns with the new discovery model

Switching to _toolDiscoveryService.GetEnabledTools() ensures the bridge only registers tools that are currently enabled, which fits the per‑tool enablement preferences added in ToolDiscoveryService. The additional log with tools.Count is also helpful for diagnostics.

If there’s any chance GetEnabledTools() could return null in custom implementations, a defensive fallback to an empty list would avoid a possible NullReferenceException, but with the current in‑repo implementation this looks fine.

MCPForUnity/Editor/Windows/Components/Common.uss (1)

296-363: Tools section USS styles are consistent; one minor style-property nit

The new .tool-* styles (items, tags, descriptions, parameters) and their dark‑theme overrides fit well with the existing layout and color system, and should render cleanly in both themes.

One optional consistency tweak: for .tool-parameters you currently use font-style: italic; while the rest of the file uses -unity-font-style for font styling. Swapping to -unity-font-style: italic; would align with the rest of the USS and Unity’s recommended property naming, but the current rule is likely to work as-is.

Also applies to: 472-485

MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (1)

46-72: Consider moving inline styles to USS.

The marginRight inline styles (lines 51, 58) could be defined in the USS stylesheet for consistency with the rest of the styling approach. The tool-action-button class is already added via UXML, so the AddToClassList calls are redundant but harmless.

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

5-7: Script path & summary caches look correct, but consider broader invalidation.

The added _scriptPathCache and _summaryCache are reasonable optimizations for editor-only reflection and asset lookups. However, InvalidateCache() currently only nulls _cachedTools and leaves these dictionaries intact; if you ever call InvalidateCache() without a domain reload (e.g., future “rescan tools” UX), script moves/renames could leave stale AssetPath or summaries. Consider clearing both caches in InvalidateCache() as well.

Also applies to: 16-17


318-352: Built‑in detection heuristic is reasonable but couples to assembly name and folder layout.

Using either the package root Editor/Tools/ prefix or AssemblyName == "MCPForUnity.Editor" is a pragmatic way to classify built‑ins, but it bakes in a hard‑coded assembly name and directory convention. If you expect future packages or renamed assemblies, consider centralizing these constants (e.g., in a config/constant) to avoid scattering magic strings.


233-236: Consider clearing per‑type/per‑asset caches in InvalidateCache.

InvalidateCache() only nulls _cachedTools. If you ever rely on it to reflect moves/renames or summary changes within the same editor domain, _scriptPathCache and _summaryCache will still serve stale entries. Clearing those dictionaries here would make cache invalidation more complete without affecting current behavior.

MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (3)

3-3: Duplicate using directives can be trimmed.

You now import several namespaces twice (Helpers, Services, Settings, Connection, ClientConfig). This is harmless but noisy; consider removing the duplicates to keep the header clean.

Also applies to: 11-11, 14-20


30-37: New tools section fields and CloseAllWindows utility integrate cleanly.

Adding McpToolsSection and tab/panel fields is straightforward, and CloseAllWindows()’s use of OpenWindows.Where(...).ToArray() avoids collection‑modified‑during‑iteration issues. Note that CloseAllOpenWindows() already performs a similar job (with extra logging), so there’s some overlap—if both are kept, it might be worth documenting their distinct intended callers.

Also applies to: 42-56


195-209: Tools section initial Refresh is appropriate; consider future refresh triggers.

Calling toolsSection.Refresh() right after construction ensures the Tools tab is accurate on first open. If you later add mechanisms to change tools (e.g., dynamic discovery without domain reload), you may want a hook from RefreshAllData() or a dedicated “Rescan” UI (which McpToolsSection already supports) to re‑sync this list.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 318c824 and 51fc4b4.

📒 Files selected for processing (21)
  • CustomTools/RoslynRuntimeCompilation/ManageRuntimeCompilation.cs (17 hunks)
  • CustomTools/RoslynRuntimeCompilation/RoslynRuntime.md (0 hunks)
  • CustomTools/RoslynRuntimeCompilation/runtime_compilation_tool.py (0 hunks)
  • MCPForUnity/Editor/Constants/EditorPrefKeys.cs (1 hunks)
  • MCPForUnity/Editor/Services/IToolDiscoveryService.cs (2 hunks)
  • MCPForUnity/Editor/Services/ToolDiscoveryService.cs (6 hunks)
  • MCPForUnity/Editor/Services/Transport/Transports/WebSocketTransportClient.cs (1 hunks)
  • MCPForUnity/Editor/Tools/CommandRegistry.cs (1 hunks)
  • MCPForUnity/Editor/Tools/ExecuteMenuItem.cs (1 hunks)
  • MCPForUnity/Editor/Tools/ManageScript.cs (2 hunks)
  • MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs (1 hunks)
  • MCPForUnity/Editor/Windows/Components/Common.uss (2 hunks)
  • MCPForUnity/Editor/Windows/Components/Tools.meta (1 hunks)
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (1 hunks)
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs.meta (1 hunks)
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml (1 hunks)
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml.meta (1 hunks)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (6 hunks)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.uss (1 hunks)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.uxml (1 hunks)
  • Server/src/services/tools/batch_execute.py (1 hunks)
💤 Files with no reviewable changes (2)
  • CustomTools/RoslynRuntimeCompilation/RoslynRuntime.md
  • CustomTools/RoslynRuntimeCompilation/runtime_compilation_tool.py
✅ Files skipped from review due to trivial changes (1)
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs.meta
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-10-03T22:11:46.002Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 301
File: docs/CUSTOM_TOOLS.md:54-62
Timestamp: 2025-10-03T22:11:46.002Z
Learning: In Unity MCP, the `description` parameter in the `mcp_for_unity_tool` decorator is technically optional but should always be included as a best practice. Without it, there's a higher chance that MCP clients will not parse the tool correctly. All Unity MCP tools should include the description in the decorator for compatibility.

Applied to files:

  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml
  • MCPForUnity/Editor/Constants/EditorPrefKeys.cs
  • MCPForUnity/Editor/Tools/ExecuteMenuItem.cs
  • MCPForUnity/Editor/Tools/ManageScript.cs
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs
📚 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:

  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml
  • MCPForUnity/Editor/Constants/EditorPrefKeys.cs
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
📚 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:

  • MCPForUnity/Editor/Tools/CommandRegistry.cs
  • MCPForUnity/Editor/Constants/EditorPrefKeys.cs
📚 Learning: 2025-10-13T13:27:23.040Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 316
File: TestProjects/UnityMCPTests/Assets/Tests/EditMode/Resources.meta:1-8
Timestamp: 2025-10-13T13:27:23.040Z
Learning: UnityMcpBridge is a legacy project kept for backwards compatibility; MCPForUnity is the only active Unity plugin project. GUID collisions between UnityMcpBridge and MCPForUnity are acceptable.

Applied to files:

  • MCPForUnity/Editor/Constants/EditorPrefKeys.cs
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml.meta
  • MCPForUnity/Editor/Windows/Components/Tools.meta
  • MCPForUnity/Editor/Services/ToolDiscoveryService.cs
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
📚 Learning: 2025-09-04T01:01:11.927Z
Learnt from: dsarno
Repo: CoplayDev/unity-mcp PR: 260
File: UnityMcpBridge/UnityMcpServer~/src/server_version.txt:1-1
Timestamp: 2025-09-04T01:01:11.927Z
Learning: The UnityMcpBridge project is not maintaining changelogs yet, so don't suggest adding changelog entries for version bumps.

Applied to files:

  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml.meta
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.uss
  • MCPForUnity/Editor/Tools/ManageScript.cs
📚 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/Tools/ManageScript.cs
  • CustomTools/RoslynRuntimeCompilation/ManageRuntimeCompilation.cs
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs
  • MCPForUnity/Editor/Services/ToolDiscoveryService.cs
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
🧬 Code graph analysis (5)
MCPForUnity/Editor/Tools/CommandRegistry.cs (1)
MCPForUnity/Editor/Tools/BatchExecute.cs (2)
  • Task (19-135)
  • JObject (137-151)
MCPForUnity/Editor/Services/IToolDiscoveryService.cs (2)
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (1)
  • IsBuiltIn (268-268)
MCPForUnity/Editor/Services/ToolDiscoveryService.cs (4)
  • ToolMetadata (62-70)
  • ToolMetadata (107-157)
  • IsToolEnabled (79-94)
  • SetToolEnabled (96-105)
CustomTools/RoslynRuntimeCompilation/ManageRuntimeCompilation.cs (2)
MCPForUnity/Editor/Tools/ExecuteMenuItem.cs (1)
  • McpForUnityTool (9-52)
MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs (1)
  • McpForUnityTool (12-277)
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (5)
MCPForUnity/Editor/Services/IToolDiscoveryService.cs (7)
  • List (44-44)
  • List (54-54)
  • ToolMetadata (8-22)
  • ToolMetadata (49-49)
  • InvalidateCache (69-69)
  • IsToolEnabled (59-59)
  • SetToolEnabled (64-64)
MCPForUnity/Editor/Services/ToolDiscoveryService.cs (8)
  • List (19-60)
  • List (72-77)
  • List (159-193)
  • ToolMetadata (62-70)
  • ToolMetadata (107-157)
  • InvalidateCache (233-236)
  • IsToolEnabled (79-94)
  • SetToolEnabled (96-105)
MCPForUnity/Editor/Services/MCPServiceLocator.cs (1)
  • MCPServiceLocator (11-85)
MCPForUnity/Editor/Constants/EditorPrefKeys.cs (1)
  • EditorPrefKeys (7-43)
MCPForUnity/Editor/Tools/ManageGameObject.cs (1)
  • Type (2281-2295)
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (2)
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (4)
  • McpToolsSection (16-269)
  • McpToolsSection (29-34)
  • VisualElement (146-203)
  • Refresh (77-117)
MCPForUnity/Editor/Constants/EditorPrefKeys.cs (1)
  • EditorPrefKeys (7-43)
🪛 Ruff (0.14.7)
Server/src/services/tools/batch_execute.py

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

(TRY003)


37-39: Avoid specifying long messages outside the exception class

(TRY003)


44-44: Prefer TypeError exception for invalid type

(TRY004)


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

(TRY003)


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

(TRY003)


55-55: Prefer TypeError exception for invalid type

(TRY004)


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

(TRY003)

🔇 Additional comments (24)
MCPForUnity/Editor/Tools/ManageScript.cs (1)

27-53: XML summary/remarks split looks good

Separating the Roslyn installation guide into a <remarks> block keeps the <summary> focused and improves IntelliSense/readability without affecting behavior.

CustomTools/RoslynRuntimeCompilation/ManageRuntimeCompilation.cs (3)

22-26: LGTM: Tool registration improved.

The explicit tool name and description enhance discoverability and clarify the tool's purpose.


89-89: Assembly name handling looks correct.

The simplified null-coalescing approach is clean and provides a sensible default.


81-81: LGTM: Consistent response type migration.

The migration to explicit ErrorResponse/SuccessResponse types improves type safety and aligns with the pattern used in other tools like ExecuteMenuItem and ManagePrefabs.

Also applies to: 95-95, 145-145, 211-211, 224-224

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

16-22: New metadata fields and enablement API look consistent with ToolDiscoveryService

AssemblyName, AssetPath, and IsBuiltIn on ToolMetadata match how ExtractToolMetadata populates and uses them, and the new GetEnabledTools / IsToolEnabled / SetToolEnabled members line up with the provided implementation snippets and WebSocket registration flow. No functional issues spotted; the additions should support the tools UI and per‑tool enablement cleanly.

Be aware this is a breaking change for any external implementers of IToolDiscoveryService, but within this package the surface looks coherent.

Also applies to: 51-64

MCPForUnity/Editor/Tools/CommandRegistry.cs (1)

251-279: Unified async invocation helper is correctly wired for both sync and async handlers

InvokeCommandAsync cleanly abstracts over sync vs async handlers: it reuses GetHandlerInfo, validates the presence of the appropriate delegate, and returns either the async handler task directly or Task.FromResult for sync results. This matches the existing ExecuteCommand branching and provides a suitable foundation for batch composition (as used by BatchExecute).

No changes needed here.

MCPForUnity/Editor/Windows/Components/Tools.meta (1)

2-4: Folder meta update looks fine

The updated GUID and folderAsset: yes with a standard DefaultImporter block are consistent with a normal folder meta. No issues anticipated from this change.

MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml.meta (1)

2-2: UXML meta now targets the built‑in importer as expected

The GUID update and ScriptedImporter.script pointing to the built‑in UXML importer look correct for a *.uxml asset. This should integrate cleanly with the new Tools UI component without functional side effects.

Also applies to: 10-10

MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.uxml (1)

1-15: LGTM!

The UXML structure is well-organized with clear element naming that aligns with the corresponding C# controller (McpToolsSection.cs). The layout follows Unity UIElements conventions and provides appropriate semantic structure for the Tools section.

MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.uxml (1)

2-14: LGTM!

The tabbed layout implementation is clean. The Settings tab defaults to active (value="true") while the Tools panel is correctly hidden by default (class="hidden"). The structure properly supports panel switching via the C# controller.

MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.uss (1)

20-37: LGTM!

The new style rules are well-structured. The .hidden class using display: none is the correct approach for panel visibility toggling, and the tab toolbar styling with flex-grow: 1 on buttons ensures even distribution.

MCPForUnity/Editor/Constants/EditorPrefKeys.cs (1)

28-30: LGTM!

The new EditorPrefs key constants follow the established naming conventions. The prefix keys correctly end with . to support dynamic key construction for per-tool preferences.

MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (5)

77-117: LGTM!

The Refresh method correctly handles tool discovery, sorting, and UI state management. The sorting logic (built-in first, then alphabetical) provides a consistent user experience, and edge cases (no tools) are properly handled.


119-144: LGTM!

The BuildCategory method properly persists foldout state using EditorPrefs. The early return for empty tool lists is a good optimization.


146-203: LGTM!

The CreateToolRow method creates a well-structured UI for each tool with appropriate metadata display. The toggle correctly syncs with the discovery service, and the tags provide useful visual indicators for tool behavior.


205-235: LGTM!

The state management is well-implemented. Using SetValueWithoutNotify prevents callback loops during bulk operations, and deferring the summary update until after all toggles are processed is efficient.


237-269: LGTM!

The helper methods are concise and well-implemented. The null-safe IsBuiltIn check and the clear summary text formatting provide good UX.

MCPForUnity/Editor/Services/ToolDiscoveryService.cs (4)

72-77: GetEnabledTools behavior is consistent with new IsToolEnabled API.

GetEnabledTools() correctly delegates to DiscoverAllTools() and filters using IsToolEnabled, so all consumers (e.g., transport registration) will respect the per‑tool EditorPrefs state without duplicating preference logic.


125-150: Extended ToolMetadata population (assembly, asset path, built‑in flag, summary) is coherent.

Adding AssemblyName, AssetPath, IsBuiltIn, and optional summary override gives the UI richer, source‑aware metadata. The flow—populate metadata, compute IsBuiltIn, then optionally override Description from XML summary—reads clearly and should be easy to extend.


268-316: Asset path resolution is robust for typical editor usage.

ResolveScriptAssetPath handles null, caches per Type, and safely logs & returns null on reflection/asset database issues. The FindAssets filter using type.Name t:MonoScript plus class comparison is a good compromise between correctness and performance for editor code.


354-404: Summary extraction is carefully scoped; minor robustness thoughts.

The XML <summary> regex with a class‑specific pattern plus a fallback generic summary match is a nice touch, and caching by AssetPath prevents repeated parsing. One small robustness improvement would be to short‑circuit if Regex.Match throws for malformed patterns (e.g., future class names or attributes), but given the try/catch and warning log, current behavior is acceptable.

MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (3)

131-155: Panel/container wiring and tools section initialization are robust and fail fast.

Querying settings-panel, tools-panel, and the corresponding *-container elements and exiting early with clear error logs if they’re missing makes UXML issues easy to diagnose. The tools section is only instantiated when its UXML loads, and you log a warning otherwise, which degrades gracefully. Adding the settings/connection/clientConfig roots into settings-container matches the new panel separation.

Also applies to: 163-165, 178-180, 191-193, 195-209


267-316: Tab setup correctly guards against both tabs being off and restores saved state.

SetupTabs() un‑hides both panels, wires value‑changed callbacks that prevent both toggles being false, and restores the last active panel from EditorPrefs.EditorWindowActivePanel. The use of SetValueWithoutNotify avoids infinite callback loops when you coerce a toggle back on.


318-336: SwitchPanel cleanly syncs visibility, toggles, and persisted state.

The SwitchPanel method centralizes panel visibility (DisplayStyle.Flex/None), uses null‑safe access for panels/toggles, and immediately updates EditorPrefs with the new ActivePanel. This should make tab behavior predictable across sessions.

This reverts commit 51fc4b4, reversing
changes made to 318c824.
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