Skip to content

feat: add manage_unity_hub tool — Unity Hub CLI integration#1042

Open
zaferdace wants to merge 2 commits intoCoplayDev:mainfrom
zaferdace:feat/manage-unity-hub
Open

feat: add manage_unity_hub tool — Unity Hub CLI integration#1042
zaferdace wants to merge 2 commits intoCoplayDev:mainfrom
zaferdace:feat/manage-unity-hub

Conversation

@zaferdace
Copy link
Copy Markdown
Contributor

@zaferdace zaferdace commented Apr 6, 2026

Summary

Adds a new manage_unity_hub MCP 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

Action Type Confirmation
get_hub_info Read No
list_installed_editors Read No
list_available_releases Read No
get_install_path Read No
set_install_path Write Yes
install_editor Write Yes
install_modules Write Yes

Example Usage

# "What Unity versions do I have installed?"
manage_unity_hub(action="list_installed_editors")

# "Install Unity 6 with Android support"
manage_unity_hub(action="install_editor", version="6000.3.10f1", confirm=True)
manage_unity_hub(action="install_modules", version="6000.3.10f1", modules=["android"], confirm=True)

Features

  • Auto-detect Hub on macOS / Windows / Linux + UNITY_HUB_PATH env override
  • Confirmation gate for state-changing actions (install, set path)
  • Robust subprocess handling with configurable timeout (30s default, 600s for installs)
  • Raw output always included for parser resilience across Hub CLI versions
  • CLI support: unity-mcp hub editors, unity-mcp hub releases --limit 5, etc.

Files

File Purpose
Server/src/services/unity_hub.py Service layer — Hub detection, subprocess, parsing
Server/src/services/tools/manage_unity_hub.py MCP tool (thin wrapper)
Server/src/cli/commands/unity_hub.py CLI commands
Server/src/cli/main.py CLI registration (1 line)
Server/src/services/registry/tool_registry.py Tool group registration (1 line)

Design Decisions

  • Single multi-action tool following manage_packages pattern
  • No Unity transport — subprocess only, since Hub CLI runs on host
  • No C# changes — purely server-side
  • Confirmation via confirm param rather than project's Unity-routed confirmation utility (since this doesn't go through Unity)

Tested On

  • macOS (Apple Silicon), Unity Hub installed at default path
  • list_installed_editors: correctly parses 6000.3.9f1, 6000.3.10f1
  • list_available_releases: correctly parses alpha/beta/stable channels
  • get_install_path: returns /Applications/Unity/Hub/Editor

Test plan

  • Verify Hub detection on macOS
  • Verify Hub detection on Windows
  • Verify Hub detection on Linux
  • Test list_installed_editors with multiple installed versions
  • Test list_available_releases with --limit
  • Test install_editor confirmation gate (confirm=false should return prompt)
  • Test install_modules with multiple modules
  • Test with UNITY_HUB_PATH env override
  • Test when Hub is not installed (graceful error)

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

  • Introduce a manage_unity_hub MCP tool that can query and manage Unity Hub and Unity Editor installations on the host machine.
  • Add a unity_hub CLI command group to inspect Hub info, list installed and available editor versions, manage install paths, and trigger editor/module installs.

Enhancements:

  • Extend the tool registry with a new unity_hub group description for host-side Hub and editor management.

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
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efb18039-729e-436d-895a-9a54987cbd10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 6, 2026

Reviewer's Guide

Adds 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 CLI

sequenceDiagram
    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
Loading

Class diagram for manage_unity_hub tool, unity_hub service, and CLI commands

classDiagram
    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
Loading

File-Level Changes

Change Details Files
Introduce a host-side Unity Hub service module that discovers the Hub executable, runs CLI commands with robust error handling/timeouts, and parses editor/release listings into structured data.
  • Add OS-specific Hub path resolution with UNITY_HUB_PATH override and fallback to PATH discovery.
  • Implement async subprocess execution helper that invokes Unity Hub in headless mode with configurable timeouts and structured error reporting for missing Hub, timeouts, non-zero exit codes, and generic subprocess failures.
  • Provide parsers to convert editors --installed output into version/path entries and editors --releases output into version/channel (LTS/Tech) entries with optional limiting.
Server/src/services/unity_hub.py
Add an MCP manage_unity_hub multi-action tool that exposes read-only Hub queries and state-changing editor/install-path operations with a confirmation gate and structured responses.
  • Define supported actions, distinguishing read-only from state-changing operations, and enforce a confirm parameter requirement before running mutating commands.
  • Implement per-action handlers that call the Unity Hub service functions, adapt their results into tool responses, and include raw CLI output where relevant for robustness.
  • Add a human-readable confirmation message builder and a get_hub_info helper that returns Hub detection and host OS details.
Server/src/services/tools/manage_unity_hub.py
Expose Unity Hub functionality through the project CLI with a new unity-mcp hub command group for info, editors, releases, install-path, install, and install-modules operations.
  • Add a Click command group hub that runs on the host, with subcommands that wrap the Unity Hub service functions and render either parsed human-friendly output or JSON error payloads.
  • Introduce a small async runner helper to safely invoke async service functions from synchronous Click commands, handling both no-loop and already-running-loop cases via a thread pool.
  • Implement interactive confirmations for dangerous CLI actions (changing install path, installing editors/modules) and use shared print utilities for success/info messages.
Server/src/cli/commands/unity_hub.py
Wire the new Unity Hub CLI commands and MCP tool group into the existing application registration.
  • Register the cli.commands.unity_hub module in the main CLI command list so unity-mcp hub ... becomes available.
  • Add a unity_hub entry to the tool group registry with a descriptive label for host-side Hub/editor management tools.
Server/src/cli/main.py
Server/src/services/registry/tool_registry.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

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 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.
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>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
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
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