Skip to content

fix(mcp): resolve hub tool auto-approve to underlying server#13493

Merged
DeJeune merged 6 commits intomainfrom
DeJeune/fix-hub-auto-approve
Mar 16, 2026
Merged

fix(mcp): resolve hub tool auto-approve to underlying server#13493
DeJeune merged 6 commits intomainfrom
DeJeune/fix-hub-auto-approve

Conversation

@DeJeune
Copy link
Copy Markdown
Collaborator

@DeJeune DeJeune commented Mar 16, 2026

What this PR does

Before this PR:

When a user clicked "Auto-approve" on a hub tool (invoke/exec), the autoApprove function looked for a server with id === 'hub', found none, and silently returned without confirming the tool or persisting the auto-approve preference.

After this PR:

The autoApprove function resolves hub tools to their underlying server via resolveHubTool, then correctly updates disabledAutoApproveTools on the real server. If resolution fails or no server is found, the tool action is still confirmed (instead of silently dropped).

fixes: #13481

Why we need it and why it was done in this way

Hub tools use a virtual serverId of 'hub' which doesn't correspond to any real MCP server entry. The fix resolves the underlying server and tool name through the existing window.api.mcp.resolveHubTool IPC call, which is already used elsewhere in the codebase (e.g., aiCore/utils/mcp.ts).

The following tradeoffs were made:

  • Duplicated the disabledAutoApproveTools update logic in the hub resolution branch for clarity. This keeps the hub path self-contained and avoids restructuring the existing flow.

The following alternatives were considered:

  • Refactoring to share the update logic between hub and non-hub paths. Decided against it to keep the change minimal and focused on the bug fix.

Breaking changes

None.

Special notes for your reviewer

  • The autoApprove callback is now async (it already was via useCallback, this just adds await for the IPC call).
  • toolResponse was added to the useCallback dependency array since it's now referenced inside the callback.
  • Added comprehensive tests covering all hub resolution branches (success, null result, IPC error, missing server, missing args).

Checklist

Release note

NONE

When auto-approving hub tools (invoke/exec), the tool's serverId is
'hub' which doesn't match any real MCP server. This fix resolves the
underlying server via resolveHubTool and updates disabledAutoApproveTools
on the correct server. Also ensures the tool action is confirmed even
when no server is found, instead of silently returning.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
Copy link
Copy Markdown
Contributor

@cherry-ai-bot cherry-ai-bot bot left a comment

Choose a reason for hiding this comment

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

Thanks for tackling the hub auto-approve path and for adding thorough branch coverage around the resolution/fallback behavior. I found one remaining blocking issue: the persistence path now resolves hub tools to the underlying server, but the UI-side isAutoApproved calculation in useMcpToolApproval still only checks tool.serverId directly. For hub invoke / exec tools, that means the execution layer can auto-approve correctly while the hook still thinks the tool is not auto-approved and may render the wrong waiting state. Please align the hook's auto-approved detection with the same hub-resolution logic used in the execution and persistence paths before merge.

The isAutoApproved UI state was not resolving hub invoke/exec tools to
their underlying server, causing the approval state machine to be
inconsistent between the execution layer and rendering. Extract a shared
resolveHubToolServer helper and add a useEffect to asynchronously resolve
hub tools for the UI auto-approve state, matching the same logic used in
the execution layer.

Also simplify the autoApprove callback to use the shared helper,
eliminating duplicated hub resolution logic.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
When multiple tool calls arrive in a single turn, all check auto-approve
simultaneously and block on requestToolConfirmation. Clicking auto-approve
on one tool only confirmed that single tool. Now the execution layer
registers tool-id-to-name mappings and calls confirmSameNameTools after
confirmation, matching the legacy middleware behavior. For hub invoke/exec
tools, the underlying tool name is used as the mapping key so only tools
targeting the same underlying server are batch-confirmed.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
Copy link
Copy Markdown
Contributor

@cherry-ai-bot cherry-ai-bot bot left a comment

Choose a reason for hiding this comment

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

The previous blocking issue (UI isAutoApproved not resolving hub tools) has been addressed. The new commit adds batch-confirm for same-name tools, and the comprehensive test coverage confirms the hub resolution logic works for both UI state and persistence. No remaining blocking issues. Approving.

@DeJeune DeJeune requested a review from eeee0717 March 16, 2026 11:52
resolveHubToolName is synchronous and returns null when toolNameMapping
has been cleared (e.g. after invalidateCache). Unlike callMcpTool which
lazily refreshes the mapping, the ResolveHubTool IPC handler did not.

This caused both the execution layer and the UI auto-approve callback
to silently fail hub tool resolution, falling back to updating the hub
server's disabledAutoApproveTools — which isToolAutoApproved ignores
for hub servers (invoke/exec are hardcoded as not auto-approved).

Add resolveHubToolNameAsync that mirrors callMcpTool's lazy refresh
pattern, and use it in the IPC handler.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
@DeJeune DeJeune requested a review from 0xfullex as a code owner March 16, 2026 12:37
DeJeune and others added 2 commits March 16, 2026 20:42
Replace dynamic import with static import in the IPC handler.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
…ndler

Reverts changes to ipc.ts to avoid code owner review. The
resolveHubToolNameAsync helper remains in mcp-bridge.ts for future use.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: suyao <[email protected]>
@DeJeune DeJeune merged commit af51a27 into main Mar 16, 2026
6 checks passed
@DeJeune DeJeune deleted the DeJeune/fix-hub-auto-approve branch March 16, 2026 12:57
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.

[Bug]: MCP requires clicking every time, auto-approve not working, no response after clicking

2 participants