feat: add manage_unity_hub tool — Unity Hub CLI integration#1042
feat: add manage_unity_hub tool — Unity Hub CLI integration#1042zaferdace wants to merge 2 commits intoCoplayDev:mainfrom
Conversation
Host-side tool for managing Unity Hub and Editor installations. Does NOT require a running Unity Editor instance. 7 actions: - get_hub_info: detect Hub path, OS info - list_installed_editors: list all installed Unity versions - list_available_releases: list downloadable versions - get_install_path / set_install_path: manage editor install location - install_editor: download and install a Unity version - install_modules: add platform modules (Android, iOS, etc.) Features: - Auto-detect Hub on macOS/Windows/Linux + UNITY_HUB_PATH env override - Confirmation required for state-changing actions - Robust subprocess handling with timeout + error recovery - CLI support: unity-mcp hub editors/releases/install/etc. - Raw output always included for parser resilience
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ 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 |
Reviewer's GuideAdds a new host-side Unity Hub integration layer (service, MCP tool, and CLI commands) that wraps the Unity Hub CLI for querying and managing Unity Editor installations, and wires it into the existing CLI and tool registry. Sequence diagram for manage_unity_hub action execution via Unity Hub CLIsequenceDiagram
actor Assistant
participant MCPServer
participant manage_unity_hub_tool
participant unity_hub_service
participant UnityHubCLI
Assistant->>MCPServer: JSON RPC tool call manage_unity_hub(action, version, modules, path, limit, confirm)
MCPServer->>manage_unity_hub_tool: invoke manage_unity_hub(...)
manage_unity_hub_tool->>manage_unity_hub_tool: normalize action, validate against ALL_ACTIONS
alt action is state-changing and confirm is false
manage_unity_hub_tool->>unity_hub_service: detect_hub_path()
unity_hub_service-->>manage_unity_hub_tool: hub_path or null
manage_unity_hub_tool->>manage_unity_hub_tool: build confirmation message
manage_unity_hub_tool-->>MCPServer: {success False, confirmation_required True, message, hint}
MCPServer-->>Assistant: response requiring confirmation
else confirmed or read-only action
alt get_hub_info
manage_unity_hub_tool->>unity_hub_service: detect_hub_path()
unity_hub_service-->>manage_unity_hub_tool: hub_path or null
manage_unity_hub_tool-->>MCPServer: hub and host info payload
else list_installed_editors
manage_unity_hub_tool->>unity_hub_service: run_hub_command(["editors", "--installed"])
unity_hub_service->>UnityHubCLI: spawn process hub -- --headless editors --installed
UnityHubCLI-->>unity_hub_service: stdout, stderr, exit_code
unity_hub_service-->>manage_unity_hub_tool: {success, hub_path, raw_output}
manage_unity_hub_tool->>unity_hub_service: parse_installed_editors(raw_output)
unity_hub_service-->>manage_unity_hub_tool: list of editors
manage_unity_hub_tool-->>MCPServer: structured list_installed_editors result
else list_available_releases
manage_unity_hub_tool->>unity_hub_service: run_hub_command(["editors", "--releases"])
unity_hub_service->>UnityHubCLI: spawn process hub -- --headless editors --releases
UnityHubCLI-->>unity_hub_service: stdout, stderr, exit_code
unity_hub_service-->>manage_unity_hub_tool: {success, hub_path, raw_output}
manage_unity_hub_tool->>unity_hub_service: parse_available_releases(raw_output, limit)
unity_hub_service-->>manage_unity_hub_tool: list of releases
manage_unity_hub_tool-->>MCPServer: structured list_available_releases result
else get_install_path or set_install_path or install_editor or install_modules
manage_unity_hub_tool->>unity_hub_service: run_hub_command(args, timeout)
unity_hub_service->>UnityHubCLI: spawn process hub -- --headless ...
UnityHubCLI-->>unity_hub_service: stdout, stderr, exit_code
unity_hub_service-->>manage_unity_hub_tool: result dict
manage_unity_hub_tool-->>MCPServer: structured action-specific result
end
MCPServer-->>Assistant: final tool result
end
Class diagram for manage_unity_hub tool, unity_hub service, and CLI commandsclassDiagram
class ManageUnityHubTool {
+ALL_ACTIONS : list~str~
+READ_ONLY_ACTIONS : set~str~
+manage_unity_hub(action str, version str, modules list~str~, path str, limit int, confirm bool) dict~str, Any~
-_build_confirmation_message(action str, hub_path str, version str, modules list~str~, path str) str
-_get_hub_info() dict~str, Any~
-_list_installed_editors() dict~str, Any~
-_list_available_releases(limit int) dict~str, Any~
-_get_install_path() dict~str, Any~
-_set_install_path(path str) dict~str, Any~
-_install_editor(version str) dict~str, Any~
-_install_modules(version str, modules list~str~) dict~str, Any~
}
class UnityHubService {
-_HUB_PATHS : dict~str, list~str~~
-_DEFAULT_TIMEOUT : int
-_INSTALL_TIMEOUT : int
+detect_hub_path() str
+run_hub_command(args list~str~, timeout int, hub_path str) dict~str, Any~
+parse_installed_editors(raw_output str) list~dict~str, str~~
+parse_available_releases(raw_output str, limit int) list~dict~str, str~~
}
class UnityHubCliGroup {
+unity_hub() void
+_run_async(coro Any) Any
+_print_result(result dict) void
+info() void
+editors() void
+releases(limit int) void
+install_path(new_path str) void
+install(version str) void
+install_modules(version str, modules tuple~str~) void
}
class ToolRegistry {
+TOOL_GROUPS : dict~str, str~
}
class CliMain {
+register_optional_command(module_name str, command_name str) void
}
ManageUnityHubTool --> UnityHubService : uses
UnityHubCliGroup --> UnityHubService : uses
CliMain --> UnityHubCliGroup : registers
ToolRegistry --> ManageUnityHubTool : groups tool
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
run_hub_command, the process-spawn timeout is hard-coded to 5 seconds and independent of thetimeoutparameter; consider either tying this to the same timeout or making it configurable so slow startups don’t fail prematurely. - The CLI commands (
installandinstall-modules) hard-codetimeout=600instead of reusing_INSTALL_TIMEOUTfromservices.unity_hub, which makes timeout behavior harder to maintain consistently across entry points.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `run_hub_command`, the process-spawn timeout is hard-coded to 5 seconds and independent of the `timeout` parameter; consider either tying this to the same timeout or making it configurable so slow startups don’t fail prematurely.
- The CLI commands (`install` and `install-modules`) hard-code `timeout=600` instead of reusing `_INSTALL_TIMEOUT` from `services.unity_hub`, which makes timeout behavior harder to maintain consistently across entry points.
## Individual Comments
### Comment 1
<location path="Server/src/services/unity_hub.py" line_range="64-70" />
<code_context>
+ cmd = [hub, "--", "--headless", *args]
+
+ try:
+ proc = await asyncio.wait_for(
+ asyncio.create_subprocess_exec(
+ *cmd,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ ),
+ timeout=5,
+ )
+ stdout_bytes, stderr_bytes = await asyncio.wait_for(
</code_context>
<issue_to_address>
**issue (bug_risk):** The subprocess creation timeout is hardcoded to 5s and ignores the `timeout` argument.
The `timeout` parameter is only applied to `proc.communicate`, while process creation is always limited to 5s. On slower or loaded systems, starting Unity Hub may exceed 5s and fail even if callers request a larger timeout. Please either reuse the `timeout` value for both `create_subprocess_exec` and `communicate`, or introduce a named spawn-timeout constant instead of the hardcoded `5`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Replace hardcoded 5s spawn timeout with _SPAWN_TIMEOUT (15s), capped at the caller's timeout value for short timeouts - CLI commands now use _INSTALL_TIMEOUT from service module instead of hardcoded 600
Summary
Adds a new
manage_unity_hubMCP tool for managing Unity Hub and Editor installations directly from AI coding assistants.This is a host-side tool — it calls the Unity Hub CLI via subprocess and does not require a running Unity Editor instance. No C# plugin changes needed.
7 Actions
get_hub_infolist_installed_editorslist_available_releasesget_install_pathset_install_pathinstall_editorinstall_modulesExample Usage
Features
UNITY_HUB_PATHenv overrideunity-mcp hub editors,unity-mcp hub releases --limit 5, etc.Files
Server/src/services/unity_hub.pyServer/src/services/tools/manage_unity_hub.pyServer/src/cli/commands/unity_hub.pyServer/src/cli/main.pyServer/src/services/registry/tool_registry.pyDesign Decisions
manage_packagespatternconfirmparam rather than project's Unity-routed confirmation utility (since this doesn't go through Unity)Tested On
list_installed_editors: correctly parses6000.3.9f1,6000.3.10f1list_available_releases: correctly parses alpha/beta/stable channelsget_install_path: returns/Applications/Unity/Hub/EditorTest plan
list_installed_editorswith multiple installed versionslist_available_releaseswith--limitinstall_editorconfirmation gate (confirm=false should return prompt)install_moduleswith multiple modulesUNITY_HUB_PATHenv overrideSummary by Sourcery
Add a new host-side Unity Hub management capability, exposed both as an MCP tool and as CLI commands for querying and controlling Unity Editor installations via the Unity Hub CLI.
New Features:
Enhancements: