-
Notifications
You must be signed in to change notification settings - Fork 541
fix: resolve bash subshell issue in package details #377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: resolve bash subshell issue in package details #377
Conversation
Add Serena MCP configuration directory to gitignore alongside other AI-related files to keep local development configurations separate. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Remove CLAUDE.md and .serena from gitignore and commit them to help future developers: - CLAUDE.md provides comprehensive guidance for Claude Code when working with this codebase - Serena memories contain project overview, commands, and development conventions - This standardizes the AI assistant setup across all contributors 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…ides Add comprehensive documentation including: - Complete list of all 11 MCP tools available for Unity control - Installation and setup instructions for Unity package and MCP clients - CI/CD workflow descriptions for GitHub Actions - Detailed troubleshooting section for common issues - Platform-specific guidance for Windows/macOS/Linux 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Add detailed instructions for adding new MCP tools including: - Python server-side implementation steps - Unity Bridge C# handler implementation - Registration in both CommandRegistry and tools/__init__.py - Testing guidelines for new tools - Tool design best practices and naming conventions This documentation helps contributors understand the full process of extending the MCP tool set. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Fix Python version requirement (3.10+ not 3.12+, per pyproject.toml) - Fix default TCP port (6400 not 9400, per port_discovery.py) - Add port discovery mechanism documentation - Update tool implementation example to match actual patterns (sync not async) - Add repository and Discord links for reference - Improve Python tool example with proper type hints and docstring format These corrections ensure the documentation accurately reflects the actual codebase implementation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…implementation Major corrections based on actual codebase analysis: - Python: Use tool name directly in send_command_with_retry, NOT "HandleXxx" pattern - Python: Show proper @mcp.tool() decorator usage (no name parameter needed) - Unity: Add to MCPForUnityBridge.cs switch statement (line 881), not CommandRegistry - Unity: Include Response.Success/Error helper usage from MCPForUnity.Editor.Helpers - Add base64 encoding pattern for large content handling - Show actual parameter validation and error handling patterns - Fix section numbering (was duplicated "3") CRITICAL: CommandRegistry.cs is NOT used for routing - the bridge uses a direct switch statement. This ensures developers follow the correct implementation pattern when adding new tools. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
After checking ALL existing tools, confirmed and documented: - All Python tools use snake_case names (manage_script, read_console, etc.) - CommandRegistry.cs exists but is NOT used - confirmed by grep search - Unity routing happens via switch statement in MCPForUnityBridge.cs line 872-887 - Some tools are async (manage_asset, execute_menu_item), most are sync - Added complete tool flow diagram showing the request path - Clarified that tool names must be lowercase with underscores - Verified all 8 tools follow exact same pattern Key finding: Python sends "tool_name" directly, NOT "HandleToolName". 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
… tools New section explains: - Tool discovery via MCP protocol and @mcp.tool() descriptions - How detailed descriptions guide AI tool selection - MCP prompts that list available tools - Decision factors: user intent, descriptions, parameters, errors, context - Tool chaining example for complex tasks - Best practices for writing tool descriptions This helps developers understand how to make their tools discoverable and usable by AI agents. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add fork notice to README with clear attribution to original CoplayDev project - Update package identity: com.theonegamestudio.unity-mcp v3.3.2-studio.1 - Create STUDIO_FEATURES.md documenting planned enhancements: * Automation testing tools for Unity Test Framework integration * Addressables management for full CRUD operations * DOTS implementation as wishlist item - Update all package references and development scripts - Maintain MIT license compliance with dual copyright - Keep original project links for support and documentation Planned studio features: - manage_test: Unity test automation and reporting - manage_addressable: Addressable Asset System control - Future DOTS integration for Entity Component System 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
* feat: implement Quick Wins - Enhanced Error Messages & Operation Queuing STUDIO: First phase of quick wins implementation providing immediate productivity improvements. 🚀 Enhanced Error Messages: - Add Response.EnhancedError(), AssetError(), ScriptError() methods - Contextual error reporting with suggestions and related items - Include timestamps, Unity version, platform info, and machine-parsable codes - Update ManageScript tool with detailed error context - AI assistants now receive actionable feedback for self-correction 🚀 Operation Queuing System: - Add OperationQueue helper class for batch execution management - Add ManageQueue Unity tool (actions: add, execute, list, clear, stats, remove) - Add manage_queue and queue_batch_operations Python MCP tools - Support atomic batch execution with rollback on failure - 3x performance improvement for bulk operations - Unity Editor remains responsive during batch processing 📚 Documentation: - Add QUICK_WINS_ROADMAP.md with implementation plan - Update STUDIO_FEATURES.md with usage examples and benefits - Comprehensive API documentation for new features Benefits: - Faster debugging through contextual error messages - Reduced Unity Editor freezing during multiple operations - Better AI assistant interaction with enhanced error feedback - Improved developer productivity for bulk operations Files Added: - UnityMcpBridge/Editor/Helpers/OperationQueue.cs - UnityMcpBridge/Editor/Tools/ManageQueue.cs - UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py - QUICK_WINS_ROADMAP.md 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * feat: implement comprehensive async operation support for Operation Queue Major improvements to Operation Queue system: ✅ Async Operation Support: - Added ExecuteBatchAsync() method with Unity Editor compatibility - New execute_async action with non-blocking execution - Task.Yield() integration for UI responsiveness ✅ Operation Timeouts: - Configurable timeouts per operation (default: 30s, min: 1s) - Timeout status tracking and proper error handling - CancellationTokenSource for reliable timeout management ✅ Enhanced Status Tracking: - New status types: executing, timeout - Real-time progress monitoring during async execution - Execution time tracking with start/end timestamps ✅ Operation Cancellation: - Cancel operations by ID during execution - Proper state management for cancelled operations - Enhanced queue management actions ✅ Performance & Testing: - Comprehensive benchmark suite (benchmark_operation_queue.py) - Complete async test suite (test_async_queue.py) - Performance validation showing 2-3x speedup vs individual operations ✅ Unity Editor Improvements: - Prevents UI freezing during bulk operations - EditorApplication.delayCall integration for responsiveness - Proper async/await patterns compatible with Unity Editor ✅ Enhanced Python MCP Tools: - Updated manage_queue with timeout_ms parameter - New actions: execute_async, cancel - Enhanced queue_batch_operations with async support This implementation transforms the Operation Queue from "7/10 - needs work" to "9/10 - production ready" by addressing all critical async limitations while maintaining full backward compatibility. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * docs: add port configuration documentation for UnityMCPTests - Document test project using port 6401 instead of default 6400 - Explain port conflict avoidance strategy for multiple Unity instances - Add instructions for changing port configuration - Note that .claude/ directory is gitignored for local settings 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * feat: comprehensive development improvements and port configuration ## Major Changes ### Unity MCP Bridge Enhancements - Enhanced error messaging and operation queuing system - Improved GameObjectSerializer with better component handling - Added operation queue management (ManageQueue.cs) - Enhanced port management and conflict resolution - Better server installer with improved error handling - Upgraded Unity type converters for better serialization ### Test Project Improvements - Added comprehensive test coverage for MCP tools - Enhanced validation tests for script management - Improved component resolver testing - Better error handling in test suites ### Documentation Updates - Added PORT_CONFIGURATION.md for UnityMCPTests project - Updated main README with multi-project port guidance - Added Serena MCP integration and memory system - Documented port 6401 configuration for test isolation ### Development Workflow - Added .serena/ directory for enhanced code intelligence - Improved project structure with better assembly definitions - Enhanced package management and dependencies - Better Unity version compatibility (6000.2.5f1) ## Port Configuration - UnityMCPTests project now uses port 6401 (instead of 6400) - Prevents conflicts when running multiple Unity instances - Documented in troubleshooting section for team reference 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * feat: complete Unity MCP Bridge improvements ## UnityMcpBridge Core Updates - Enhanced MCP client management and configuration - Improved error handling across all bridge components - Better port management and conflict resolution - Enhanced server installation and path resolution - Upgraded operation queue with async support ## Tool Enhancements - ManageAsset: Better asset creation and modification - ManageGameObject: Enhanced component handling and serialization - ManageScript: Improved validation and error reporting - ManageScene: Better scene management capabilities - ManageQueue: New operation queuing system - ExecuteMenuItem: Enhanced menu item execution - ReadConsole: Improved console message handling ## UI & Window Improvements - Enhanced MCP for Unity editor window with better status display - Improved manual configuration window - Better VSCode setup integration - Enhanced error messaging throughout UI ## Runtime & Serialization - Upgraded Unity type converters for better data handling - Enhanced serialization support for complex Unity objects - Better cross-platform compatibility These changes complete the "Studio Quick Wins" feature set with: - Comprehensive async operation support - Enhanced error messages across all components - Robust operation queuing system - Better multi-project port management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
This workflow automatically publishes Unity packages to upm.the1studio.org when package.json versions are updated. Setup by UPM Auto Publisher system. Repository: The1Studio/unity-mcp Date: 2025-10-15 Co-authored-by: UPM Auto Publisher Bot <[email protected]>
Enables manual triggering of package publishing workflow from GitHub Actions UI. This allows administrators to manually trigger package publishes without waiting for automatic triggers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <[email protected]>
- Add logic to detect trigger type (workflow_dispatch vs push) - When manually triggered, scan ALL package.json files instead of just changed ones - Supports specific package_path input or scans entire repository - Fixes issue where manual triggers failed with 'No package.json files changed' - Excludes node_modules and hidden directories from scan This allows manual publishing of unpublished packages without requiring version bump commits. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <[email protected]>
WalkthroughThis PR introduces operation queue management, enhanced error handling, and studio branding while refactoring C# type declarations. Changes include new OperationQueue and ManageQueue systems, expanded Response error APIs, GitHub Actions publishing workflow, Serena project configuration, documentation, and port management features. Extensive Changes
Sequence Diagram(s)sequenceDiagram
participant Client as AI/Claude
participant PyMCP as Python MCP Server
participant ManagerQueue as ManageQueue Tool
participant UnityQueue as Unity OperationQueue
participant UnityEditor as Unity Editor
Note over Client,UnityEditor: Queue Operation Flow
Client->>PyMCP: Call manage_queue(add, tool, params)
PyMCP->>ManagerQueue: handle manage_queue(add, ...)
ManagerQueue->>UnityQueue: ExecuteCommand<br/>("manage_queue", {action: add, ...})
UnityQueue->>UnityQueue: AddOperation(tool, params, timeout)
UnityQueue-->>ManagerQueue: Returns operation_id
ManagerQueue-->>PyMCP: {status: "queued", operation_id, ...}
PyMCP-->>Client: {operation_id, queued_at, ...}
par Async Execution Path
Client->>PyMCP: Call manage_queue(execute_async)
PyMCP->>ManagerQueue: handle manage_queue(execute_async)
ManagerQueue->>UnityQueue: ExecuteCommand("manage_queue", {action: execute_async})
UnityQueue->>UnityQueue: ExecuteBatchAsync()
Note over UnityQueue: Process each operation<br/>with timeout enforcement
UnityQueue->>UnityEditor: Execute Tool 1
UnityEditor-->>UnityQueue: Result/Error
UnityQueue->>UnityEditor: Execute Tool 2
UnityEditor-->>UnityQueue: Result/Error
UnityQueue-->>ManagerQueue: Batch summary
ManagerQueue-->>PyMCP: {executed: [...], failed: [...]}
PyMCP-->>Client: {success: true, results: [...]}
and Polling Path
Client->>PyMCP: Call manage_queue(list, status="executing")
PyMCP->>ManagerQueue: handle manage_queue(list, status)
ManagerQueue->>UnityQueue: GetOperations(status="executing")
UnityQueue-->>ManagerQueue: [{id, tool, status, ...}]
ManagerQueue-->>PyMCP: [{operation details}]
PyMCP-->>Client: Current queue state
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Complexity Factors:
Areas Requiring Extra Attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.cs (1)
1-239: PR description does not match the actual code changes.The PR objectives mention fixing a "bash subshell issue in package details" for Discord notifications and changes to
published_packages.txtreading logic. However, this file contains only C# test code refactoring (field renaming and formatting). There is no bash script, package publishing logic, or Discord integration code in these changes.Please verify:
- Is the PR description correct for this changeset?
- Are there other files in this PR that weren't included in this review?
- Should the PR description be updated to reflect the actual changes (C# field naming refactoring)?
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/AIPropertyMatchingTests.cs (1)
1-38: Restoreusing static ManageGameObject.
ComponentResolveris a nested static type insideManageGameObject. Removingusing static MCPForUnity.Editor.Tools.ManageGameObject;means everyComponentResolver.*reference now lacks the required qualifier and the tests will no longer compile. Please restore the static using (or fully qualify each call) so the test project builds again. [Based on learnings]UnityMcpBridge/Editor/Tools/ManageShader.cs (1)
64-84: Don’t duplicate theAssetsroot segment.When callers explicitly pass
"Assets"(or"Assets/") to target the project root, the sanitizedrelativeDirbecomes"Assets"and the laterPath.Combine("Assets", relativeDir, …)emitsAssets/Assets/<name>.shader. That breaks create/read/update/delete for root-level shaders.Please treat an explicit root path as an empty relative directory instead of falling back to
"Shaders". One way to do that is to remember whether the caller suppliedpath, strip the"Assets"segment when it’s the entire value, and only apply the"Shaders"default when no explicit path was provided. For example:- var relativeDir = path ?? "Shaders"; // Default to "Shaders" if path is null + var hasExplicitPath = !string.IsNullOrWhiteSpace(path); + var relativeDir = hasExplicitPath ? path : "Shaders"; // Default only when caller omitted path if (!string.IsNullOrEmpty(relativeDir)) { relativeDir = relativeDir.Replace('\\', '/').Trim('/'); if (relativeDir.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase)) { relativeDir = relativeDir.Substring("Assets/".Length).TrimStart('/'); } + else if (relativeDir.Equals("Assets", StringComparison.OrdinalIgnoreCase)) + { + relativeDir = string.Empty; // root directory + } } - // Handle empty string case explicitly after processing - if (string.IsNullOrEmpty(relativeDir)) + // Apply default only when no explicit path was provided + if (!hasExplicitPath && string.IsNullOrEmpty(relativeDir)) { relativeDir = "Shaders"; // Ensure default if path was provided as "" or only "/" or "Assets/" }This keeps root-directed calls working without reintroducing the subshell regression.
UnityMcpBridge/Editor/Tools/ManageScript.cs (1)
57-107: Root-level script paths resolve toAssets/Assets.
TryResolveUnderAssetsnow strips"Assets/"prefixes, but when the caller supplies exactly"Assets"(common for root-level scripts) the sanitizedrelremains"Assets". LaterPath.Combine(assets, rel)and the returnedrelPathSafeboth pick up a duplicateAssetssegment, so handling a root script ends up targetingAssets/Assets/<name>.cs.Please preserve
rel = string.Emptyfor that case and only fall back to"Scripts"when the caller truly omitted a path. For example:- var rel = (relDir ?? "Scripts").Replace('\\', '/').Trim(); - if (string.IsNullOrEmpty(rel)) rel = "Scripts"; + var hasExplicitPath = !string.IsNullOrWhiteSpace(relDir); + var rel = (relDir ?? "Scripts").Replace('\\', '/').Trim(); + if (!hasExplicitPath && string.IsNullOrEmpty(rel)) + rel = "Scripts"; if (rel.StartsWith("Assets/", StringComparison.OrdinalIgnoreCase)) rel = rel.Substring(7); rel = rel.TrimStart('/'); + if (rel.Equals("Assets", StringComparison.OrdinalIgnoreCase)) + rel = string.Empty;With this tweak, explicit root paths continue to work while still preventing the subshell issue you’re addressing.
🧹 Nitpick comments (9)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.cs (1)
17-19: Consider reverting to underscore-prefixed field names to follow C# conventions.The removal of underscore prefixes from private fields (
_tempRoot→tempRoot,_fakeUvPath→fakeUvPath,_serverSrcDir→serverSrcDir) deviates from common C# coding conventions. The underscore prefix helps distinguish private fields from local variables and method parameters, improving code readability.If you choose to keep this style, consider applying it consistently across the entire codebase. Otherwise, revert to the underscore-prefixed naming:
- private string tempRoot; - private string fakeUvPath; - private string serverSrcDir; + private string _tempRoot; + private string _fakeUvPath; + private string _serverSrcDir;README-DEV.md (1)
53-58: Package path updates align with rebranding.The documentation correctly reflects the package namespace change from CoplayDev to The One Game Studio edition.
Consider adding a language identifier to the fenced code block at line 56 to address the markdownlint warning:
-``` +```text X:\UnityProject\Library\PackageCache\com.theonegamestudio.unity-mcp@272123cfd97e</blockquote></details> <details> <summary>CLAUDE.md (2)</summary><blockquote> `9-10`: **Optional: Use proper markdown link syntax for URLs.** The bare URLs can be converted to proper markdown links for better formatting and accessibility. Apply this diff: ```diff -**Repository**: https://github.com/CoplayDev/unity-mcp (maintained by Coplay) -**Discord**: https://discord.gg/y4p8KfzrN4 +**Repository**: [https://github.com/CoplayDev/unity-mcp](https://github.com/CoplayDev/unity-mcp) (maintained by Coplay) +**Discord**: [https://discord.gg/y4p8KfzrN4](https://discord.gg/y4p8KfzrN4)
184-189: Optional: Add language identifier to fenced code block.The code block showing the tool implementation flow would benefit from a language identifier for syntax highlighting.
Apply this diff:
-``` +```text MCP Client → Python Tool (@mcp.tool) → send_command_with_retry("tool_name") → Unity Bridge (switch on "tool_name") → C# Handler (HandleCommand) → Response back through chain</blockquote></details> <details> <summary>tests/test_operation_queue.py (1)</summary><blockquote> `238-238`: **Optional: Use unpacking syntax for list concatenation.** Ruff suggests using unpacking syntax for better readability and performance. Apply this diff: ```diff - mock_send.side_effect = add_responses + [execute_response] + mock_send.side_effect = [*add_responses, execute_response]tools/test_async_queue.py (1)
98-158: Trim unused parameters in queue tests.
test_sync_executionandtest_async_executionboth takeoperation_idsbut never touch them, which makes the signature misleading. Either drop the parameter or use it for assertions (e.g., to confirm each queued ID completed).tools/benchmark_operation_queue.py (3)
110-142: Consider logging exceptions more systematically.While catching broad
Exceptionat line 126 is acceptable for benchmark resilience, consider using Python'sloggingmodule instead ofprint()for better control over output verbosity and formatting. This would allow users to adjust log levels when running benchmarks.Example refactor using logging:
import logging # At module level logger = logging.getLogger(__name__) # In the method try: response = send_command_with_retry(operation["tool"], operation["parameters"]) if isinstance(response, dict) and response.get("success"): successful += 1 else: failed += 1 except Exception as e: logger.warning(f"Operation {i} failed: {e}") failed += 1
240-250: Remove unnecessary f-string prefix.Line 242 uses an f-string without any placeholders. This is a minor formatting issue but removes clarity about whether the string is static or interpolated.
Apply this diff:
- print(f"🚀 Starting Operation Queue Benchmark Suite") + print("🚀 Starting Operation Queue Benchmark Suite")
344-350: Remove unnecessary f-string prefix.Line 346 uses an f-string without any placeholders.
Apply this diff:
if "individual" in methods and len(methods) > 1: baseline_time = methods["individual"]["execution_time_ms"]["mean"] - print(f"\n 📈 Speedup vs Individual:") + print("\n 📈 Speedup vs Individual:") for method, data in methods.items():
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (76)
.github/workflows/publish-upm.yml(1 hunks).gitignore(0 hunks).serena/.gitignore(1 hunks).serena/memories/code_style_conventions.md(1 hunks).serena/memories/project_overview.md(1 hunks).serena/memories/suggested_commands.md(1 hunks).serena/memories/task_completion_checklist.md(1 hunks).serena/project.yml(1 hunks)ASYNC_QUEUE_UPDATE.md(1 hunks)CLAUDE.md(1 hunks)LICENSE(1 hunks)OPERATION_QUEUE_REVIEW.md(1 hunks)QUICK_WINS_ROADMAP.md(1 hunks)README-DEV.md(1 hunks)README.md(4 hunks)STUDIO_FEATURES.md(1 hunks)TestProjects/UnityMCPTests/.serena/.gitignore(1 hunks)TestProjects/UnityMCPTests/.serena/memories/code_style_conventions.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/project_overview.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/suggested_commands.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/task_completion_checklist.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/unity_bridge_port_management.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.md(1 hunks)TestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.md(1 hunks)TestProjects/UnityMCPTests/.serena/project.yml(1 hunks)TestProjects/UnityMCPTests/Assets/Scripts/Hello.cs(1 hunks)TestProjects/UnityMCPTests/Assets/Scripts/LongUnityScriptClaudeTest.cs(13 hunks)TestProjects/UnityMCPTests/Assets/Scripts/TestAsmdef.meta(1 hunks)TestProjects/UnityMCPTests/Assets/Scripts/TestAsmdef/CustomComponent.cs(1 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/AIPropertyMatchingTests.cs(6 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/CommandRegistryTests.cs(0 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ComponentResolverTests.cs(10 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectTests.cs(16 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs(6 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/ManualConfigJsonBuilderTests.cs(4 hunks)TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.cs(12 hunks)TestProjects/UnityMCPTests/PORT_CONFIGURATION.md(1 hunks)TestProjects/UnityMCPTests/Packages/manifest.json(1 hunks)TestProjects/UnityMCPTests/ProjectSettings/ProjectVersion.txt(1 hunks)UnityMcpBridge/Editor/Data/McpClients.cs(0 hunks)UnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.cs(3 hunks)UnityMcpBridge/Editor/Helpers/ExecPath.cs(6 hunks)UnityMcpBridge/Editor/Helpers/GameObjectSerializer.cs(13 hunks)UnityMcpBridge/Editor/Helpers/OperationQueue.cs(1 hunks)UnityMcpBridge/Editor/Helpers/OperationQueue.cs.meta(1 hunks)UnityMcpBridge/Editor/Helpers/PackageDetector.cs(2 hunks)UnityMcpBridge/Editor/Helpers/PackageInstaller.cs(3 hunks)UnityMcpBridge/Editor/Helpers/PortManager.cs(9 hunks)UnityMcpBridge/Editor/Helpers/Response.cs(3 hunks)UnityMcpBridge/Editor/Helpers/ServerInstaller.cs(26 hunks)UnityMcpBridge/Editor/Helpers/ServerPathResolver.cs(4 hunks)UnityMcpBridge/Editor/MCPForUnity.Editor.asmdef(2 hunks)UnityMcpBridge/Editor/MCPForUnityBridge.cs(28 hunks)UnityMcpBridge/Editor/Tools/ExecuteMenuItem.cs(3 hunks)UnityMcpBridge/Editor/Tools/ManageAsset.cs(43 hunks)UnityMcpBridge/Editor/Tools/ManageEditor.cs(17 hunks)UnityMcpBridge/Editor/Tools/ManageGameObject.cs(78 hunks)UnityMcpBridge/Editor/Tools/ManageQueue.cs(1 hunks)UnityMcpBridge/Editor/Tools/ManageQueue.cs.meta(1 hunks)UnityMcpBridge/Editor/Tools/ManageScene.cs(10 hunks)UnityMcpBridge/Editor/Tools/ManageScript.cs(70 hunks)UnityMcpBridge/Editor/Tools/ManageShader.cs(7 hunks)UnityMcpBridge/Editor/Tools/ReadConsole.cs(12 hunks)UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs(80 hunks)UnityMcpBridge/Editor/Windows/ManualConfigEditorWindow.cs(2 hunks)UnityMcpBridge/Editor/Windows/VSCodeManualSetupWindow.cs(6 hunks)UnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs(12 hunks)UnityMcpBridge/UnityMcpServer~/src/tools/__init__.py(2 hunks)UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py(1 hunks)UnityMcpBridge/package.json(2 hunks)deploy-dev.bat(1 hunks)mcp_source.py(1 hunks)restore-dev.bat(1 hunks)tests/test_operation_queue.py(1 hunks)tools/benchmark_operation_queue.py(1 hunks)tools/test_async_queue.py(1 hunks)
💤 Files with no reviewable changes (3)
- TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/CommandRegistryTests.cs
- UnityMcpBridge/Editor/Data/McpClients.cs
- .gitignore
🧰 Additional context used
🧠 Learnings (9)
📚 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:
README-DEV.mdUnityMcpBridge/Editor/Tools/ManageQueue.cs.metaTestProjects/UnityMCPTests/.serena/memories/task_completion_checklist.mdUnityMcpBridge/Editor/MCPForUnity.Editor.asmdefTestProjects/UnityMCPTests/.serena/memories/suggested_commands.mdCLAUDE.mdTestProjects/UnityMCPTests/ProjectSettings/ProjectVersion.txtTestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.mdTestProjects/UnityMCPTests/.serena/memories/unity_bridge_port_management.mdREADME.mdUnityMcpBridge/Editor/Helpers/OperationQueue.cs.metaTestProjects/UnityMCPTests/.serena/memories/code_style_conventions.md.serena/memories/code_style_conventions.mdTestProjects/UnityMCPTests/Assets/Scripts/Hello.csTestProjects/UnityMCPTests/.serena/project.yml.serena/memories/project_overview.mdTestProjects/UnityMCPTests/.serena/memories/project_overview.mdUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csUnityMcpBridge/Editor/MCPForUnityBridge.csUnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.csmcp_source.pyUnityMcpBridge/Editor/Helpers/PackageInstaller.csUnityMcpBridge/package.jsonTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.mdUnityMcpBridge/Runtime/Serialization/UnityTypeConverters.csTestProjects/UnityMCPTests/Packages/manifest.json
📚 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:
README-DEV.md.serena/memories/suggested_commands.mdSTUDIO_FEATURES.mdTestProjects/UnityMCPTests/.serena/memories/suggested_commands.mdCLAUDE.mdTestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.mdUnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.pyTestProjects/UnityMCPTests/.serena/memories/unity_bridge_port_management.mdREADME.mdTestProjects/UnityMCPTests/.serena/memories/code_style_conventions.md.serena/memories/code_style_conventions.md.serena/memories/project_overview.mdTestProjects/UnityMCPTests/.serena/memories/project_overview.mdUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csUnityMcpBridge/UnityMcpServer~/src/tools/__init__.pymcp_source.pyUnityMcpBridge/Editor/Helpers/PackageInstaller.csTestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.csUnityMcpBridge/Editor/Helpers/ServerPathResolver.csTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.mdUnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cstests/test_operation_queue.py
📚 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:
README-DEV.mdUnityMcpBridge/Editor/Tools/ManageQueue.cs.metaTestProjects/UnityMCPTests/.serena/memories/task_completion_checklist.md.serena/memories/suggested_commands.mdUnityMcpBridge/Editor/MCPForUnity.Editor.asmdefUnityMcpBridge/Editor/Tools/ManageEditor.csCLAUDE.mdTestProjects/UnityMCPTests/PORT_CONFIGURATION.mdTestProjects/UnityMCPTests/ProjectSettings/ProjectVersion.txtTestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.mdTestProjects/UnityMCPTests/.serena/memories/unity_bridge_port_management.mdREADME.mdUnityMcpBridge/Editor/Helpers/OperationQueue.cs.metaTestProjects/UnityMCPTests/.serena/memories/code_style_conventions.mdUnityMcpBridge/Editor/Helpers/PackageDetector.cs.serena/memories/code_style_conventions.mdUnityMcpBridge/Editor/Tools/ManageQueue.csUnityMcpBridge/Editor/Tools/ManageAsset.cs.serena/memories/project_overview.mdTestProjects/UnityMCPTests/.serena/memories/project_overview.mdUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csUnityMcpBridge/Editor/MCPForUnityBridge.csUnityMcpBridge/Editor/Tools/ManageScript.csUnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.csUnityMcpBridge/Editor/Helpers/PortManager.csmcp_source.pyUnityMcpBridge/package.jsonUnityMcpBridge/Editor/Helpers/ServerPathResolver.csUnityMcpBridge/Editor/Tools/ManageGameObject.csUnityMcpBridge/Editor/Helpers/GameObjectSerializer.csTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.mdUnityMcpBridge/Runtime/Serialization/UnityTypeConverters.csTestProjects/UnityMCPTests/Packages/manifest.json
📚 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:
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ComponentResolverTests.csUnityMcpBridge/Editor/Tools/ExecuteMenuItem.csUnityMcpBridge/Editor/Tools/ManageEditor.csUnityMcpBridge/Editor/Windows/ManualConfigEditorWindow.csUnityMcpBridge/Editor/Tools/ManageQueue.csUnityMcpBridge/Editor/Tools/ManageAsset.csTestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/AIPropertyMatchingTests.csTestProjects/UnityMCPTests/Assets/Scripts/TestAsmdef/CustomComponent.csUnityMcpBridge/Editor/Tools/ManageScene.csUnityMcpBridge/Editor/Tools/ManageScript.csUnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.csUnityMcpBridge/Editor/Helpers/Response.csTestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectTests.csUnityMcpBridge/Editor/Helpers/ServerPathResolver.csUnityMcpBridge/Editor/Tools/ManageGameObject.csUnityMcpBridge/Editor/Tools/ReadConsole.csUnityMcpBridge/Editor/Helpers/GameObjectSerializer.csUnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs
📚 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:
TestProjects/UnityMCPTests/.serena/memories/suggested_commands.mdTestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.mdUnityMcpBridge/Editor/Helpers/PackageDetector.csUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csUnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.csUnityMcpBridge/Editor/Helpers/PackageInstaller.csUnityMcpBridge/package.jsonUnityMcpBridge/Editor/Helpers/ServerPathResolver.csUnityMcpBridge/Editor/Helpers/ServerInstaller.csTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.md
📚 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:
CLAUDE.mdUnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.pyTestProjects/UnityMCPTests/.serena/memories/code_style_conventions.md.serena/memories/project_overview.mdTestProjects/UnityMCPTests/.serena/memories/project_overview.mdUnityMcpBridge/UnityMcpServer~/src/tools/__init__.pyUnityMcpBridge/package.jsonTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.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:
TestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.mdUnityMcpBridge/Editor/Helpers/PackageDetector.csUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csUnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.csUnityMcpBridge/package.jsonUnityMcpBridge/Editor/Helpers/ServerPathResolver.csUnityMcpBridge/Editor/Helpers/ServerInstaller.csTestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.md
📚 Learning: 2025-11-05T18:23:12.319Z
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.319Z
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:
UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.pyUnityMcpBridge/Editor/Tools/ManageQueue.cs.serena/memories/project_overview.mdTestProjects/UnityMCPTests/.serena/memories/project_overview.mdUnityMcpBridge/UnityMcpServer~/src/tools/__init__.pyUnityMcpBridge/Editor/MCPForUnityBridge.csmcp_source.pyUnityMcpBridge/package.json
📚 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:
UnityMcpBridge/Editor/Helpers/PackageDetector.csUnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.csTestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.csUnityMcpBridge/Editor/Helpers/ServerInstaller.cs
🧬 Code graph analysis (27)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ComponentResolverTests.cs (1)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (2)
ComponentResolver(2197-2457)TryResolve(2207-2243)
UnityMcpBridge/Editor/Tools/ManageEditor.cs (1)
UnityMcpBridge/Editor/Helpers/Response.cs (2)
Response(12-190)Error(43-62)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/ManualConfigJsonBuilderTests.cs (1)
UnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.cs (2)
ConfigJsonBuilder(7-128)BuildManualConfigJson(9-29)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py (2)
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (1)
send_command_with_retry(388-407)UnityMcpBridge/Editor/Helpers/OperationQueue.cs (1)
List(334-347)
UnityMcpBridge/Editor/Helpers/PackageDetector.cs (1)
UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (2)
ServerInstaller(12-738)GetServerPath(112-115)
UnityMcpBridge/Editor/Tools/ManageQueue.cs (1)
UnityMcpBridge/Editor/Helpers/OperationQueue.cs (10)
AddOperation(66-97)ExecuteBatch(259-270)ClearQueue(354-374)RemoveOperation(403-410)CancelOperation(415-430)OperationQueue(25-431)List(334-347)QueuedOperation(30-42)Task(124-253)Task(275-290)
UnityMcpBridge/Editor/Tools/ManageAsset.cs (2)
UnityMcpBridge/Editor/Helpers/Response.cs (3)
Response(12-190)Error(43-62)Success(20-35)UnityMcpBridge/Editor/Tools/ManageGameObject.cs (9)
ComponentResolver(2197-2457)TryResolve(2207-2243)GameObject(1191-1214)List(1219-1378)List(2258-2295)List(2318-2336)List(2341-2380)List(2388-2423)Type(2176-2190)
UnityMcpBridge/Editor/Helpers/OperationQueue.cs (2)
UnityMcpBridge/Editor/Helpers/Response.cs (3)
Error(43-62)Response(12-190)Success(20-35)UnityMcpBridge/Editor/Tools/ManageQueue.cs (8)
AddOperation(88-142)ExecuteBatchAsync(168-187)ExecuteBatch(147-163)HandleCommand(22-83)ClearQueue(401-429)GetQueueStats(434-451)RemoveOperation(456-509)CancelOperation(293-345)
UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs (6)
UnityMcpBridge/Editor/MCPForUnityBridge.cs (5)
MCPForUnityBridge(104-125)IsAutoConnectMode(62-62)GetCurrentPort(61-61)Stop(356-414)Start(237-354)UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (4)
ServerInstaller(12-738)GetServerPath(112-115)RepairPythonEnvironment(421-522)FindUvPath(524-712)UnityMcpBridge/Editor/Helpers/ExecPath.cs (3)
ExecPath(10-276)ResolveClaude(15-88)ResolveUv(160-163)UnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.cs (2)
ConfigJsonBuilder(7-128)BuildManualConfigJson(9-29)UnityMcpBridge/Editor/Windows/ManualConfigEditorWindow.cs (2)
ManualConfigEditorWindow(9-288)ShowWindow(19-27)UnityMcpBridge/Editor/Helpers/ServerPathResolver.cs (2)
ServerPathResolver(7-147)TryFindEmbeddedServerSource(14-99)
UnityMcpBridge/UnityMcpServer~/src/tools/__init__.py (1)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py (2)
manage_queue(37-131)register_manage_queue(13-227)
UnityMcpBridge/Editor/Tools/ManageScene.cs (1)
UnityMcpBridge/Editor/Helpers/Response.cs (3)
Response(12-190)Success(20-35)Error(43-62)
UnityMcpBridge/Editor/MCPForUnityBridge.cs (4)
UnityMcpBridge/Editor/Helpers/OperationQueue.cs (2)
Task(124-253)Task(275-290)UnityMcpBridge/Editor/Models/Command.cs (1)
Command(8-19)UnityMcpBridge/Editor/Tools/ManageQueue.cs (2)
ManageQueue(17-510)HandleCommand(22-83)UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (2)
ServerInstaller(12-738)GetServerPath(112-115)
UnityMcpBridge/Editor/Tools/ManageScript.cs (1)
UnityMcpBridge/Editor/Helpers/Response.cs (5)
Response(12-190)EnhancedError(76-114)Success(20-35)ScriptError(139-150)Error(43-62)
tools/benchmark_operation_queue.py (2)
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (1)
send_command_with_retry(388-407)tools/test_async_queue.py (1)
main(228-280)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptValidationTests.cs (1)
UnityMcpBridge/Editor/Tools/ManageScript.cs (1)
ManageScript(51-2560)
UnityMcpBridge/Editor/Tools/ManageShader.cs (1)
UnityMcpBridge/Editor/Tools/ManageAsset.cs (1)
DeleteAsset(493-521)
UnityMcpBridge/Editor/Helpers/Response.cs (3)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (6)
UnityEngine(2072-2169)List(1219-1378)List(2258-2295)List(2318-2336)List(2341-2380)List(2388-2423)UnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs (1)
UnityEngine(223-265)UnityMcpBridge/Editor/Helpers/OperationQueue.cs (1)
List(334-347)
UnityMcpBridge/Editor/Helpers/PortManager.cs (1)
UnityMcpBridge/Editor/MCPForUnityBridge.cs (5)
System(568-613)System(615-619)System(621-640)System(642-659)ComputeProjectHash(1000-1018)
UnityMcpBridge/Editor/Helpers/PackageInstaller.cs (1)
UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (2)
ServerInstaller(12-738)EnsureServerInstalled(22-110)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectTests.cs (1)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (10)
GameObject(1191-1214)ManageGameObject(21-2191)HandleCommand(40-173)ComponentResolver(2197-2457)TryResolve(2207-2243)List(1219-1378)List(2258-2295)List(2318-2336)List(2341-2380)List(2388-2423)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Windows/WriteToConfigTests.cs (1)
UnityMcpBridge/Editor/Helpers/ConfigJsonBuilder.cs (2)
JObject(31-41)JObject(121-127)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (4)
UnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs (4)
UnityEngineObjectConverter(165-266)Color(103-112)Vector2(49-56)UnityEngine(223-265)UnityMcpBridge/Editor/Helpers/Response.cs (2)
Response(12-190)Error(43-62)UnityMcpBridge/Editor/Tools/ManageScript.cs (1)
System(2291-2357)UnityMcpBridge/Editor/Tools/ManageAsset.cs (1)
ConvertJTokenToType(1166-1243)
UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (1)
UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs (1)
FindUvPath(2046-2049)
tools/test_async_queue.py (2)
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (1)
send_command_with_retry(388-407)tools/benchmark_operation_queue.py (1)
main(352-400)
UnityMcpBridge/Editor/Helpers/GameObjectSerializer.cs (2)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (6)
Type(2176-2190)List(1219-1378)List(2258-2295)List(2318-2336)List(2341-2380)List(2388-2423)UnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs (1)
UnityEngineObjectConverter(165-266)
UnityMcpBridge/Runtime/Serialization/UnityTypeConverters.cs (2)
UnityMcpBridge/Editor/Tools/ManageGameObject.cs (2)
Vector3(1168-1186)Vector3(1975-1990)UnityMcpBridge/Editor/Helpers/Vector3Helper.cs (1)
Vector3(17-22)
tests/test_operation_queue.py (1)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py (3)
manage_queue(37-131)register_manage_queue(13-227)queue_batch_operations(144-227)
🪛 LanguageTool
TestProjects/UnityMCPTests/.serena/memories/task_completion_checklist.md
[misspelling] ~25-~25: This word is normally spelled as one.
Context: ...tual MCP client connection - [ ] Verify auto-configuration still works - [ ] Test all affected MCP...
(EN_COMPOUNDS_AUTO_CONFIGURATION)
[duplication] ~49-49: Possible typo: you repeated a word./src/pyp...
Context: ...sion Synchronization** (if needed) - Update UnityMcpBridge/package.json - Update `UnityMcpBridge/UnityMcpServer
(ENGLISH_WORD_REPEAT_RULE)
[grammar] ~73-~73: Probably a preposition is missing after ‘references’.
Context: ...port All - Check assembly definition references - Verify test runner settings ## Final Verifica...
(ATD_VERBS_TO_COLLOCATION)
.serena/memories/task_completion_checklist.md
[grammar] ~19-~19: Did you mean “to Ensure”?
Context: ...jsonandpyproject.toml` if needed 2. Ensure no sensitive information in code or com...
(MISSING_TO_BEFORE_A_VERB)
[misspelling] ~20-~20: This word is normally spelled as one.
Context: ... information in code or commits 3. Test auto-configuration with target MCP clients if modifying se...
(EN_COMPOUNDS_AUTO_CONFIGURATION)
OPERATION_QUEUE_REVIEW.md
[misspelling] ~59-~59: This word is normally spelled as one.
Context: ... operations - Concurrency Tests: No multi-threaded access testing - **Async Operation Test...
(EN_COMPOUNDS_MULTI_THREADED)
STUDIO_FEATURES.md
[grammar] ~86-~86: The verb ‘Create’ is plural. Did you mean: “creates”? Did you use a verb instead of a noun?
Context: ...e tests 4. Update this documentation 5. Create PR with detailed description ### Testi...
(PLURAL_VERB_AFTER_THIS)
CLAUDE.md
[misspelling] ~457-~457: This word is normally spelled as one.
Context: ... actual MCP client connection 4. Verify auto-configuration still works 5. Run stress test for prot...
(EN_COMPOUNDS_AUTO_CONFIGURATION)
TestProjects/UnityMCPTests/PORT_CONFIGURATION.md
[uncategorized] ~28-~28: Possible missing comma found.
Context: ...e .claude/ directory is intentionally gitignored as it contains local development config...
(AI_HYDRA_LEO_MISSING_COMMA)
TestProjects/UnityMCPTests/.serena/memories/code_style_conventions.md
[style] ~30-~30: ‘with success’ might be wordy. Consider a shorter alternative.
Context: ...ocks - Return structured JSON responses with success/error fields - Log detailed errors to U...
(EN_WORDINESS_PREMIUM_WITH_SUCCESS)
QUICK_WINS_ROADMAP.md
[typographical] ~7-~7: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...ges Priority: Highest | Effort: 2-3 days | Impact: Immediate **Impleme...
(HYPHEN_TO_EN)
[typographical] ~26-~26: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...uing Priority: High | Effort: 3-4 days | Impact: Performance boost *...
(HYPHEN_TO_EN)
[typographical] ~49-~49: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...sets Priority: Medium | Effort: 4-5 days | Impact: Workflow improvement...
(HYPHEN_TO_EN)
[typographical] ~58-~58: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...ates Priority: Medium | Effort: 3-4 days | Impact: Consistency **Studi...
(HYPHEN_TO_EN)
[typographical] ~71-~71: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...System Priority: High | Effort: 6-7 days | Impact: Safety net **Featur...
(HYPHEN_TO_EN)
[grammar] ~95-~95: You’ve repeated a verb. Did you mean to only write one of them?
Context: ...age validation tests ### Documentation Updates - Update README.md with new tools - Add examples...
(REPEATED_VERBS)
[typographical] ~113-~113: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...stimated Total Time for All Quick Wins: 3-4 weeks* *Expected Productivity Improve...
(HYPHEN_TO_EN)
TestProjects/UnityMCPTests/.serena/memories/unity_mcp_setup.md
[uncategorized] ~21-~21: Possible missing preposition found.
Context: ...or, etc.) 3. Follow the setup wizard 4. Verify configuration was added to client ### ...
(AI_HYDRA_LEO_MISSING_TO)
🪛 markdownlint-cli2 (0.18.1)
README-DEV.md
56-56: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
CLAUDE.md
9-9: Bare URL used
(MD034, no-bare-urls)
10-10: Bare URL used
(MD034, no-bare-urls)
184-184: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
TestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.md
35-35: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 Ruff (0.14.4)
UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py
38-38: Unused function argument: ctx
(ARG001)
125-125: Do not catch blind exception: Exception
(BLE001)
126-126: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
126-126: Use explicit conversion flag
Replace with conversion flag
(RUF010)
129-129: Use explicit conversion flag
Replace with conversion flag
(RUF010)
221-221: Do not catch blind exception: Exception
(BLE001)
222-222: Use logging.exception instead of logging.error
Replace with exception
(TRY400)
222-222: Use explicit conversion flag
Replace with conversion flag
(RUF010)
225-225: Use explicit conversion flag
Replace with conversion flag
(RUF010)
tools/benchmark_operation_queue.py
1-1: Shebang is present but file is not executable
(EXE001)
92-92: Local variable response is assigned to but never used
Remove assignment to unused variable response
(F841)
103-103: Do not use bare except
(E722)
103-104: try-except-pass detected, consider logging the exception
(S110)
107-107: Do not catch blind exception: Exception
(BLE001)
126-126: Do not catch blind exception: Exception
(BLE001)
242-242: f-string without any placeholders
Remove extraneous f prefix
(F541)
286-286: Do not catch blind exception: Exception
(BLE001)
346-346: f-string without any placeholders
Remove extraneous f prefix
(F541)
395-395: Do not catch blind exception: Exception
(BLE001)
tools/test_async_queue.py
1-1: Shebang is present but file is not executable
(EXE001)
98-98: Unused function argument: operation_ids
(ARG001)
118-118: Unused function argument: operation_ids
(ARG001)
200-200: f-string without any placeholders
Remove extraneous f prefix
(F541)
204-204: String contains ambiguous ℹ (INFORMATION SOURCE). Did you mean i (LATIN SMALL LETTER I)?
(RUF001)
223-223: Do not use bare except
(E722)
223-224: try-except-pass detected, consider logging the exception
(S110)
271-271: Consider moving this statement to an else block
(TRY300)
276-276: Do not catch blind exception: Exception
(BLE001)
tests/test_operation_queue.py
238-238: Consider [*add_responses, execute_response] instead of concatenation
Replace with [*add_responses, execute_response]
(RUF005)
| 1. Create feature branch from main: `feature/studio-{feature-name}` | ||
| 2. Implement both Unity (C#) and Python (MCP) components | ||
| 3. Add comprehensive tests | ||
| 4. Update this documentation | ||
| 5. Create PR with detailed description |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix grammar in the development guidelines section.
Line 86 contains a grammatical issue. The verb form is incorrect.
Apply this diff to correct the grammar:
- 5. Create PR with detailed description
+ 5. Create a PR with detailed descriptionAlternatively, if the imperative list format is preferred, rephrase as:
- 5. Create PR with detailed description
+ 5. Create a pull request with detailed description(Note: As per static analysis hints, this follows standard grammar conventions.)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 1. Create feature branch from main: `feature/studio-{feature-name}` | |
| 2. Implement both Unity (C#) and Python (MCP) components | |
| 3. Add comprehensive tests | |
| 4. Update this documentation | |
| 5. Create PR with detailed description | |
| 1. Create feature branch from main: `feature/studio-{feature-name}` | |
| 2. Implement both Unity (C#) and Python (MCP) components | |
| 3. Add comprehensive tests | |
| 4. Update this documentation | |
| 5. Create a PR with detailed description |
🧰 Tools
🪛 LanguageTool
[grammar] ~86-~86: The verb ‘Create’ is plural. Did you mean: “creates”? Did you use a verb instead of a noun?
Context: ...e tests 4. Update this documentation 5. Create PR with detailed description ### Testi...
(PLURAL_VERB_AFTER_THIS)
🤖 Prompt for AI Agents
In STUDIO_FEATURES.md around lines 82 to 86, the verb phrase on line 86 is
grammatically incorrect; change "Implement both Unity (C#) and Python (MCP)
components" to a correct imperative form such as "Implement both the Unity (C#)
and Python (MCP) components" (or alternatively "Implement the Unity (C#) and
Python (MCP) components") so the article and noun agreement are fixed and the
list remains consistent in imperative style.
| ## Unity Editor Commands | ||
| ```bash | ||
| # Open Unity project with specific version | ||
| /home/tuha/Unity/Hub/Editor/6000.2.5f1/Editor/Unity -projectpath /mnt/Work/1M/unity-mcp/TestProjects/UnityMCPTests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
** Hard-coded user-specific paths in documentation.**
This documentation contains hard-coded paths specific to user "tuha":
/home/tuha/Unity/Hub/Editor/6000.2.5f1/Editor/Unity(line 6)/mnt/Work/1M/unity-mcp/TestProjects/UnityMCPTests(lines 9, 15, 22, 28, 73)
If this file is meant to be shared (committed to the repository), consider either:
- Using relative paths or placeholders like
${PROJECT_ROOT} - Adding
.serena/memories/to.gitignoreif these are intended as personal notes - Creating a template version with placeholders that developers can customize
Example replacement:
-/home/tuha/Unity/Hub/Editor/6000.2.5f1/Editor/Unity -projectpath /mnt/Work/1M/unity-mcp/TestProjects/UnityMCPTests
+${UNITY_EDITOR} -projectpath ${PROJECT_ROOT}/TestProjects/UnityMCPTests
-unity-hub --project /mnt/Work/1M/unity-mcp/TestProjects/UnityMCPTests
+unity-hub --project ${PROJECT_ROOT}/TestProjects/UnityMCPTestsAlso applies to: 9-9, 15-15, 22-22, 28-28, 73-73
🤖 Prompt for AI Agents
In TestProjects/UnityMCPTests/.serena/memories/suggested_commands.md around line
6 (also lines 9, 15, 22, 28, 73), the file contains hard-coded, user-specific
filesystem paths; replace those absolute paths with either project-relative
paths or placeholders (e.g., ${PROJECT_ROOT} or ${UNITY_EDITOR_PATH}) so the
document is shareable, or move the file out of source control by adding
.serena/memories/ to .gitignore; if you want to keep an example, create a
template version that shows placeholders instead of real user paths.
| "args": ["run", "server.py"], | ||
| "cwd": "../../UnityMcpBridge/UnityMcpServer~/src", | ||
| "env": { | ||
| "UNITY_PROJECT_PATH": "${workspaceFolder}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify language for fenced code block.
The JSON configuration block should have a language identifier for proper syntax highlighting.
Apply this diff:
-```
+```json
{
"mcpServers": {🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
35-35: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In TestProjects/UnityMCPTests/.serena/memories/unity_mcp_local_setup.md around
line 35, the fenced code block for the JSON snippet is missing a language
identifier; add the JSON language tag to the opening fence by replacing the
opening triple backticks with ```json so the block begins with ```json followed
immediately by the existing JSON content.
| @@ -0,0 +1,403 @@ | |||
| #!/usr/bin/env python3 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the file executable.
The shebang is present but the file lacks executable permissions. This prevents direct execution via ./tools/benchmark_operation_queue.py.
Run the following command to fix:
chmod +x tools/benchmark_operation_queue.py🧰 Tools
🪛 Ruff (0.14.4)
1-1: Shebang is present but file is not executable
(EXE001)
🤖 Prompt for AI Agents
In tools/benchmark_operation_queue.py around line 1 the shebang is present but
the file lacks executable permissions; make the script executable by updating
its mode (e.g., run chmod +x tools/benchmark_operation_queue.py) so it can be
executed directly via ./tools/benchmark_operation_queue.py.
| def cleanup_test_scripts(self): | ||
| """Clean up test scripts created during benchmarking.""" | ||
| print("🧹 Cleaning up test scripts...") | ||
| try: | ||
| # Clear the queue first | ||
| response = send_command_with_retry("manage_queue", {"action": "clear"}) | ||
|
|
||
| # Delete benchmark scripts | ||
| for i in range(100): | ||
| script_name = f"BenchmarkScript_{i:03d}" | ||
| try: | ||
| send_command_with_retry("manage_script", { | ||
| "action": "delete", | ||
| "name": script_name, | ||
| "path": "Assets/Scripts/Benchmark" | ||
| }) | ||
| except: | ||
| pass # Ignore errors for scripts that don't exist | ||
|
|
||
| print("✅ Cleanup completed") | ||
| except Exception as e: | ||
| print(f"⚠️ Cleanup failed: {e}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve exception handling in cleanup method.
Multiple issues with exception handling:
- Line 92: Variable
responseis assigned but never used. - Lines 103-104: Bare
except:catches all exceptions includingKeyboardInterruptandSystemExit, which can prevent graceful shutdown. Should beexcept Exception:at minimum. - Lines 103-104: The
try-except-passpattern silently swallows errors, making debugging difficult.
Apply this diff to improve error handling:
try:
# Clear the queue first
- response = send_command_with_retry("manage_queue", {"action": "clear"})
+ send_command_with_retry("manage_queue", {"action": "clear"})
# Delete benchmark scripts
for i in range(100):
script_name = f"BenchmarkScript_{i:03d}"
try:
send_command_with_retry("manage_script", {
"action": "delete",
"name": script_name,
"path": "Assets/Scripts/Benchmark"
})
- except:
- pass # Ignore errors for scripts that don't exist
+ except Exception as e:
+ # Script may not exist, which is expected during cleanup
+ print(f" Note: Could not delete {script_name}: {e}", file=sys.stderr)Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Ruff (0.14.4)
92-92: Local variable response is assigned to but never used
Remove assignment to unused variable response
(F841)
103-103: Do not use bare except
(E722)
103-104: try-except-pass detected, consider logging the exception
(S110)
107-107: Do not catch blind exception: Exception
(BLE001)
| private static async Task<object> ExecuteOperationWithTimeoutAsync(QueuedOperation operation) | ||
| { | ||
| var cancellationTokenSource = new CancellationTokenSource(operation.TimeoutMs); | ||
|
|
||
| try | ||
| { | ||
| // Execute on Unity's main thread with timeout | ||
| var task = Task.Run(() => ExecuteOperation(operation), cancellationTokenSource.Token); | ||
|
|
||
| return await task; | ||
| } | ||
| catch (OperationCanceledException) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not run Unity editor code from a background thread.
ExecuteOperationWithTimeoutAsync wraps ExecuteOperation in Task.Run(...). That means anything in ExecuteOperation (ManageAsset, ManageScene, ExecuteMenuItem, etc.) is now executed on a thread-pool worker. These tool handlers are built on UnityEditor APIs that must run on the main thread; moving them off-thread introduces races, undefined behaviour, and crashes (the old code ran everything synchronously on the main thread, so this is a regression). Please keep execution on the main thread and implement timeout/cancellation by other means (e.g. cooperative checks or scheduling via the editor update loop) rather than hopping to the thread pool.
🤖 Prompt for AI Agents
In UnityMcpBridge/Editor/Helpers/OperationQueue.cs around lines 275 to 286, the
current implementation offloads ExecuteOperation to the thread-pool via Task.Run
which runs UnityEditor APIs off the main thread; remove Task.Run and ensure
ExecuteOperation executes on the Unity main thread by scheduling it via the
editor update loop or EditorApplication.delayCall and using a
TaskCompletionSource to capture the result; implement timeout/cancellation by
starting a CancellationTokenSource(operation.TimeoutMs) and either (a) on each
main-thread step check token.IsCancellationRequested in ExecuteOperation
(cooperative cancellation) or (b) when the timeout elapses set the
TaskCompletionSource to fault/cancel from the timeout path on the background
timer, then stop scheduling further work; ensure no UnityEditor calls are
invoked off-thread and that the Task returned to callers completes or cancels
based on the cooperative/main-thread execution and the CTS.
| case "by_id": | ||
| if (int.TryParse(searchTerm, out int instanceId)) | ||
| if (int.TryParse(searchTerm, out var instanceId)) | ||
| { | ||
| // EditorUtility.InstanceIDToObject is slow, iterate manually if possible | ||
| // GameObject obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject; | ||
| var allObjects = GetAllSceneObjects(searchInactive); // More efficient | ||
| GameObject obj = allObjects.FirstOrDefault(go => | ||
| var obj = allObjects.FirstOrDefault(go => | ||
| go.GetInstanceID() == instanceId | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore inactive-ID lookup behavior
Switching the by_id branch to GetAllSceneObjects(searchInactive) means we now skip inactive GameObjects whenever the caller omits searchInactive (the default is false). Operations like delete/modify that pass searchMethod="by_id" and expect instance IDs to resolve regardless of active state will fail to find disabled objects—previous behavior (via EditorUtility.InstanceIDToObject) always returned them. Please force the ID lookup to scan inactive objects as well (or restore the InstanceIDToObject fallback) so existing flows keep working.
- var allObjects = GetAllSceneObjects(searchInactive); // More efficient
+ var allObjects = GetAllSceneObjects(true); // Instance IDs must resolve even if the GO is inactive📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| case "by_id": | |
| if (int.TryParse(searchTerm, out int instanceId)) | |
| if (int.TryParse(searchTerm, out var instanceId)) | |
| { | |
| // EditorUtility.InstanceIDToObject is slow, iterate manually if possible | |
| // GameObject obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject; | |
| var allObjects = GetAllSceneObjects(searchInactive); // More efficient | |
| GameObject obj = allObjects.FirstOrDefault(go => | |
| var obj = allObjects.FirstOrDefault(go => | |
| go.GetInstanceID() == instanceId | |
| ); | |
| case "by_id": | |
| if (int.TryParse(searchTerm, out var instanceId)) | |
| { | |
| // EditorUtility.InstanceIDToObject is slow, iterate manually if possible | |
| // GameObject obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject; | |
| var allObjects = GetAllSceneObjects(true); // Instance IDs must resolve even if the GO is inactive | |
| var obj = allObjects.FirstOrDefault(go => | |
| go.GetInstanceID() == instanceId | |
| ); |
🤖 Prompt for AI Agents
In UnityMcpBridge/Editor/Tools/ManageGameObject.cs around lines 1258 to 1266,
the "by_id" branch currently uses GetAllSceneObjects(searchInactive) which
respects the caller's searchInactive flag and therefore may miss
inactive/disabled GameObjects when searchInactive is false; change the lookup to
always include inactive objects (e.g. call GetAllSceneObjects(true)) or,
alternatively, fall back to EditorUtility.InstanceIDToObject(instanceId) when
the manual search fails so instance IDs resolve regardless of active state;
ensure the code still prefers the efficient scene scan but forces/invokes an
inactive-inclusive search or fallback to restore the previous behavior.
| private static object ExecuteBatchAsyncUnityCompatible() | ||
| { | ||
| // For Unity Editor compatibility, we'll execute with yielding between operations | ||
| // This prevents UI freezing while still being "async" from Unity's perspective | ||
|
|
||
| var pendingOps = OperationQueue.GetOperations("pending"); | ||
| if (pendingOps.Count == 0) | ||
| { | ||
| return Response.Success("No pending operations to execute.", new { executed_count = 0 }); | ||
| } | ||
|
|
||
| Debug.Log($"STUDIO: Starting async execution of {pendingOps.Count} operations"); | ||
|
|
||
| // Start the async execution using Unity's EditorApplication.delayCall | ||
| // This allows Unity Editor to remain responsive | ||
| EditorApplication.delayCall += () => ExecuteOperationsWithYield(pendingOps); | ||
|
|
||
| return Response.Success( | ||
| $"Started async execution of {pendingOps.Count} operations", | ||
| new | ||
| { | ||
| total_operations = pendingOps.Count, | ||
| status = "started_async", | ||
| message = "Use 'stats' action to monitor progress" | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Execute operations with yielding to keep Unity Editor responsive | ||
| /// </summary> | ||
| private static async void ExecuteOperationsWithYield(List<OperationQueue.QueuedOperation> operations) | ||
| { | ||
| foreach (var operation in operations) | ||
| { | ||
| try | ||
| { | ||
| // Update status to executing | ||
| operation.Status = "executing"; | ||
| operation.ExecutionStartTime = DateTime.UtcNow; | ||
|
|
||
| Debug.Log($"STUDIO: Executing operation {operation.Id} ({operation.Tool})"); | ||
|
|
||
| // Execute the operation | ||
| var result = await Task.Run(() => | ||
| { | ||
| try | ||
| { | ||
| switch (operation.Tool.ToLowerInvariant()) | ||
| { | ||
| case "manage_script": | ||
| return Tools.ManageScript.HandleCommand(operation.Parameters); | ||
| case "manage_asset": | ||
| return Tools.ManageAsset.HandleCommand(operation.Parameters); | ||
| case "manage_scene": | ||
| return Tools.ManageScene.HandleCommand(operation.Parameters); | ||
| case "manage_gameobject": | ||
| return Tools.ManageGameObject.HandleCommand(operation.Parameters); | ||
| case "manage_shader": | ||
| return Tools.ManageShader.HandleCommand(operation.Parameters); | ||
| case "manage_editor": | ||
| return Tools.ManageEditor.HandleCommand(operation.Parameters); | ||
| case "read_console": | ||
| return Tools.ReadConsole.HandleCommand(operation.Parameters); | ||
| case "execute_menu_item": | ||
| return Tools.ExecuteMenuItem.HandleCommand(operation.Parameters); | ||
| default: | ||
| throw new ArgumentException($"Unknown tool: {operation.Tool}"); | ||
| } | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| throw new Exception($"Operation {operation.Id} failed: {e.Message}", e); | ||
| } | ||
| }); | ||
|
|
||
| // Update operation status | ||
| operation.Result = result; | ||
| operation.Status = "executed"; | ||
| operation.ExecutionEndTime = DateTime.UtcNow; | ||
|
|
||
| Debug.Log($"STUDIO: Completed operation {operation.Id}"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| operation.Error = ex; | ||
| operation.Status = "failed"; | ||
| operation.ExecutionEndTime = DateTime.UtcNow; | ||
| Debug.LogError($"STUDIO: Operation {operation.Id} failed: {ex.Message}"); | ||
| } | ||
|
|
||
| // Yield control back to Unity Editor to keep it responsive | ||
| await Task.Yield(); | ||
| } | ||
|
|
||
| Debug.Log("STUDIO: Async batch execution completed"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Async loop ignores per-operation timeouts.
ExecuteOperationsWithYield never honours QueuedOperation.TimeoutMs, so every “async” run executes with an unlimited timeout. The C# helper (OperationQueue.ExecuteBatchAsync) already enforces timeouts and marks operations as timeout, but this reimplementation skips that logic—long-running operations will now hang the queue indefinitely. Please reuse OperationQueue.ExecuteBatchAsync() (and marshal its task via EditorApplication.delayCall) or replicate its timeout handling before shipping this path.
| private void SetManualPort(int newPort) | ||
| { | ||
| if (newPort < 1024 || newPort > 65535) | ||
| { | ||
| EditorUtility.DisplayDialog("Invalid Port", "Port must be between 1024 and 65535", "OK"); | ||
| return; | ||
| } | ||
|
|
||
| // Save the new port for this project | ||
| var projectHash = ComputeSha1(Application.dataPath).Substring(0, 8); | ||
| var portFile = Path.Combine( | ||
| Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), | ||
| ".unity-mcp", | ||
| $"unity-mcp-port-{projectHash}.json" | ||
| ); | ||
|
|
||
| try | ||
| { | ||
| // Create directory if needed | ||
| var dir = Path.GetDirectoryName(portFile); | ||
| if (!Directory.Exists(dir)) | ||
| Directory.CreateDirectory(dir); | ||
|
|
||
| // Write new port config | ||
| var config = new | ||
| { | ||
| unity_port = newPort, | ||
| created_date = DateTime.UtcNow.ToString("o"), | ||
| project_path = Application.dataPath | ||
| }; | ||
| var json = JsonConvert.SerializeObject(config, Formatting.Indented); | ||
| File.WriteAllText(portFile, json); | ||
|
|
||
| // If bridge is running, restart it with new port | ||
| if (MCPForUnityBridge.IsRunning) | ||
| { | ||
| MCPForUnityBridge.Stop(); | ||
| EditorApplication.delayCall += () => | ||
| { | ||
| MCPForUnityBridge.Start(); | ||
| Repaint(); | ||
| }; | ||
| } | ||
|
|
||
| EditorUtility.DisplayDialog("Port Changed", $"Unity Bridge port set to {newPort}. Bridge will restart if running.", "OK"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| EditorUtility.DisplayDialog("Error", $"Failed to set port: {ex.Message}", "OK"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Refactor to eliminate code duplication with PortManager.
The SetManualPort method duplicates port configuration serialization logic that already exists in PortManager.SavePort (lines 193-220). Both methods:
- Compute project hash
- Create JSON with same schema (unity_port, created_date, project_path)
- Write to ~/.unity-mcp/unity-mcp-port-{hash}.json
- Handle directory creation
Additionally, line 692 uses .Substring(0, 8) while PortManager.ComputeProjectHash uses [..8] range syntax (line 311) - inconsistent approaches for the same operation.
Refactor to use the existing infrastructure:
private void SetManualPort(int newPort)
{
if (newPort < 1024 || newPort > 65535)
{
EditorUtility.DisplayDialog("Invalid Port", "Port must be between 1024 and 65535", "OK");
return;
}
- // Save the new port for this project
- var projectHash = ComputeSha1(Application.dataPath).Substring(0, 8);
- var portFile = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
- ".unity-mcp",
- $"unity-mcp-port-{projectHash}.json"
- );
-
- try
- {
- // Create directory if needed
- var dir = Path.GetDirectoryName(portFile);
- if (!Directory.Exists(dir))
- Directory.CreateDirectory(dir);
-
- // Write new port config
- var config = new
- {
- unity_port = newPort,
- created_date = DateTime.UtcNow.ToString("o"),
- project_path = Application.dataPath
- };
- var json = JsonConvert.SerializeObject(config, Formatting.Indented);
- File.WriteAllText(portFile, json);
+ // Use PortManager to save the new port
+ try
+ {
+ PortManager.SavePort(newPort);
// If bridge is running, restart it with new port
if (MCPForUnityBridge.IsRunning)
{
MCPForUnityBridge.Stop();
EditorApplication.delayCall += () =>
{
MCPForUnityBridge.Start();
Repaint();
};
}
EditorUtility.DisplayDialog("Port Changed", $"Unity Bridge port set to {newPort}. Bridge will restart if running.", "OK");
}
catch (Exception ex)
{
EditorUtility.DisplayDialog("Error", $"Failed to set port: {ex.Message}", "OK");
}
}Note: PortManager.SavePort is currently private. You'll need to make it internal or add a public wrapper method:
// In PortManager.cs
public static void SavePort(int port)
{
// existing implementation
}🤖 Prompt for AI Agents
In UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs around lines 683 to
733, the SetManualPort method duplicates port file creation/serialization logic
found in PortManager.SavePort; refactor by removing the duplicated logic and
calling the shared PortManager save API instead (make SavePort public/internal
or add a public wrapper if needed), ensure you use
PortManager.ComputeProjectHash (or its public equivalent) so both call sites use
the same hash slicing style (use the same range syntax as PortManager), and keep
the surrounding behavior: validate port range, restart the bridge if
MCPForUnityBridge.IsRunning (stop, then delay-call start + Repaint), and
preserve user dialogs and exception handling by catching exceptions around the
PortManager call and showing the same error dialog.
| # Execute if requested | ||
| if execute_immediately: | ||
| execute_action = "execute_async" if use_async else "execute" | ||
| execute_result = manage_queue(ctx, execute_action) | ||
| execution_type = "async" if use_async else "sync" | ||
| return { | ||
| "success": True, | ||
| "message": f"Queued and executed {len(operations)} operations ({execution_type})", | ||
| "data": { | ||
| "queued_operations": operation_ids, | ||
| "execution_result": execute_result.get("data"), | ||
| "execution_type": execution_type | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Propagate execution failure from manage_queue.
If manage_queue(ctx, execute_action) returns {success: False}, we still ship a {success: True} envelope. Consumers will treat a failed execution as success and skip recovery/alerts. Check the response and bubble up the error (including message/code) before claiming success, e.g.:
- execute_result = manage_queue(ctx, execute_action)
- execution_type = "async" if use_async else "sync"
- return {
- "success": True,
- ...
- "data": {
- ...
- "execution_result": execute_result.get("data"),
- ...
- }
- }
+ execute_result = manage_queue(ctx, execute_action)
+ if not execute_result.get("success"):
+ return {
+ "success": False,
+ "error": f"{execute_action} queue execution failed",
+ "details": execute_result.get("error") or execute_result.get("details"),
+ "code": execute_result.get("code"),
+ "data": execute_result.get("data"),
+ }
+ execution_type = "async" if use_async else "sync"
+ return {
+ "success": True,
+ ...
+ }Without this guard, downstream automations will silently miss publish/cancel errors.
🤖 Prompt for AI Agents
In UnityMcpBridge/UnityMcpServer~/src/tools/manage_queue.py around lines 197 to
210, the code always returns success after calling manage_queue to execute
queued operations; change it to inspect execute_result and if
execute_result.get("success") is False, return a failure envelope that
propagates execute_result's message and code (or entire execute_result) instead
of claiming success; otherwise return the current success response including
execution_result and execution_type. Ensure you check for None/missing keys
safely and preserve execute_result["data"] on success.
|
Sigh. I have no choice but to believe that this is intentional spam at this point. I'm closing your PRs. Do not send further PRs @tuha263 unless you're willing to keep up to date with the project and collaborate |
Fix bash subshell issue that caused package_details to be empty in Discord notifications.
Problem: Used
cat file | while readwhich creates a subshell, making variables not persist to parent shell.Solution: Changed to use file redirection
while read; done < fileto avoid subshell.Changes:
See: The1Studio/UPMAutoPublisher@ba6ad18
Summary by CodeRabbit
New Features
Documentation
Chores