diff --git a/packages/types/src/mcp.ts b/packages/types/src/mcp.ts index 92e238efbb1..f1bfde325de 100644 --- a/packages/types/src/mcp.ts +++ b/packages/types/src/mcp.ts @@ -1,5 +1,11 @@ import { z } from "zod" +/** + * Maximum number of MCP tools that can be enabled before showing a warning. + * LLMs tend to perform poorly when given too many tools to choose from. + */ +export const MAX_MCP_TOOLS_THRESHOLD = 60 + /** * McpServerUse */ @@ -128,3 +134,53 @@ export type McpErrorEntry = { timestamp: number level: "error" | "warn" | "info" } + +/** + * Result of counting enabled MCP tools across servers. + */ +export interface EnabledMcpToolsCount { + /** Number of enabled and connected MCP servers */ + enabledServerCount: number + /** Total number of enabled tools across all enabled servers */ + enabledToolCount: number +} + +/** + * Count the number of enabled MCP tools across all enabled and connected servers. + * This is a pure function that can be used in both backend and frontend contexts. + * + * @param servers - Array of MCP server objects + * @returns Object with enabledToolCount and enabledServerCount + * + * @example + * const { enabledToolCount, enabledServerCount } = countEnabledMcpTools(mcpServers) + * if (enabledToolCount > MAX_MCP_TOOLS_THRESHOLD) { + * // Show warning + * } + */ +export function countEnabledMcpTools(servers: McpServer[]): EnabledMcpToolsCount { + let serverCount = 0 + let toolCount = 0 + + for (const server of servers) { + // Skip disabled servers + if (server.disabled) continue + + // Skip servers that are not connected + if (server.status !== "connected") continue + + serverCount++ + + // Count enabled tools on this server + if (server.tools) { + for (const tool of server.tools) { + // Tool is enabled if enabledForPrompt is undefined (default) or true + if (tool.enabledForPrompt !== false) { + toolCount++ + } + } + } + } + + return { enabledToolCount: toolCount, enabledServerCount: serverCount } +} diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts index 109cd842bac..d6dd46099ad 100644 --- a/packages/types/src/message.ts +++ b/packages/types/src/message.ts @@ -149,6 +149,7 @@ export function isNonBlockingAsk(ask: ClineAsk): ask is NonBlockingAsk { * - `condense_context`: Context condensation/summarization has started * - `condense_context_error`: Error occurred during context condensation * - `codebase_search_result`: Results from searching the codebase + * - `too_many_tools_warning`: Warning that too many MCP tools are enabled, which may confuse the LLM */ export const clineSays = [ "error", @@ -180,6 +181,7 @@ export const clineSays = [ "sliding_window_truncation", "codebase_search_result", "user_edit_todos", + "too_many_tools_warning", ] as const export const clineSaySchema = z.enum(clineSays) diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index 3acb6c24918..e933fbff2cd 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -53,6 +53,8 @@ import { MIN_CHECKPOINT_TIMEOUT_SECONDS, TOOL_PROTOCOL, ConsecutiveMistakeError, + MAX_MCP_TOOLS_THRESHOLD, + countEnabledMcpTools, } from "@roo-code/types" import { TelemetryService } from "@roo-code/telemetry" import { CloudService, BridgeOrchestrator } from "@roo-code/cloud" @@ -1832,6 +1834,37 @@ export class Task extends EventEmitter implements TaskLike { // Lifecycle // Start / Resume / Abort / Dispose + /** + * Get enabled MCP tools count for this task. + * Returns the count along with the number of servers contributing. + * + * @returns Object with enabledToolCount and enabledServerCount + */ + private async getEnabledMcpToolsCount(): Promise<{ enabledToolCount: number; enabledServerCount: number }> { + try { + const provider = this.providerRef.deref() + if (!provider) { + return { enabledToolCount: 0, enabledServerCount: 0 } + } + + const { mcpEnabled } = (await provider.getState()) ?? {} + if (!(mcpEnabled ?? true)) { + return { enabledToolCount: 0, enabledServerCount: 0 } + } + + const mcpHub = await McpServerManager.getInstance(provider.context, provider) + if (!mcpHub) { + return { enabledToolCount: 0, enabledServerCount: 0 } + } + + const servers = mcpHub.getServers() + return countEnabledMcpTools(servers) + } catch (error) { + console.error("[Task#getEnabledMcpToolsCount] Error counting MCP tools:", error) + return { enabledToolCount: 0, enabledServerCount: 0 } + } + } + private async startTask(task?: string, images?: string[]): Promise { if (this.enableBridge) { try { @@ -1858,6 +1891,24 @@ export class Task extends EventEmitter implements TaskLike { await this.providerRef.deref()?.postStateToWebview() await this.say("text", task, images) + + // Check for too many MCP tools and warn the user + const { enabledToolCount, enabledServerCount } = await this.getEnabledMcpToolsCount() + if (enabledToolCount > MAX_MCP_TOOLS_THRESHOLD) { + await this.say( + "too_many_tools_warning", + JSON.stringify({ + toolCount: enabledToolCount, + serverCount: enabledServerCount, + threshold: MAX_MCP_TOOLS_THRESHOLD, + }), + undefined, + undefined, + undefined, + undefined, + { isNonInteractive: true }, + ) + } this.isInitialized = true let imageBlocks: Anthropic.ImageBlockParam[] = formatResponse.imageBlocks(images) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 24749bb4191..eb00cd3671d 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -32,6 +32,7 @@ import { ReasoningBlock } from "./ReasoningBlock" import Thumbnails from "../common/Thumbnails" import ImageBlock from "../common/ImageBlock" import ErrorRow from "./ErrorRow" +import WarningRow from "./WarningRow" import McpResourceRow from "../mcp/McpResourceRow" @@ -1512,6 +1513,33 @@ export const ChatRowContent = ({ case "browser_action_result": // Handled by BrowserSessionRow; prevent raw JSON (action/result) from rendering here return null + case "too_many_tools_warning": { + const warningData = safeJsonParse<{ + toolCount: number + serverCount: number + threshold: number + }>(message.text || "{}") + if (!warningData) return null + const toolsPart = t("chat:tooManyTools.toolsPart", { count: warningData.toolCount }) + const serversPart = t("chat:tooManyTools.serversPart", { count: warningData.serverCount }) + return ( + + window.postMessage( + { type: "action", action: "settingsButtonClicked", values: { section: "mcp" } }, + "*", + ) + } + /> + ) + } default: return ( <> diff --git a/webview-ui/src/components/chat/ErrorRow.tsx b/webview-ui/src/components/chat/ErrorRow.tsx index 50e7c67b5bb..70253504247 100644 --- a/webview-ui/src/components/chat/ErrorRow.tsx +++ b/webview-ui/src/components/chat/ErrorRow.tsx @@ -266,11 +266,11 @@ export const ErrorRow = memo( )} -
+

{message} {formattedErrorDetails && ( diff --git a/webview-ui/src/components/chat/TooManyToolsWarning.tsx b/webview-ui/src/components/chat/TooManyToolsWarning.tsx new file mode 100644 index 00000000000..697fad19ae4 --- /dev/null +++ b/webview-ui/src/components/chat/TooManyToolsWarning.tsx @@ -0,0 +1,39 @@ +import React, { useCallback } from "react" +import { useAppTranslation } from "@/i18n/TranslationContext" +import { useTooManyTools } from "@src/hooks/useTooManyTools" +import WarningRow from "./WarningRow" + +/** + * Displays a warning when the user has too many MCP tools enabled. + * LLMs get confused when offered too many tools, which can lead to errors. + * + * The warning is shown when: + * - The total number of enabled tools across all enabled MCP servers exceeds the threshold + * + * @example + * + */ +export const TooManyToolsWarning: React.FC = () => { + const { t } = useAppTranslation() + const { isOverThreshold, title, message } = useTooManyTools() + + const handleOpenMcpSettings = useCallback(() => { + window.postMessage({ type: "action", action: "settingsButtonClicked", values: { section: "mcp" } }, "*") + }, []) + + // Don't show warning if under threshold + if (!isOverThreshold) { + return null + } + + return ( + + ) +} + +export default TooManyToolsWarning diff --git a/webview-ui/src/components/chat/WarningRow.tsx b/webview-ui/src/components/chat/WarningRow.tsx new file mode 100644 index 00000000000..3fe4e900769 --- /dev/null +++ b/webview-ui/src/components/chat/WarningRow.tsx @@ -0,0 +1,77 @@ +import React from "react" +import { TriangleAlert, BookOpenText } from "lucide-react" +import { useAppTranslation } from "@/i18n/TranslationContext" +import { vscode } from "@src/utils/vscode" + +export interface WarningRowProps { + title: string + message: string + docsURL?: string + actionText?: string + onAction?: () => void +} + +/** + * A generic warning row component that displays a warning icon, title, and message. + * Optionally includes a documentation link and/or an action link. + * + * @param title - The warning title displayed in bold + * @param message - The warning message displayed below the title + * @param docsURL - Optional documentation link URL (shown as "Learn more" with book icon) + * @param actionText - Optional text for an action link appended to the message + * @param onAction - Optional callback when the action link is clicked + * + * @example + * openSettings()} + * /> + */ +export const WarningRow: React.FC = ({ title, message, docsURL, actionText, onAction }) => { + const { t } = useAppTranslation() + + return ( +

+ ) +} + +export default WarningRow diff --git a/webview-ui/src/components/chat/__tests__/TooManyToolsWarning.spec.tsx b/webview-ui/src/components/chat/__tests__/TooManyToolsWarning.spec.tsx new file mode 100644 index 00000000000..85560201da9 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/TooManyToolsWarning.spec.tsx @@ -0,0 +1,296 @@ +import { render, screen, fireEvent } from "@/utils/test-utils" +import { MAX_MCP_TOOLS_THRESHOLD } from "@roo-code/types" + +import { TooManyToolsWarning } from "../TooManyToolsWarning" + +// Mock vscode webview messaging +vi.mock("@/utils/vscode", () => ({ + vscode: { + postMessage: vi.fn(), + }, +})) + +// Mock ExtensionState context with variable mcpServers +const mockMcpServers = vi.fn() + +vi.mock("@/context/ExtensionStateContext", () => ({ + useExtensionState: () => ({ + mcpServers: mockMcpServers(), + }), +})) + +// Mock i18n TranslationContext +vi.mock("@/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string, params?: Record) => { + if (key === "chat:tooManyTools.title") { + return "Too many tools enabled" + } + if (key === "chat:tooManyTools.toolsPart") { + const count = params?.count ?? 0 + return count === 1 ? `${count} tool` : `${count} tools` + } + if (key === "chat:tooManyTools.serversPart") { + const count = params?.count ?? 0 + return count === 1 ? `${count} MCP server` : `${count} MCP servers` + } + if (key === "chat:tooManyTools.messageTemplate") { + return `You have ${params?.tools} enabled via ${params?.servers}. Such a high number can confuse the model and lead to errors. Try to keep it below ${params?.threshold}.` + } + if (key === "chat:tooManyTools.openMcpSettings") { + return "Open MCP Settings" + } + if (key === "chat:apiRequest.errorMessage.docs") { + return "Docs" + } + return key + }, + }), +})) + +describe("TooManyToolsWarning", () => { + beforeEach(() => { + vi.clearAllMocks() + mockMcpServers.mockReturnValue([]) + }) + + it("does not render when there are no MCP servers", () => { + mockMcpServers.mockReturnValue([]) + + const { container } = render() + + expect(container.firstChild).toBeNull() + }) + + it("does not render when tool count is below threshold", () => { + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools: [ + { name: "tool1", enabledForPrompt: true }, + { name: "tool2", enabledForPrompt: true }, + ], + }, + ]) + + const { container } = render() + + expect(container.firstChild).toBeNull() + }) + + it("does not render when tool count equals threshold", () => { + // Create tools to exactly match threshold + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD }, (_, i) => ({ + name: `tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools, + }, + ]) + + const { container } = render() + + expect(container.firstChild).toBeNull() + }) + + it("renders warning when tool count exceeds threshold", () => { + // Create more tools than the threshold + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 10 }, (_, i) => ({ + name: `tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools, + }, + ]) + + render() + + expect(screen.getByText("Too many tools enabled")).toBeInTheDocument() + expect( + screen.getByText( + `You have ${MAX_MCP_TOOLS_THRESHOLD + 10} tools enabled via 1 MCP server. Such a high number can confuse the model and lead to errors. Try to keep it below ${MAX_MCP_TOOLS_THRESHOLD}.`, + ), + ).toBeInTheDocument() + }) + + it("ignores disabled servers", () => { + // Create tools across two servers, one disabled + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 10 }, (_, i) => ({ + name: `tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "disabledServer", + status: "connected", + disabled: true, // This server is disabled + tools, + }, + { + name: "enabledServer", + status: "connected", + disabled: false, + tools: [{ name: "tool1", enabledForPrompt: true }], // Only 1 tool + }, + ]) + + const { container } = render() + + // Should not render because only 1 tool is on enabled server + expect(container.firstChild).toBeNull() + }) + + it("ignores disconnected servers", () => { + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 10 }, (_, i) => ({ + name: `tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "disconnectedServer", + status: "disconnected", // Not connected + disabled: false, + tools, + }, + ]) + + const { container } = render() + + expect(container.firstChild).toBeNull() + }) + + it("ignores disabled tools", () => { + // Create tools with some disabled + const enabledTools = Array.from({ length: 20 }, (_, i) => ({ + name: `enabledTool${i}`, + enabledForPrompt: true, + })) + const disabledTools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 10 }, (_, i) => ({ + name: `disabledTool${i}`, + enabledForPrompt: false, // These are disabled + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools: [...enabledTools, ...disabledTools], + }, + ]) + + const { container } = render() + + // Should not render because only 20 tools are enabled + expect(container.firstChild).toBeNull() + }) + + it("treats tools with undefined enabledForPrompt as enabled", () => { + // Create tools without enabledForPrompt set (default behavior is enabled) + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 5 }, (_, i) => ({ + name: `tool${i}`, + // enabledForPrompt is undefined, which means enabled by default + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools, + }, + ]) + + render() + + expect(screen.getByText("Too many tools enabled")).toBeInTheDocument() + }) + + it("counts tools across multiple servers", () => { + // Create tools across multiple servers + const tools1 = Array.from({ length: 35 }, (_, i) => ({ + name: `server1tool${i}`, + enabledForPrompt: true, + })) + const tools2 = Array.from({ length: 30 }, (_, i) => ({ + name: `server2tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools: tools1, + }, + { + name: "server2", + status: "connected", + disabled: false, + tools: tools2, + }, + ]) + + render() + + // 35 + 30 = 65 tools > 60 threshold + expect(screen.getByText("Too many tools enabled")).toBeInTheDocument() + expect( + screen.getByText( + `You have 65 tools enabled via 2 MCP servers. Such a high number can confuse the model and lead to errors. Try to keep it below ${MAX_MCP_TOOLS_THRESHOLD}.`, + ), + ).toBeInTheDocument() + }) + + it("renders MCP settings link and opens settings when clicked", () => { + const mockWindowPostMessage = vi.spyOn(window, "postMessage") + + // Create more tools than the threshold + const tools = Array.from({ length: MAX_MCP_TOOLS_THRESHOLD + 10 }, (_, i) => ({ + name: `tool${i}`, + enabledForPrompt: true, + })) + + mockMcpServers.mockReturnValue([ + { + name: "server1", + status: "connected", + disabled: false, + tools, + }, + ]) + + render() + + // Verify the link is rendered + const settingsLink = screen.getByText("Open MCP Settings") + expect(settingsLink).toBeInTheDocument() + + // Click the link and verify it posts the message + fireEvent.click(settingsLink) + + expect(mockWindowPostMessage).toHaveBeenCalledWith( + { type: "action", action: "settingsButtonClicked", values: { section: "mcp" } }, + "*", + ) + + mockWindowPostMessage.mockRestore() + }) +}) diff --git a/webview-ui/src/components/chat/__tests__/WarningRow.spec.tsx b/webview-ui/src/components/chat/__tests__/WarningRow.spec.tsx new file mode 100644 index 00000000000..38eae810a04 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/WarningRow.spec.tsx @@ -0,0 +1,109 @@ +import { render, screen, fireEvent } from "@/utils/test-utils" +import { vscode } from "@/utils/vscode" + +import { WarningRow } from "../WarningRow" + +// Mock vscode webview messaging +vi.mock("@/utils/vscode", () => ({ + vscode: { + postMessage: vi.fn(), + }, +})) + +// Mock i18n TranslationContext +vi.mock("@/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string) => { + const map: Record = { + "chat:apiRequest.errorMessage.docs": "Docs", + } + return map[key] ?? key + }, + }), +})) + +describe("WarningRow", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it("renders title and message", () => { + render() + + expect(screen.getByText("Test Warning")).toBeInTheDocument() + expect(screen.getByText("This is a test warning message")).toBeInTheDocument() + }) + + it("does not render docs link when docsURL is not provided", () => { + render() + + expect(screen.queryByText("Docs")).not.toBeInTheDocument() + }) + + it("renders docs link when docsURL is provided", () => { + render() + + const docsLink = screen.getByText("Docs") + expect(docsLink).toBeInTheDocument() + }) + + it("opens external URL when docs link is clicked", () => { + const mockPostMessage = vi.mocked(vscode.postMessage) + + render() + + const docsLink = screen.getByText("Docs") + fireEvent.click(docsLink) + + expect(mockPostMessage).toHaveBeenCalledWith({ + type: "openExternal", + url: "https://docs.example.com", + }) + }) + + it("renders warning icon", () => { + const { container } = render() + + // TriangleAlert icon should be present (as an SVG element) + const warningIcon = container.querySelector("svg") + expect(warningIcon).toBeInTheDocument() + }) + + it("does not render action link when actionText and onAction are not provided", () => { + render() + + expect(screen.queryByText("Open Settings")).not.toBeInTheDocument() + }) + + it("renders action link when actionText and onAction are provided", () => { + const mockOnAction = vi.fn() + render( + , + ) + + const actionLink = screen.getByText("Open Settings") + expect(actionLink).toBeInTheDocument() + }) + + it("calls onAction when action link is clicked", () => { + const mockOnAction = vi.fn() + render( + , + ) + + const actionLink = screen.getByText("Open Settings") + fireEvent.click(actionLink) + + expect(mockOnAction).toHaveBeenCalledTimes(1) + }) +}) diff --git a/webview-ui/src/components/mcp/McpView.tsx b/webview-ui/src/components/mcp/McpView.tsx index 6803e60baf4..2167ee18b3e 100644 --- a/webview-ui/src/components/mcp/McpView.tsx +++ b/webview-ui/src/components/mcp/McpView.tsx @@ -13,6 +13,7 @@ import type { McpServer } from "@roo-code/types" import { vscode } from "@src/utils/vscode" import { useExtensionState } from "@src/context/ExtensionStateContext" import { useAppTranslation } from "@src/i18n/TranslationContext" +import { useTooManyTools } from "@src/hooks/useTooManyTools" import { Button, Dialog, @@ -43,6 +44,7 @@ const McpView = () => { } = useExtensionState() const { t } = useAppTranslation() + const { isOverThreshold, title, message } = useTooManyTools() return (
@@ -99,6 +101,31 @@ const McpView = () => {
+ {/* Too Many Tools Warning */} + {isOverThreshold && ( +
+
+ + {title} +
+
+ {message} +
+
+ )} + {/* Server List */} {servers.length > 0 && (
diff --git a/webview-ui/src/hooks/useTooManyTools.ts b/webview-ui/src/hooks/useTooManyTools.ts new file mode 100644 index 00000000000..ba18b10a708 --- /dev/null +++ b/webview-ui/src/hooks/useTooManyTools.ts @@ -0,0 +1,57 @@ +import { useMemo } from "react" +import { useExtensionState } from "@src/context/ExtensionStateContext" +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { MAX_MCP_TOOLS_THRESHOLD, countEnabledMcpTools } from "@roo-code/types" + +export interface TooManyToolsInfo { + /** Number of enabled and connected MCP servers */ + enabledServerCount: number + /** Total number of enabled tools across all enabled servers */ + enabledToolCount: number + /** Whether the tool count exceeds the threshold */ + isOverThreshold: boolean + /** The maximum recommended threshold */ + threshold: number + /** Localized title string */ + title: string + /** Localized message string */ + message: string +} + +/** + * Hook that calculates tool counts and provides localized warning messages. + * Used by TooManyToolsWarning components in both chat and MCP settings views. + * + * @returns Tool count information and localized messages + * + * @example + * const { isOverThreshold, title, message } = useTooManyTools() + * if (isOverThreshold) { + * // Show warning + * } + */ +export function useTooManyTools(): TooManyToolsInfo { + const { t } = useAppTranslation() + const { mcpServers } = useExtensionState() + + const { enabledServerCount, enabledToolCount } = useMemo(() => countEnabledMcpTools(mcpServers), [mcpServers]) + + const isOverThreshold = enabledToolCount > MAX_MCP_TOOLS_THRESHOLD + + const toolsPart = t("chat:tooManyTools.toolsPart", { count: enabledToolCount }) + const serversPart = t("chat:tooManyTools.serversPart", { count: enabledServerCount }) + const message = t("chat:tooManyTools.messageTemplate", { + tools: toolsPart, + servers: serversPart, + threshold: MAX_MCP_TOOLS_THRESHOLD, + }) + + return { + enabledServerCount, + enabledToolCount, + isOverThreshold, + threshold: MAX_MCP_TOOLS_THRESHOLD, + title: t("chat:tooManyTools.title"), + message, + } +} diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 650a4949a2c..c989cc030bd 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -492,5 +492,14 @@ "updated": "S'ha actualitzat la llista de tasques pendents", "completed": "Completat", "started": "Iniciat" + }, + "tooManyTools": { + "title": "Massa eines habilitades", + "toolsPart_one": "{{count}} eina", + "toolsPart_other": "{{count}} eines", + "serversPart_one": "{{count}} servidor MCP", + "serversPart_other": "{{count}} servidors MCP", + "messageTemplate": "Tens {{tools}} habilitades via {{servers}}. Un nombre tant alt pot confondre el model i portar a errors. Intenta mantenir-lo per sota de {{threshold}}.", + "openMcpSettings": "Obrir configuració de MCP" } } diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index fc251576346..254052278bd 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -492,5 +492,14 @@ "updated": "Die To-Do-Liste wurde aktualisiert", "completed": "Abgeschlossen", "started": "Gestartet" + }, + "tooManyTools": { + "title": "Zu viele Tools aktiviert", + "toolsPart_one": "{{count}} Tool", + "toolsPart_other": "{{count}} Tools", + "serversPart_one": "{{count}} MCP-Server", + "serversPart_other": "{{count}} MCP-Server", + "messageTemplate": "Du hast {{tools}} über {{servers}} aktiviert. Eine so hohe Anzahl kann das Modell verwirren und zu Fehlern führen. Versuche, es unter {{threshold}} zu halten.", + "openMcpSettings": "MCP-Einstellungen öffnen" } } diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 3ab2c037af2..d92957916b3 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -484,5 +484,14 @@ "updated": "Updated the to-do list", "completed": "Completed", "started": "Started" + }, + "tooManyTools": { + "title": "Too many tools enabled", + "toolsPart_one": "{{count}} tool", + "toolsPart_other": "{{count}} tools", + "serversPart_one": "{{count}} MCP server", + "serversPart_other": "{{count}} MCP servers", + "messageTemplate": "You have {{tools}} enabled via {{servers}}. Such a high number can confuse the model and lead to errors. Try to keep it below {{threshold}}.", + "openMcpSettings": "Open MCP Settings" } } diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 09bb9c80aae..ae0d02232f6 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -492,5 +492,14 @@ "updated": "Se actualizó la lista de tareas pendientes", "completed": "Completado", "started": "Iniciado" + }, + "tooManyTools": { + "title": "Demasiadas herramientas habilitadas", + "toolsPart_one": "{{count}} herramienta", + "toolsPart_other": "{{count}} herramientas", + "serversPart_one": "{{count}} servidor MCP", + "serversPart_other": "{{count}} servidores MCP", + "messageTemplate": "Tienes {{tools}} habilitadas a través de {{servers}}. Un número tan alto puede confundir al modelo y llevar a errores. Intenta mantenerlo por debajo de {{threshold}}.", + "openMcpSettings": "Abrir configuración de MCP" } } diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 700b1534337..56eec51e96b 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -492,5 +492,14 @@ "updated": "La liste des tâches a été mise à jour", "completed": "Terminé", "started": "Commencé" + }, + "tooManyTools": { + "title": "Trop d'outils activés", + "toolsPart_one": "{{count}} outil", + "toolsPart_other": "{{count}} outils", + "serversPart_one": "{{count}} serveur MCP", + "serversPart_other": "{{count}} serveurs MCP", + "messageTemplate": "Tu as {{tools}} activés via {{servers}}. Un nombre aussi élevé peut confondre le modèle et entraîner des erreurs. Essaie de le maintenir en dessous de {{threshold}}.", + "openMcpSettings": "Ouvrir les paramètres MCP" } } diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 753fc857168..a58e3abff44 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -492,5 +492,14 @@ "updated": "टू-डू सूची अपडेट की गई", "completed": "पूरा हुआ", "started": "शुरू हुआ" + }, + "tooManyTools": { + "title": "बहुत सारे उपकरण सक्षम हैं", + "toolsPart_one": "{{count}} उपकरण", + "toolsPart_other": "{{count}} उपकरण", + "serversPart_one": "{{count}} MCP सर्वर", + "serversPart_other": "{{count}} MCP सर्वर", + "messageTemplate": "आपके पास {{servers}} के माध्यम से {{tools}} सक्षम हैं। इतनी अधिक संख्या मॉडल को भ्रमित कर सकती है और त्रुटियों का कारण बन सकती है। इसे {{threshold}} से नीचे रखने का प्रयास करें।", + "openMcpSettings": "MCP सेटिंग्स खोलें" } } diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 04db7af45e8..c00a6d5ab3b 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -498,5 +498,14 @@ "updated": "Memperbarui daftar to-do", "completed": "Selesai", "started": "Dimulai" + }, + "tooManyTools": { + "title": "Terlalu banyak alat diaktifkan", + "toolsPart_one": "{{count}} alat", + "toolsPart_other": "{{count}} alat", + "serversPart_one": "{{count}} server MCP", + "serversPart_other": "{{count}} server MCP", + "messageTemplate": "Anda memiliki {{tools}} diaktifkan melalui {{servers}}. Jumlah yang begitu besar dapat membingungkan model dan menyebabkan kesalahan. Cobalah untuk menjaganya di bawah {{threshold}}.", + "openMcpSettings": "Buka Pengaturan MCP" } } diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 73ed761b293..3fe64691356 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -492,5 +492,14 @@ "updated": "Aggiornata la lista delle cose da fare", "completed": "Completato", "started": "Iniziato" + }, + "tooManyTools": { + "title": "Troppi strumenti abilitati", + "toolsPart_one": "{{count}} strumento", + "toolsPart_other": "{{count}} strumenti", + "serversPart_one": "{{count}} server MCP", + "serversPart_other": "{{count}} server MCP", + "messageTemplate": "Hai {{tools}} abilitate via {{servers}}. Un numero così alto può confondere il modello e portare a errori. Prova a mantenerlo sotto {{threshold}}.", + "openMcpSettings": "Apri impostazioni MCP" } } diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 44543b22acd..68f3597396c 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -492,5 +492,14 @@ "updated": "To-Doリストを更新しました", "completed": "完了", "started": "開始" + }, + "tooManyTools": { + "title": "有効になっているツールが多すぎます", + "toolsPart_one": "{{count}} ツール", + "toolsPart_other": "{{count}} ツール", + "serversPart_one": "{{count}} MCP サーバー", + "serversPart_other": "{{count}} MCP サーバー", + "messageTemplate": "{{servers}}経由で{{tools}}が有効になっています。このような高い数は、モデルを混乱させてエラーを引き起こす可能性があります。{{threshold}}以下に保つようにしてください。", + "openMcpSettings": "MCP 設定を開く" } } diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index d758f082df0..a9934a4fd3d 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -492,5 +492,14 @@ "updated": "할 일 목록을 업데이트했습니다", "completed": "완료됨", "started": "시작됨" + }, + "tooManyTools": { + "title": "활성화된 도구가 너무 많습니다", + "toolsPart_one": "{{count}}개 도구", + "toolsPart_other": "{{count}}개 도구", + "serversPart_one": "{{count}}개 MCP 서버", + "serversPart_other": "{{count}}개 MCP 서버", + "messageTemplate": "{{servers}}를 통해 {{tools}}가 활성화되어 있습니다. 이렇게 많은 수의 도구는 모델을 혼동시키고 오류를 유발할 수 있습니다. {{threshold}} 이하로 유지하도록 노력하세요.", + "openMcpSettings": "MCP 설정 열기" } } diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 6f98a005382..d1747ed529d 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -492,5 +492,14 @@ "updated": "De to-do-lijst is bijgewerkt", "completed": "Voltooid", "started": "Gestart" + }, + "tooManyTools": { + "title": "Te veel tools ingeschakeld", + "toolsPart_one": "{{count}} tool", + "toolsPart_other": "{{count}} tools", + "serversPart_one": "{{count}} MCP server", + "serversPart_other": "{{count}} MCP servers", + "messageTemplate": "Je hebt {{tools}} ingeschakeld via {{servers}}. Zoveel tools kunnen het model verwarren en tot fouten leiden. Probeer dit onder {{threshold}} te houden.", + "openMcpSettings": "MCP-instellingen openen" } } diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index eaac2b46693..acdd23f06be 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -492,5 +492,14 @@ "updated": "Zaktualizowano listę zadań do wykonania", "completed": "Ukończono", "started": "Rozpoczęto" + }, + "tooManyTools": { + "title": "Włączono zbyt wiele narzędzi", + "toolsPart_one": "{{count}} narzędzie", + "toolsPart_other": "{{count}} narzędzi", + "serversPart_one": "{{count}} serwer MCP", + "serversPart_other": "{{count}} serwerów MCP", + "messageTemplate": "Masz {{tools}} włączonych przez {{servers}}. Taka duża liczba może zamieszać model i prowadzić do błędów. Staraj się, aby była poniżej {{threshold}}.", + "openMcpSettings": "Otwórz ustawienia MCP" } } diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 555da7dca85..30a86559fa4 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -492,5 +492,14 @@ "updated": "A lista de tarefas foi atualizada", "completed": "Concluído", "started": "Iniciado" + }, + "tooManyTools": { + "title": "Muitas ferramentas habilitadas", + "toolsPart_one": "{{count}} ferramenta", + "toolsPart_other": "{{count}} ferramentas", + "serversPart_one": "{{count}} servidor MCP", + "serversPart_other": "{{count}} servidores MCP", + "messageTemplate": "Você tem {{tools}} habilitadas via {{servers}}. Um número tão alto pode confundir o modelo e levar a erros. Tente mantê-lo abaixo de {{threshold}}.", + "openMcpSettings": "Abrir Configurações MCP" } } diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 7d688361e76..008de4397d9 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -493,5 +493,14 @@ "updated": "Список задач обновлен", "completed": "Завершено", "started": "Начато" + }, + "tooManyTools": { + "title": "Включено слишком много инструментов", + "toolsPart_one": "{{count}} инструмент", + "toolsPart_other": "{{count}} инструментов", + "serversPart_one": "{{count}} сервер MCP", + "serversPart_other": "{{count}} серверов MCP", + "messageTemplate": "У тебя включено {{tools}} через {{servers}}. Такое большое количество может сбить модель с толку и привести к ошибкам. Постарайся держать это ниже {{threshold}}.", + "openMcpSettings": "Открыть настройки MCP" } } diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 733c612564c..f88ed480c0b 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -493,5 +493,14 @@ "updated": "Yapılacaklar listesi güncellendi", "completed": "Tamamlandı", "started": "Başladı" + }, + "tooManyTools": { + "title": "Çok fazla araç etkinleştirildi", + "toolsPart_one": "{{count}} araç", + "toolsPart_other": "{{count}} araç", + "serversPart_one": "{{count}} MCP sunucusu", + "serversPart_other": "{{count}} MCP sunucusu", + "messageTemplate": "{{servers}} üzerinden {{tools}} etkinleştirilmiş durumda. Bu kadar fazlası modeli kafası karışabilir ve hatalara neden olabilir. {{threshold}} altında tutmaya çalış.", + "openMcpSettings": "MCP Ayarlarını Aç" } } diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 1f253189646..c5724152f88 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -493,5 +493,14 @@ "updated": "Đã cập nhật danh sách công việc", "completed": "Đã hoàn thành", "started": "Đã bắt đầu" + }, + "tooManyTools": { + "title": "Đã bật quá nhiều công cụ", + "toolsPart_one": "{{count}} công cụ", + "toolsPart_other": "{{count}} công cụ", + "serversPart_one": "{{count}} máy chủ MCP", + "serversPart_other": "{{count}} máy chủ MCP", + "messageTemplate": "Bạn đã bật {{tools}} qua {{servers}}. Số lượng lớn như vậy có thể khiến mô hình bối rối và dẫn đến lỗi. Cố gắng giữ nó dưới {{threshold}}.", + "openMcpSettings": "Mở cài đặt MCP" } } diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index a075f2686aa..e13124379e7 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -493,5 +493,14 @@ "updated": "已更新待办事项列表", "completed": "已完成", "started": "已开始" + }, + "tooManyTools": { + "title": "启用的工具过多", + "toolsPart_one": "{{count}} 个工具", + "toolsPart_other": "{{count}} 个工具", + "serversPart_one": "{{count}} 个 MCP 服务", + "serversPart_other": "{{count}} 个 MCP 服务", + "messageTemplate": "你通过 {{servers}} 启用了 {{tools}}。这么多数量会混淆模型并导致错误。建议将其保持在 {{threshold}} 以下。", + "openMcpSettings": "打开 MCP 设置" } } diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 826178ec06f..5d20352c573 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -493,5 +493,14 @@ "updated": "已更新待辦事項列表", "completed": "已完成", "started": "已開始" + }, + "tooManyTools": { + "title": "啟用的工具過多", + "toolsPart_one": "{{count}} 個工具", + "toolsPart_other": "{{count}} 個工具", + "serversPart_one": "{{count}} 個 MCP 伺服器", + "serversPart_other": "{{count}} 個 MCP 伺服器", + "messageTemplate": "你已啟用 {{tools}}(透過 {{servers}})。這麼多的工具可能會混淆模型並導致錯誤。請嘗試保持在 {{threshold}} 以下。", + "openMcpSettings": "開啟 MCP 設定" } }