Skip to content

Commit 5b9907b

Browse files
authored
fix: resolve MCP tool eye icon state and hide in chat context (#4993) (#4994)
1 parent 6a9503d commit 5b9907b

File tree

3 files changed

+71
-20
lines changed

3 files changed

+71
-20
lines changed

webview-ui/src/components/chat/McpExecution.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ export const McpExecution = ({
242242
serverName={useMcpServer.serverName}
243243
serverSource={server?.source}
244244
alwaysAllowMcp={alwaysAllowMcp}
245+
isInChatContext={true}
245246
/>
246247
</div>
247248
)}
@@ -256,6 +257,7 @@ export const McpExecution = ({
256257
serverName={serverName}
257258
serverSource={undefined}
258259
alwaysAllowMcp={alwaysAllowMcp}
260+
isInChatContext={true}
259261
/>
260262
</div>
261263
)}

webview-ui/src/components/mcp/McpToolRow.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ type McpToolRowProps = {
1010
serverName?: string
1111
serverSource?: "global" | "project"
1212
alwaysAllowMcp?: boolean
13+
isInChatContext?: boolean
1314
}
1415

15-
const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp }: McpToolRowProps) => {
16+
const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp, isInChatContext = false }: McpToolRowProps) => {
1617
const { t } = useAppTranslation()
1718
const handleAlwaysAllowChange = () => {
1819
if (!serverName) return
@@ -66,25 +67,27 @@ const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp }: McpToolR
6667
</VSCodeCheckbox>
6768
)}
6869

69-
{/* Enabled eye button */}
70-
<button
71-
role="button"
72-
aria-pressed={tool.enabledForPrompt}
73-
aria-label={t("mcp:tool.togglePromptInclusion")}
74-
className={`p-1 rounded hover:bg-vscode-toolbar-hoverBackground transition-colors ${
75-
tool.enabledForPrompt
76-
? "text-vscode-foreground"
77-
: "text-vscode-descriptionForeground opacity-60"
78-
}`}
79-
onClick={handleEnabledForPromptChange}
80-
data-tool-prompt-toggle={tool.name}
81-
title={t("mcp:tool.togglePromptInclusion")}>
82-
<span
83-
className={`codicon ${
84-
tool.enabledForPrompt ? "codicon-eye" : "codicon-eye-closed"
85-
} text-base`}
86-
/>
87-
</button>
70+
{/* Enabled eye button - only show in settings context */}
71+
{!isInChatContext && (
72+
<button
73+
role="button"
74+
aria-pressed={tool.enabledForPrompt}
75+
aria-label={t("mcp:tool.togglePromptInclusion")}
76+
className={`p-1 rounded hover:bg-vscode-toolbar-hoverBackground transition-colors ${
77+
tool.enabledForPrompt
78+
? "text-vscode-foreground"
79+
: "text-vscode-descriptionForeground opacity-60"
80+
}`}
81+
onClick={handleEnabledForPromptChange}
82+
data-tool-prompt-toggle={tool.name}
83+
title={t("mcp:tool.togglePromptInclusion")}>
84+
<span
85+
className={`codicon ${
86+
tool.enabledForPrompt ? "codicon-eye-closed" : "codicon-eye"
87+
} text-base`}
88+
/>
89+
</button>
90+
)}
8891
</div>
8992
)}
9093
</div>

webview-ui/src/components/mcp/__tests__/McpToolRow.spec.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ vi.mock("@src/i18n/TranslationContext", () => ({
1212
"mcp:tool.alwaysAllow": "Always allow",
1313
"mcp:tool.parameters": "Parameters",
1414
"mcp:tool.noDescription": "No description",
15+
"mcp:tool.togglePromptInclusion": "Toggle prompt inclusion",
1516
}
1617
return translations[key] || key
1718
},
@@ -48,6 +49,7 @@ describe("McpToolRow", () => {
4849
name: "test-tool",
4950
description: "A test tool",
5051
alwaysAllow: false,
52+
enabledForPrompt: true,
5153
}
5254

5355
beforeEach(() => {
@@ -141,4 +143,48 @@ describe("McpToolRow", () => {
141143
expect(screen.getByText("First parameter")).toBeInTheDocument()
142144
expect(screen.getByText("Second parameter")).toBeInTheDocument()
143145
})
146+
147+
it("shows eye button when serverName is provided and not in chat context", () => {
148+
render(<McpToolRow tool={mockTool} serverName="test-server" />)
149+
150+
const eyeButton = screen.getByRole("button", { name: "Toggle prompt inclusion" })
151+
expect(eyeButton).toBeInTheDocument()
152+
})
153+
154+
it("hides eye button when isInChatContext is true", () => {
155+
render(<McpToolRow tool={mockTool} serverName="test-server" isInChatContext={true} />)
156+
157+
const eyeButton = screen.queryByRole("button", { name: "Toggle prompt inclusion" })
158+
expect(eyeButton).not.toBeInTheDocument()
159+
})
160+
161+
it("shows correct eye icon based on enabledForPrompt state", () => {
162+
// Test when enabled (should show eye-closed icon)
163+
const { rerender } = render(<McpToolRow tool={mockTool} serverName="test-server" />)
164+
165+
let eyeIcon = screen.getByRole("button", { name: "Toggle prompt inclusion" }).querySelector("span")
166+
expect(eyeIcon).toHaveClass("codicon-eye-closed")
167+
168+
// Test when disabled (should show eye icon)
169+
const disabledTool = { ...mockTool, enabledForPrompt: false }
170+
rerender(<McpToolRow tool={disabledTool} serverName="test-server" />)
171+
172+
eyeIcon = screen.getByRole("button", { name: "Toggle prompt inclusion" }).querySelector("span")
173+
expect(eyeIcon).toHaveClass("codicon-eye")
174+
})
175+
176+
it("sends message to toggle enabledForPrompt when eye button is clicked", () => {
177+
render(<McpToolRow tool={mockTool} serverName="test-server" />)
178+
179+
const eyeButton = screen.getByRole("button", { name: "Toggle prompt inclusion" })
180+
fireEvent.click(eyeButton)
181+
182+
expect(vscode.postMessage).toHaveBeenCalledWith({
183+
type: "toggleToolEnabledForPrompt",
184+
serverName: "test-server",
185+
source: "global",
186+
toolName: "test-tool",
187+
isEnabled: false,
188+
})
189+
})
144190
})

0 commit comments

Comments
 (0)