Skip to content

fix: enforce tool toggle checks in batch_execute#741

Merged
dsarno merged 1 commit intoCoplayDev:betafrom
dsarno:fix/batch-execute-tool-toggle
Feb 13, 2026
Merged

fix: enforce tool toggle checks in batch_execute#741
dsarno merged 1 commit intoCoplayDev:betafrom
dsarno:fix/batch-execute-tool-toggle

Conversation

@dsarno
Copy link
Collaborator

@dsarno dsarno commented Feb 13, 2026

Summary

  • batch_execute was bypassing disabled-tool checks by calling CommandRegistry.InvokeCommandAsync directly
  • Adds the same IsToolEnabled guard that TransportCommandDispatcher already uses
  • Disabled tools now return "Tool 'X' is disabled in the Unity Editor." errors in batch results

Test plan

  • 621 EditMode tests pass (577 passed, 44 skipped)
  • Manually verified: disabled tools blocked in batch, enabled tools still work

🤖 Generated with Claude Code

Summary by Sourcery

Bug Fixes:

  • Prevent batch tool execution from bypassing existing disabled-tool checks by validating tool enablement before invocation.

Summary by CodeRabbit

  • Bug Fixes
    • Added validation to prevent execution of commands when tools are disabled in the Unity Editor. Disabled tools now properly block command execution, recording the attempt as a failed invocation with detailed error information. Failure counters are automatically updated, ensuring consistent and accurate tracking of command execution results throughout your workflow.

batch_execute was bypassing disabled-tool checks by calling
CommandRegistry.InvokeCommandAsync directly. Add the same
IsToolEnabled guard that TransportCommandDispatcher uses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 13, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds a disabled-tool guard to batch_execute so batch tool invocations respect tool enablement and surface a consistent error when blocked.

Sequence diagram for batch_execute tool invocation with disabled-tool guard

sequenceDiagram
    participant BatchExecute
    participant ToolDiscovery
    participant CommandRegistry

    loop For_each_tool_in_batch
        BatchExecute->>ToolDiscovery: GetToolMetadata(toolName)
        alt ToolMetadata_exists
            BatchExecute->>ToolDiscovery: IsToolEnabled(toolName)
            alt Tool_disabled
                BatchExecute->>BatchExecute: Increment_invocationFailureCount
                BatchExecute->>BatchExecute: Set_anyCommandFailed_true
                BatchExecute->>BatchExecute: Add_error_result_with_ErrorResponse
                alt failFast_true
                    BatchExecute->>BatchExecute: Break_loop
                else failFast_false
                    BatchExecute->>BatchExecute: Continue_to_next_tool
                end
            else Tool_enabled
                BatchExecute->>CommandRegistry: InvokeCommandAsync(toolName, commandParams)
                CommandRegistry-->>BatchExecute: result
                BatchExecute->>BatchExecute: Add_success_result
            end
        else ToolMetadata_missing
            BatchExecute->>BatchExecute: Handle_missing_tool_metadata
        end
    end
Loading

Updated class diagram for BatchExecute disabled-tool guard integration

classDiagram
    class BatchExecute {
        +Task~object~ HandleCommand(JObject params)
        -int invocationFailureCount
        -bool anyCommandFailed
        -bool failFast
    }

    class MCPServiceLocator {
        +ToolDiscoveryService ToolDiscovery
    }

    class ToolDiscoveryService {
        +ToolMetadata GetToolMetadata(string toolName)
        +bool IsToolEnabled(string toolName)
    }

    class ToolMetadata {
        +string Name
        +string Description
        +bool Enabled
    }

    class CommandRegistry {
        +Task~object~ InvokeCommandAsync(string toolName, JObject commandParams)
    }

    class ErrorResponse {
        +ErrorResponse(string message)
        +string Message
    }

    BatchExecute ..> MCPServiceLocator : uses
    MCPServiceLocator *-- ToolDiscoveryService : provides
    ToolDiscoveryService --> ToolMetadata : returns
    BatchExecute ..> ToolDiscoveryService : queries
    BatchExecute ..> CommandRegistry : invokes
    BatchExecute ..> ErrorResponse : creates
Loading

File-Level Changes

Change Details Files
Enforce tool-enabled checks in batch_execute before invoking tools.
  • Import MCPForUnity.Editor.Services to access MCPServiceLocator and tool discovery
  • Look up tool metadata for each requested tool name before invocation
  • If a tool exists but is disabled, increment failure counters, mark the batch as having failures, and append a structured error result indicating the tool is disabled in the Unity Editor
  • Honor the existing failFast flag by breaking the loop after the first disabled-tool failure when enabled
  • Only invoke CommandRegistry.InvokeCommandAsync when the tool is enabled or has no metadata
MCPForUnity/Editor/Tools/BatchExecute.cs

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds a pre-invocation validation check to BatchExecute that blocks command execution for disabled tools. When a disabled tool is detected, the command is marked as failed, failure counters increment, and the loop continues or breaks based on the failFast setting. A new import for MCPForUnity.Editor.Services enables tool state querying.

Changes

Cohort / File(s) Summary
Tool State Validation
MCPForUnity/Editor/Tools/BatchExecute.cs
Added pre-invocation check to validate tool enabled state before command execution. Disabled tools trigger failure recording, counter increments, and conditional loop continuation based on failFast flag. Introduces MCPForUnity.Editor.Services import for tool metadata access.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • PR #414: Introduces ToolDiscoveryService with IsToolEnabled/GetEnabledTools methods that enable the pre-invocation tool state validation added in this PR.
  • PR #531: Also modifies the command invocation loop in BatchExecute.cs, adding call-success detection and fail-fast behavior alongside this disabled-tool check.

Poem

🐰 Before commands leap and bound,
We check if tools are enabled, sound!
Disabled ones receive their rest,
While counters catch what failed the test.
A gentle guard, so swift and neat! ✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dsarno dsarno merged commit 0d2d10c into CoplayDev:beta Feb 13, 2026
1 of 2 checks passed
Copy link
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 left some high level feedback:

  • The new disabled-tool guard duplicates logic from TransportCommandDispatcher; consider extracting a shared helper or extension so the behavior and error messaging stay in sync in both call paths.
  • The toolMeta local is only used for a null check before calling IsToolEnabled; if IsToolEnabled already handles unknown tools safely, you can simplify by calling it directly without fetching metadata.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new disabled-tool guard duplicates logic from `TransportCommandDispatcher`; consider extracting a shared helper or extension so the behavior and error messaging stay in sync in both call paths.
- The `toolMeta` local is only used for a null check before calling `IsToolEnabled`; if `IsToolEnabled` already handles unknown tools safely, you can simplify by calling it directly without fetching metadata.

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.

@dsarno dsarno deleted the fix/batch-execute-tool-toggle branch February 13, 2026 04:28
msanatan pushed a commit to msanatan/unity-mcp that referenced this pull request Feb 25, 2026
batch_execute was bypassing disabled-tool checks by calling
CommandRegistry.InvokeCommandAsync directly. Add the same
IsToolEnabled guard that TransportCommandDispatcher uses.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
msanatan pushed a commit to msanatan/unity-mcp that referenced this pull request Feb 25, 2026
batch_execute was bypassing disabled-tool checks by calling
CommandRegistry.InvokeCommandAsync directly. Add the same
IsToolEnabled guard that TransportCommandDispatcher uses.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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