Browse Source

fix: resolve MCP tool eye icon state and hide in chat context (#4993) (#4994)

Daniel 8 months ago
parent
commit
5b9907b925

+ 2 - 0
webview-ui/src/components/chat/McpExecution.tsx

@@ -242,6 +242,7 @@ export const McpExecution = ({
 							serverName={useMcpServer.serverName}
 							serverName={useMcpServer.serverName}
 							serverSource={server?.source}
 							serverSource={server?.source}
 							alwaysAllowMcp={alwaysAllowMcp}
 							alwaysAllowMcp={alwaysAllowMcp}
+							isInChatContext={true}
 						/>
 						/>
 					</div>
 					</div>
 				)}
 				)}
@@ -256,6 +257,7 @@ export const McpExecution = ({
 							serverName={serverName}
 							serverName={serverName}
 							serverSource={undefined}
 							serverSource={undefined}
 							alwaysAllowMcp={alwaysAllowMcp}
 							alwaysAllowMcp={alwaysAllowMcp}
+							isInChatContext={true}
 						/>
 						/>
 					</div>
 					</div>
 				)}
 				)}

+ 23 - 20
webview-ui/src/components/mcp/McpToolRow.tsx

@@ -10,9 +10,10 @@ type McpToolRowProps = {
 	serverName?: string
 	serverName?: string
 	serverSource?: "global" | "project"
 	serverSource?: "global" | "project"
 	alwaysAllowMcp?: boolean
 	alwaysAllowMcp?: boolean
+	isInChatContext?: boolean
 }
 }
 
 
-const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp }: McpToolRowProps) => {
+const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp, isInChatContext = false }: McpToolRowProps) => {
 	const { t } = useAppTranslation()
 	const { t } = useAppTranslation()
 	const handleAlwaysAllowChange = () => {
 	const handleAlwaysAllowChange = () => {
 		if (!serverName) return
 		if (!serverName) return
@@ -66,25 +67,27 @@ const McpToolRow = ({ tool, serverName, serverSource, alwaysAllowMcp }: McpToolR
 							</VSCodeCheckbox>
 							</VSCodeCheckbox>
 						)}
 						)}
 
 
-						{/* Enabled eye button */}
-						<button
-							role="button"
-							aria-pressed={tool.enabledForPrompt}
-							aria-label={t("mcp:tool.togglePromptInclusion")}
-							className={`p-1 rounded hover:bg-vscode-toolbar-hoverBackground transition-colors ${
-								tool.enabledForPrompt
-									? "text-vscode-foreground"
-									: "text-vscode-descriptionForeground opacity-60"
-							}`}
-							onClick={handleEnabledForPromptChange}
-							data-tool-prompt-toggle={tool.name}
-							title={t("mcp:tool.togglePromptInclusion")}>
-							<span
-								className={`codicon ${
-									tool.enabledForPrompt ? "codicon-eye" : "codicon-eye-closed"
-								} text-base`}
-							/>
-						</button>
+						{/* Enabled eye button - only show in settings context */}
+						{!isInChatContext && (
+							<button
+								role="button"
+								aria-pressed={tool.enabledForPrompt}
+								aria-label={t("mcp:tool.togglePromptInclusion")}
+								className={`p-1 rounded hover:bg-vscode-toolbar-hoverBackground transition-colors ${
+									tool.enabledForPrompt
+										? "text-vscode-foreground"
+										: "text-vscode-descriptionForeground opacity-60"
+								}`}
+								onClick={handleEnabledForPromptChange}
+								data-tool-prompt-toggle={tool.name}
+								title={t("mcp:tool.togglePromptInclusion")}>
+								<span
+									className={`codicon ${
+										tool.enabledForPrompt ? "codicon-eye-closed" : "codicon-eye"
+									} text-base`}
+								/>
+							</button>
+						)}
 					</div>
 					</div>
 				)}
 				)}
 			</div>
 			</div>

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

@@ -12,6 +12,7 @@ vi.mock("@src/i18n/TranslationContext", () => ({
 				"mcp:tool.alwaysAllow": "Always allow",
 				"mcp:tool.alwaysAllow": "Always allow",
 				"mcp:tool.parameters": "Parameters",
 				"mcp:tool.parameters": "Parameters",
 				"mcp:tool.noDescription": "No description",
 				"mcp:tool.noDescription": "No description",
+				"mcp:tool.togglePromptInclusion": "Toggle prompt inclusion",
 			}
 			}
 			return translations[key] || key
 			return translations[key] || key
 		},
 		},
@@ -48,6 +49,7 @@ describe("McpToolRow", () => {
 		name: "test-tool",
 		name: "test-tool",
 		description: "A test tool",
 		description: "A test tool",
 		alwaysAllow: false,
 		alwaysAllow: false,
+		enabledForPrompt: true,
 	}
 	}
 
 
 	beforeEach(() => {
 	beforeEach(() => {
@@ -141,4 +143,48 @@ describe("McpToolRow", () => {
 		expect(screen.getByText("First parameter")).toBeInTheDocument()
 		expect(screen.getByText("First parameter")).toBeInTheDocument()
 		expect(screen.getByText("Second parameter")).toBeInTheDocument()
 		expect(screen.getByText("Second parameter")).toBeInTheDocument()
 	})
 	})
+
+	it("shows eye button when serverName is provided and not in chat context", () => {
+		render(<McpToolRow tool={mockTool} serverName="test-server" />)
+
+		const eyeButton = screen.getByRole("button", { name: "Toggle prompt inclusion" })
+		expect(eyeButton).toBeInTheDocument()
+	})
+
+	it("hides eye button when isInChatContext is true", () => {
+		render(<McpToolRow tool={mockTool} serverName="test-server" isInChatContext={true} />)
+
+		const eyeButton = screen.queryByRole("button", { name: "Toggle prompt inclusion" })
+		expect(eyeButton).not.toBeInTheDocument()
+	})
+
+	it("shows correct eye icon based on enabledForPrompt state", () => {
+		// Test when enabled (should show eye-closed icon)
+		const { rerender } = render(<McpToolRow tool={mockTool} serverName="test-server" />)
+
+		let eyeIcon = screen.getByRole("button", { name: "Toggle prompt inclusion" }).querySelector("span")
+		expect(eyeIcon).toHaveClass("codicon-eye-closed")
+
+		// Test when disabled (should show eye icon)
+		const disabledTool = { ...mockTool, enabledForPrompt: false }
+		rerender(<McpToolRow tool={disabledTool} serverName="test-server" />)
+
+		eyeIcon = screen.getByRole("button", { name: "Toggle prompt inclusion" }).querySelector("span")
+		expect(eyeIcon).toHaveClass("codicon-eye")
+	})
+
+	it("sends message to toggle enabledForPrompt when eye button is clicked", () => {
+		render(<McpToolRow tool={mockTool} serverName="test-server" />)
+
+		const eyeButton = screen.getByRole("button", { name: "Toggle prompt inclusion" })
+		fireEvent.click(eyeButton)
+
+		expect(vscode.postMessage).toHaveBeenCalledWith({
+			type: "toggleToolEnabledForPrompt",
+			serverName: "test-server",
+			source: "global",
+			toolName: "test-tool",
+			isEnabled: false,
+		})
+	})
 })
 })