feat: warn users when too many MCP tools are enabled (#10772)

* feat: warn users when too many MCP tools are enabled

- Add WarningRow component for displaying generic warnings with icon, title, message, and optional docs link
- Add TooManyToolsWarning component that shows when users have more than 40 MCP tools enabled
- Add MAX_MCP_TOOLS_THRESHOLD constant (40)
- Add i18n translations for the warning message
- Integrate warning into ChatView to display after task header
- Add comprehensive tests for both components

Closes ROO-542

* Moves constant to the right place

* Move it to the backend

* i18n

* Add actionlink that takes you to MCP settings in this case

* Add to MCP settings too

* Bump max tools up to 60 since github itself has 50+

* DRY

* Fix test

---------

Co-authored-by: Roo Code <roomote@roocode.com>
Co-authored-by: Bruno Bergher <bruno@roocode.com>
Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
This commit is contained in:
roomote[bot] 2026-01-18 09:22:09 -05:00 • committed by GitHub
parent 719e6cb35b
commit a148862a06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 906 additions and 2 deletions

View file

@ -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 }
}

View file

@ -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)

View file

@ -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<TaskEvents> 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<void> {
if (this.enableBridge) {
try {
@ -1858,6 +1891,24 @@ export class Task extends EventEmitter<TaskEvents> 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)

View file

@ -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"
@ -1517,6 +1518,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 (
<WarningRow
title={t("chat:tooManyTools.title")}
message={t("chat:tooManyTools.messageTemplate", {
tools: toolsPart,
servers: serversPart,
threshold: warningData.threshold,
})}
actionText={t("chat:tooManyTools.openMcpSettings")}
onAction={() =>
window.postMessage(
{ type: "action", action: "settingsButtonClicked", values: { section: "mcp" } },
"*",
)
}
/>
)
}
default:
return (
<>

View file

@ -266,11 +266,11 @@ export const ErrorRow = memo(
</div>
</div>
)}
<div className="ml-2 pl-4 mt-1 pt-1 border-l border-vscode-errorForeground/50">
<div className="ml-2 pl-4 mt-1 pt-0.5 border-l border-vscode-errorForeground/50">
<p
className={
messageClassName ||
"my-0 font-light whitespace-pre-wrap break-words text-vscode-descriptionForeground"
"cursor-default my-0 font-light whitespace-pre-wrap break-words text-vscode-descriptionForeground"
}>
{message}
{formattedErrorDetails && (

View file

@ -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
* <TooManyToolsWarning />
*/
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 (
<WarningRow
title={title}
message={message}
actionText={t("chat:tooManyTools.openMcpSettings")}
onAction={handleOpenMcpSettings}
/>
)
}
export default TooManyToolsWarning

View file

@ -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
* <WarningRow
* title="Too many tools enabled"
* message="You have 50 tools enabled via 5 MCP servers."
* docsURL="https://docs.example.com/mcp-best-practices"
* actionText="Open MCP Settings"
* onAction={() => openSettings()}
* />
*/
export const WarningRow: React.FC<WarningRowProps> = ({ title, message, docsURL, actionText, onAction }) => {
const { t } = useAppTranslation()
return (
<div className="group pr-2 py-2">
<div className="flex items-center justify-between gap-2 break-words">
<TriangleAlert className="w-4 text-vscode-editorWarning-foreground shrink-0" />
<span className="font-bold text-vscode-editorWarning-foreground grow cursor-default">{title}</span>
{docsURL && (
<a
href={docsURL}
className="text-sm flex items-center gap-1 transition-opacity opacity-0 group-hover:opacity-100"
onClick={(e) => {
e.preventDefault()
vscode.postMessage({ type: "openExternal", url: docsURL })
}}>
<BookOpenText className="size-3 mt-[3px]" />
{t("chat:apiRequest.errorMessage.docs")}
</a>
)}
</div>
<div className="cursor-default ml-2 pl-4 mt-1 pt-0.5 border-l border-vscode-editorWarning-foreground/50">
<p className="my-0 font-light whitespace-pre-wrap break-words text-vscode-descriptionForeground">
{message}
{actionText && onAction && (
<>
{" "}
<a
href="#"
className="text-vscode-textLink-foreground hover:text-vscode-textLink-activeForeground cursor-pointer"
onClick={(e) => {
e.preventDefault()
onAction()
}}>
{actionText}
</a>
</>
)}
</p>
</div>
</div>
)
}
export default WarningRow

View file

@ -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<string, any>) => {
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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
// 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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
// 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(<TooManyToolsWarning />)
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(<TooManyToolsWarning />)
// 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(<TooManyToolsWarning />)
// 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()
})
})

View file

@ -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<string, string> = {
"chat:apiRequest.errorMessage.docs": "Docs",
}
return map[key] ?? key
},
}),
}))
describe("WarningRow", () => {
beforeEach(() => {
vi.clearAllMocks()
})
it("renders title and message", () => {
render(<WarningRow title="Test Warning" message="This is a test warning message" />)
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(<WarningRow title="Test Warning" message="This is a test message" />)
expect(screen.queryByText("Docs")).not.toBeInTheDocument()
})
it("renders docs link when docsURL is provided", () => {
render(<WarningRow title="Test Warning" message="This is a test message" docsURL="https://docs.example.com" />)
const docsLink = screen.getByText("Docs")
expect(docsLink).toBeInTheDocument()
})
it("opens external URL when docs link is clicked", () => {
const mockPostMessage = vi.mocked(vscode.postMessage)
render(<WarningRow title="Test Warning" message="This is a test message" docsURL="https://docs.example.com" />)
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(<WarningRow title="Test Warning" message="This is a test message" />)
// 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(<WarningRow title="Test Warning" message="This is a test message" />)
expect(screen.queryByText("Open Settings")).not.toBeInTheDocument()
})
it("renders action link when actionText and onAction are provided", () => {
const mockOnAction = vi.fn()
render(
<WarningRow
title="Test Warning"
message="This is a test message"
actionText="Open Settings"
onAction={mockOnAction}
/>,
)
const actionLink = screen.getByText("Open Settings")
expect(actionLink).toBeInTheDocument()
})
it("calls onAction when action link is clicked", () => {
const mockOnAction = vi.fn()
render(
<WarningRow
title="Test Warning"
message="This is a test message"
actionText="Open Settings"
onAction={mockOnAction}
/>,
)
const actionLink = screen.getByText("Open Settings")
fireEvent.click(actionLink)
expect(mockOnAction).toHaveBeenCalledTimes(1)
})
})

View file

@ -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 (
<div>
@ -99,6 +101,31 @@ const McpView = () => {
</div>
</div>
{/* Too Many Tools Warning */}
{isOverThreshold && (
<div style={{ marginBottom: 15 }}>
<div
style={{
display: "flex",
alignItems: "center",
gap: "6px",
fontWeight: "500",
color: "var(--vscode-editorWarning-foreground)",
marginBottom: "5px",
}}>
<span className="codicon codicon-warning" />
{title}
</div>
<div
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
}}>
{message}
</div>
</div>
)}
{/* Server List */}
{servers.length > 0 && (
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>

View file

@ -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,
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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 सेटिंग्स खोलें"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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 設定を開く"
}
}

View file

@ -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 설정 열기"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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"
}
}

View file

@ -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ç"
}
}

View file

@ -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"
}
}

View file

@ -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 设置"
}
}

View file

@ -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 設定"
}
}