diff --git a/ui/desktop/src/components/GooseMessage.tsx b/ui/desktop/src/components/GooseMessage.tsx
index 66c58074a414..cbcf47fee236 100644
--- a/ui/desktop/src/components/GooseMessage.tsx
+++ b/ui/desktop/src/components/GooseMessage.tsx
@@ -10,6 +10,7 @@ import {
getToolResponses,
getToolConfirmationContent,
getElicitationContent,
+ getPendingToolConfirmationIds,
NotificationEvent,
} from '../types/message';
import { Message } from '../api';
@@ -99,6 +100,8 @@ export default function GooseMessage({
return responseMap;
}, [messages, messageIndex, toolRequests]);
+ const pendingConfirmationIds = getPendingToolConfirmationIds(messages);
+
return (
@@ -157,6 +160,7 @@ export default function GooseMessage({
toolResponse={toolResponsesMap.get(toolRequest.id)}
notifications={toolCallNotifications.get(toolRequest.id)}
isStreamingMessage={isStreaming}
+ isPendingApproval={pendingConfirmationIds.has(toolRequest.id)}
append={append}
/>
diff --git a/ui/desktop/src/components/ToolCallWithResponse.tsx b/ui/desktop/src/components/ToolCallWithResponse.tsx
index bfe8baeab788..58ba03be3a8f 100644
--- a/ui/desktop/src/components/ToolCallWithResponse.tsx
+++ b/ui/desktop/src/components/ToolCallWithResponse.tsx
@@ -55,6 +55,7 @@ interface ToolCallWithResponseProps {
toolResponse?: ToolResponseMessageContent;
notifications?: NotificationEvent[];
isStreamingMessage?: boolean;
+ isPendingApproval: boolean;
append?: (value: string) => void;
}
@@ -106,10 +107,8 @@ function McpAppWrapper({
? requestWithMeta.toolCall.value.arguments
: undefined;
- // Memoize toolInput to prevent unnecessary re-renders
const toolInput = useMemo(() => ({ arguments: toolArguments || {} }), [toolArguments]);
- // Memoize toolResult to prevent unnecessary re-renders
const toolResult = useMemo(() => {
if (!toolResponse) return undefined;
const resultWithMeta = toolResponse.toolResult as ToolResultWithMeta;
@@ -149,6 +148,7 @@ export default function ToolCallWithResponse({
toolResponse,
notifications,
isStreamingMessage,
+ isPendingApproval,
append,
}: ToolCallWithResponseProps) {
// Handle both the wrapped ToolResult format and the unwrapped format
@@ -169,6 +169,8 @@ export default function ToolCallWithResponse({
requestWithMeta._meta?.ui?.resourceUri || resultWithMeta?.value?._meta?.ui?.resourceUri
);
+ const shouldShowMcpContent = !isPendingApproval;
+
return (
<>
{/* MCP UI — Inline */}
- {!hasMcpAppResourceURI &&
+ {shouldShowMcpContent &&
+ !hasMcpAppResourceURI &&
toolResponse?.toolResult &&
getToolResultContent(toolResponse.toolResult).map((content, index) => {
const resourceContent = isEmbeddedResource(content)
@@ -210,7 +213,8 @@ export default function ToolCallWithResponse({
}
})}
- {hasMcpAppResourceURI && sessionId && (
+ {/* MCP App */}
+ {shouldShowMcpContent && hasMcpAppResourceURI && sessionId && (
= ({
isCancelledMessage={
toolResponsesMap.get(toolRequest.id) == undefined
}
+ isPendingApproval={false}
key={toolRequest.id}
toolRequest={toolRequest}
toolResponse={toolResponsesMap.get(toolRequest.id)}
diff --git a/ui/desktop/src/types/message.ts b/ui/desktop/src/types/message.ts
index fcb9b0cbd271..ba4425fddeaf 100644
--- a/ui/desktop/src/types/message.ts
+++ b/ui/desktop/src/types/message.ts
@@ -73,6 +73,39 @@ export function getToolConfirmationContent(
);
}
+export function getToolConfirmationId(
+ content: ActionRequired & { type: 'actionRequired' }
+): string | undefined {
+ if (content.data.actionType === 'toolConfirmation') {
+ return content.data.id;
+ }
+ return undefined;
+}
+
+export function getPendingToolConfirmationIds(messages: Message[]): Set {
+ const pendingIds = new Set();
+ const respondedIds = new Set();
+
+ for (const message of messages) {
+ const responses = getToolResponses(message);
+ for (const response of responses) {
+ respondedIds.add(response.id);
+ }
+ }
+
+ for (const message of messages) {
+ const confirmation = getToolConfirmationContent(message);
+ if (confirmation) {
+ const confirmationId = getToolConfirmationId(confirmation);
+ if (confirmationId && !respondedIds.has(confirmationId)) {
+ pendingIds.add(confirmationId);
+ }
+ }
+ }
+
+ return pendingIds;
+}
+
export function getElicitationContent(
message: Message
): (ActionRequired & { type: 'actionRequired' }) | undefined {