diff --git a/packages/types/src/mode.ts b/packages/types/src/mode.ts index 88dcbb9574..4a0900d624 100644 --- a/packages/types/src/mode.ts +++ b/packages/types/src/mode.ts @@ -26,6 +26,12 @@ export const groupOptionsSchema = z.object({ { message: "Invalid regular expression pattern" }, ), description: z.string().optional(), + mcp: z + .object({ + included: z.array(z.string()), + description: z.string().optional(), + }) + .optional(), }) export type GroupOptions = z.infer @@ -34,7 +40,17 @@ export type GroupOptions = z.infer * GroupEntry */ -export const groupEntrySchema = z.union([toolGroupsSchema, z.tuple([toolGroupsSchema, groupOptionsSchema])]) +export const groupEntrySchema = z.union([ + toolGroupsSchema, + z.tuple([toolGroupsSchema, groupOptionsSchema]), + // Allow direct mcp configuration object + z.object({ + mcp: z.object({ + included: z.array(z.string()), + description: z.string().optional(), + }), + }), +]) export type GroupEntry = z.infer diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap index 7ca32b80a1..9f4d34f54a 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap @@ -519,7 +519,7 @@ The Model Context Protocol (MCP) enables communication between the system and MC When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool. - +## test-server (`test-command`) ## Creating an MCP Server The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this: diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap index 7ca32b80a1..9f4d34f54a 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap @@ -519,7 +519,7 @@ The Model Context Protocol (MCP) enables communication between the system and MC When a server is connected, you can use the server's tools via the `use_mcp_tool` tool, and access the server's resources via the `access_mcp_resource` tool. - +## test-server (`test-command`) ## Creating an MCP Server The user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. If they do, you should obtain detailed instructions on this topic using the fetch_instructions tool, like this: diff --git a/src/core/prompts/__tests__/add-custom-instructions.spec.ts b/src/core/prompts/__tests__/add-custom-instructions.spec.ts index 5097685e3b..c2365925cf 100644 --- a/src/core/prompts/__tests__/add-custom-instructions.spec.ts +++ b/src/core/prompts/__tests__/add-custom-instructions.spec.ts @@ -170,7 +170,36 @@ const mockContext = { // Instead of extending McpHub, create a mock that implements just what we need const createMockMcpHub = (withServers: boolean = false): McpHub => ({ - getServers: () => (withServers ? [{ name: "test-server", disabled: false }] : []), + getServers: () => + withServers + ? [ + { + name: "test-server", + disabled: false, + status: "connected", + config: JSON.stringify({ command: "test-command" }), + tools: [], + resourceTemplates: [], + resources: [], + instructions: undefined, + }, + ] + : [], + getAllServers: () => + withServers + ? [ + { + name: "test-server", + disabled: false, + status: "connected", + config: JSON.stringify({ command: "test-command" }), + tools: [], + resourceTemplates: [], + resources: [], + instructions: undefined, + }, + ] + : [], getMcpServersPath: async () => "/mock/mcp/path", getMcpSettingsFilePath: async () => "/mock/settings/path", dispose: async () => {}, diff --git a/src/core/prompts/__tests__/system-prompt.spec.ts b/src/core/prompts/__tests__/system-prompt.spec.ts index 4d5579408c..a417158e99 100644 --- a/src/core/prompts/__tests__/system-prompt.spec.ts +++ b/src/core/prompts/__tests__/system-prompt.spec.ts @@ -170,7 +170,36 @@ const mockContext = { // Instead of extending McpHub, create a mock that implements just what we need const createMockMcpHub = (withServers: boolean = false): McpHub => ({ - getServers: () => (withServers ? [{ name: "test-server", disabled: false }] : []), + getServers: () => + withServers + ? [ + { + name: "test-server", + disabled: false, + status: "connected", + config: JSON.stringify({ command: "test-command" }), + tools: [], + resourceTemplates: [], + resources: [], + instructions: undefined, + }, + ] + : [], + getAllServers: () => + withServers + ? [ + { + name: "test-server", + disabled: false, + status: "connected", + config: JSON.stringify({ command: "test-command" }), + tools: [], + resourceTemplates: [], + resources: [], + instructions: undefined, + }, + ] + : [], getMcpServersPath: async () => "/mock/mcp/path", getMcpSettingsFilePath: async () => "/mock/settings/path", dispose: async () => {}, diff --git a/src/core/prompts/sections/mcp-servers.ts b/src/core/prompts/sections/mcp-servers.ts index 643233ab6f..f3d660f6b4 100644 --- a/src/core/prompts/sections/mcp-servers.ts +++ b/src/core/prompts/sections/mcp-servers.ts @@ -1,53 +1,133 @@ import { DiffStrategy } from "../../../shared/tools" import { McpHub } from "../../../services/mcp/McpHub" +import { GroupEntry, ModeConfig } from "@roo-code/types" +import { getGroupName } from "../../../shared/modes" +import { McpServer } from "../../../shared/mcp" + +let lastMcpHub: McpHub | undefined +let lastMcpIncludedList: string[] | undefined +let lastFilteredServers: McpServer[] = [] + +function memoizeFilteredServers(mcpHub: McpHub, mcpIncludedList?: string[]): McpServer[] { + const mcpHubChanged = mcpHub !== lastMcpHub + const listChanged = !areArraysEqual(mcpIncludedList, lastMcpIncludedList) + + if (!mcpHubChanged && !listChanged) { + return lastFilteredServers + } + + lastMcpHub = mcpHub + lastMcpIncludedList = mcpIncludedList + + lastFilteredServers = ( + mcpIncludedList && mcpIncludedList.length > 0 ? mcpHub.getAllServers() : mcpHub.getServers() + ).filter((server) => { + if (mcpIncludedList && mcpIncludedList.length > 0) { + return mcpIncludedList.includes(server.name) && server.status === "connected" + } + return server.status === "connected" + }) + + return lastFilteredServers +} +function areArraysEqual(arr1?: string[], arr2?: string[]): boolean { + if (!arr1 && !arr2) return true + if (!arr1 || !arr2) return false + if (arr1.length !== arr2.length) return false + + return arr1.every((item, index) => item === arr2[index]) +} export async function getMcpServersSection( mcpHub?: McpHub, diffStrategy?: DiffStrategy, enableMcpServerCreation?: boolean, + currentMode?: ModeConfig, ): Promise { if (!mcpHub) { return "" } - const connectedServers = - mcpHub.getServers().length > 0 - ? `${mcpHub - .getServers() - .filter((server) => server.status === "connected") - .map((server) => { - const tools = server.tools - ?.filter((tool) => tool.enabledForPrompt !== false) - ?.map((tool) => { - const schemaStr = tool.inputSchema - ? ` Input Schema: - ${JSON.stringify(tool.inputSchema, null, 2).split("\n").join("\n ")}` - : "" - - return `- ${tool.name}: ${tool.description}\n${schemaStr}` - }) - .join("\n\n") - - const templates = server.resourceTemplates - ?.map((template) => `- ${template.uriTemplate} (${template.name}): ${template.description}`) - .join("\n") - - const resources = server.resources - ?.map((resource) => `- ${resource.uri} (${resource.name}): ${resource.description}`) - .join("\n") - - const config = JSON.parse(server.config) - - return ( - `## ${server.name}${config.command ? ` (\`${config.command}${config.args && Array.isArray(config.args) ? ` ${config.args.join(" ")}` : ""}\`)` : ""}` + - (server.instructions ? `\n\n### Instructions\n${server.instructions}` : "") + - (tools ? `\n\n### Available Tools\n${tools}` : "") + - (templates ? `\n\n### Resource Templates\n${templates}` : "") + - (resources ? `\n\n### Direct Resources\n${resources}` : "") - ) + // Get MCP configuration for current mode + let mcpIncludedList: string[] | undefined + + if (currentMode) { + // Find MCP group configuration - object format: { mcp: { included: [...] } } + const mcpGroup = currentMode.groups.find((group: GroupEntry) => { + if (typeof group === "object" && !Array.isArray(group) && "mcp" in group) { + return true + } + return getGroupName(group) === "mcp" + }) + + // Extract mcpIncludedList from the MCP configuration + if (mcpGroup && typeof mcpGroup === "object" && !Array.isArray(mcpGroup) && "mcp" in mcpGroup) { + const mcpOptions = mcpGroup as { mcp?: { included?: unknown[] } } + mcpIncludedList = Array.isArray(mcpOptions.mcp?.included) + ? mcpOptions.mcp.included.filter((item: unknown): item is string => typeof item === "string") + : undefined + } + } + + const filteredServers = memoizeFilteredServers(mcpHub, mcpIncludedList) + + let connectedServers: string + + if (filteredServers.length > 0) { + connectedServers = `${filteredServers + .map((server) => { + const tools = server.tools + ?.filter((tool) => tool.enabledForPrompt !== false) + ?.map((tool) => { + const schemaStr = tool.inputSchema + ? ` Input Schema: + ${JSON.stringify(tool.inputSchema, null, 2).split("\n").join("\n ")}` + : "" + + return `- ${tool.name}: ${tool.description}\n${schemaStr}` }) - .join("\n\n")}` - : "(No MCP servers currently connected)" + .join("\n\n") + + const templates = server.resourceTemplates + ?.map((template) => `- ${template.uriTemplate} (${template.name}): ${template.description}`) + .join("\n") + + const resources = server.resources + ?.map((resource) => `- ${resource.uri} (${resource.name}): ${resource.description}`) + .join("\n") + + const config = JSON.parse(server.config) + + return ( + `## ${server.name}${config.command ? ` (\`${config.command}${config.args && Array.isArray(config.args) ? ` ${config.args.join(" ")}` : ""}\`)` : ""}` + + (server.instructions ? `\n\n### Instructions\n${server.instructions}` : "") + + (tools ? `\n\n### Available Tools\n${tools}` : "") + + (templates ? `\n\n### Resource Templates\n${templates}` : "") + + (resources ? `\n\n### Direct Resources\n${resources}` : "") + ) + }) + .join("\n\n")}` + } else if (mcpIncludedList && mcpIncludedList.length > 0) { + const allServers = mcpHub.getAllServers() + const disconnectedServers = mcpIncludedList + .map((name) => { + const server = allServers.find((s) => s.name === name) + if (server && server.status !== "connected") { + return `- ${server.name} (${server.status})` + } + if (!server) { + return `- ${name} (not found)` + } + return null + }) + .filter(Boolean) + .join("\n") + connectedServers = `(Configured MCP servers are not currently connected)${ + disconnectedServers ? `\n\nConfigured but disconnected servers:\n${disconnectedServers}` : "" + }` + } else { + connectedServers = "(No MCP servers currently connected)" + } const baseSection = `MCP SERVERS diff --git a/src/core/prompts/system.ts b/src/core/prompts/system.ts index 4ed1185da7..da8ad0a399 100644 --- a/src/core/prompts/system.ts +++ b/src/core/prompts/system.ts @@ -81,7 +81,7 @@ async function generatePrompt( const [modesSection, mcpServersSection] = await Promise.all([ getModesSection(context), shouldIncludeMcp - ? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation) + ? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation, modeConfig) : Promise.resolve(""), ]) diff --git a/src/shared/modes.ts b/src/shared/modes.ts index f68d25c682..f7fb6a5eca 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -23,13 +23,26 @@ export function getGroupName(group: GroupEntry): ToolGroup { if (typeof group === "string") { return group } - - return group[0] + if (Array.isArray(group)) { + return group[0] + } + // Handle direct MCP object format + if (typeof group === "object" && "mcp" in group) { + return "mcp" as ToolGroup + } + return group as ToolGroup } // Helper to get group options if they exist function getGroupOptions(group: GroupEntry): GroupOptions | undefined { - return Array.isArray(group) ? group[1] : undefined + if (Array.isArray(group)) { + return group[1] + } + // Handle direct MCP object format - return the object itself as options + if (typeof group === "object" && "mcp" in group) { + return group as GroupOptions + } + return undefined } // Helper to check if a file path matches a regex pattern diff --git a/webview-ui/src/components/modes/McpSelector.tsx b/webview-ui/src/components/modes/McpSelector.tsx new file mode 100644 index 0000000000..eef9459442 --- /dev/null +++ b/webview-ui/src/components/modes/McpSelector.tsx @@ -0,0 +1,250 @@ +import React, { useState, useRef, useEffect } from "react" +import { ChevronsUpDown, X } from "lucide-react" +import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react" +import { + Popover, + PopoverContent, + PopoverTrigger, + Button, + Command, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, +} from "@src/components/ui" +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { ModeConfig, GroupEntry } from "@roo-code/types" +import { McpServer } from "@roo/mcp" + +interface McpSelectorProps { + group: string + isEnabled: boolean + isCustomMode: boolean + mcpServers: McpServer[] + currentMode?: ModeConfig + visualMode: string + customModes: ModeConfig[] + findModeBySlug: (slug: string, modes: ModeConfig[]) => ModeConfig | undefined + updateCustomMode: (slug: string, config: ModeConfig) => void +} + +const McpSelector: React.FC = ({ + group, + isEnabled, + isCustomMode, + mcpServers, + currentMode, + visualMode, + customModes, + findModeBySlug, + updateCustomMode, +}) => { + const { t } = useAppTranslation() + + // State + const [isDialogOpen, setIsDialogOpen] = useState(false) + const [mcpIncludedList, setMcpIncludedList] = useState([]) + const [searchValue, setSearchValue] = useState("") + const searchInputRef = useRef(null) + + // Sync MCP settings + useEffect(() => { + if (!currentMode) { + setMcpIncludedList([]) + return + } + + // Find MCP group - object format: { mcp: { included: [...] } } + const mcpGroup = currentMode.groups?.find((g: GroupEntry) => { + return typeof g === "object" && !Array.isArray(g) && "mcp" in g + }) + + let included: string[] = [] + + if (mcpGroup && typeof mcpGroup === "object" && !Array.isArray(mcpGroup) && "mcp" in mcpGroup) { + const mcpOptions = mcpGroup as { mcp?: { included?: unknown[] } } + included = Array.isArray(mcpOptions.mcp?.included) + ? (mcpOptions.mcp.included.filter((item) => typeof item === "string") as string[]) + : [] + } + + // Sync MCP settings when mode changes + setMcpIncludedList(included) + }, [currentMode]) + // Handle save + function updateMcpGroupOptions(groups: GroupEntry[] = [], _group: string, mcpIncludedList: string[]): GroupEntry[] { + // Filter out any existing "mcp" entries (string or object forms) + const filteredGroups = groups.filter((g) => { + if (typeof g === "string") { + return g !== "mcp" + } + if (typeof g === "object" && g !== null && !Array.isArray(g) && "mcp" in g) { + return false + } + return true + }) + + // Always add MCP back if it's enabled + // If mcpIncludedList is empty, it means all servers are enabled (default behavior) + // If mcpIncludedList has items, only those servers are enabled + if (mcpIncludedList.length > 0) { + // Specific servers selected + return [...filteredGroups, { mcp: { included: mcpIncludedList } }] as GroupEntry[] + } else { + // No specific servers selected - enable all (just add "mcp" string) + return [...filteredGroups, "mcp"] as GroupEntry[] + } + } + + // Handle save + const handleSave = () => { + const customMode = findModeBySlug(visualMode, customModes) + if (!customMode) { + setIsDialogOpen(false) + return + } + + const updatedGroups = updateMcpGroupOptions(customMode.groups, group, mcpIncludedList) + + updateCustomMode(customMode.slug, { + ...customMode, + groups: updatedGroups, + source: customMode.source || "global", + }) + + setIsDialogOpen(false) + } + if (!isCustomMode || !isEnabled) { + return null + } + + return ( + { + setIsDialogOpen(open) + // Reset search box + if (!open) { + setTimeout(() => { + setSearchValue("") + }, 100) + } + }}> + + + + + +
+
{t("prompts:tools.selectMcpServers")}
+
+ + +
+
+
+ + {searchValue.length > 0 && ( +
+ { + setSearchValue("") + searchInputRef.current?.focus() + }} + /> +
+ )} +
+
+
+ {t("prompts:tools.requiredMcpList")} +
+
+ {t("prompts:tools.mcpDefaultDescription")} +
+ + + {mcpServers.length === 0 ? ( +
+ {t("prompts:tools.noMcpServers")} +
+ ) : ( +
{t("prompts:tools.noMatchFound")}
+ )} +
+ + {(() => { + const uniqueMcpServers = Array.from( + new Map(mcpServers.map((server) => [server.name, server])).values(), + ) + return uniqueMcpServers + .filter( + (server) => + !searchValue || + server.name.toLowerCase().includes(searchValue.toLowerCase()), + ) + .map((server) => ( + { + const isIncluded = mcpIncludedList.includes(server.name) + if (isIncluded) { + setMcpIncludedList( + mcpIncludedList.filter((n) => n !== server.name), + ) + } else { + setMcpIncludedList([...mcpIncludedList, server.name]) + } + }} + className="flex items-center px-2 py-1"> +
+ { + e.stopPropagation() + const isIncluded = mcpIncludedList.includes(server.name) + if (isIncluded) { + setMcpIncludedList( + mcpIncludedList.filter((n) => n !== server.name), + ) + } else { + setMcpIncludedList([...mcpIncludedList, server.name]) + } + }} + /> + {server.name} +
+
+ )) + })()} +
+
+
+
+
+
+ ) +} + +export default McpSelector diff --git a/webview-ui/src/components/modes/ModesView.tsx b/webview-ui/src/components/modes/ModesView.tsx index d470f7a658..1eb2b8bd97 100644 --- a/webview-ui/src/components/modes/ModesView.tsx +++ b/webview-ui/src/components/modes/ModesView.tsx @@ -49,6 +49,7 @@ import { } from "@src/components/ui" import { DeleteModeDialog } from "@src/components/modes/DeleteModeDialog" import { useEscapeKey } from "@src/hooks/useEscapeKey" +import McpSelector from "./McpSelector" // Get all available groups that should show in prompts view const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) => !TOOL_GROUPS[group].alwaysAvailable) @@ -61,7 +62,13 @@ type ModesViewProps = { // Helper to get group name regardless of format function getGroupName(group: GroupEntry): ToolGroup { - return Array.isArray(group) ? group[0] : group + if (Array.isArray(group)) { + return group[0] + } + if (typeof group === "object" && "mcp" in group) { + return "mcp" as ToolGroup + } + return group as ToolGroup } const ModesView = ({ onDone }: ModesViewProps) => { @@ -75,6 +82,7 @@ const ModesView = ({ onDone }: ModesViewProps) => { customInstructions, setCustomInstructions, customModes, + mcpServers, } = useExtensionState() // Use a local state to track the visually active mode @@ -1018,33 +1026,76 @@ const ModesView = ({ onDone }: ModesViewProps) => { ? customMode?.groups?.some((g) => getGroupName(g) === group) : currentMode?.groups?.some((g) => getGroupName(g) === group) + const isMcpGroup = group === "mcp" + + if (isMcpGroup) { + return ( +
+ + {t(`prompts:tools.toolNames.${group}`)} + + {isGroupEnabled && isCustomMode && ( + + )} +
+ ) + } + return ( - - {t(`prompts:tools.toolNames.${group}`)} - {group === "edit" && ( -
- {t("prompts:tools.allowedFiles")}{" "} - {(() => { - const currentMode = getCurrentMode() - const editGroup = currentMode?.groups?.find( - (g) => - Array.isArray(g) && - g[0] === "edit" && - g[1]?.fileRegex, - ) - if (!Array.isArray(editGroup)) return t("prompts:allFiles") - return ( - editGroup[1].description || - `/${editGroup[1].fileRegex}/` - ) - })()} -
- )} -
+
+ + {t(`prompts:tools.toolNames.${group}`)} + {group === "edit" && ( +
+ {t("prompts:tools.allowedFiles")}{" "} + {(() => { + const currentMode = getCurrentMode() + const editGroup = currentMode?.groups?.find( + (g) => + Array.isArray(g) && + g[0] === "edit" && + g[1]?.fileRegex, + ) + if (!Array.isArray(editGroup)) + return t("prompts:allFiles") + return ( + editGroup[1].description || + `/${editGroup[1].fileRegex}/` + ) + })()} +
+ )} +
+
) })} @@ -1494,25 +1545,57 @@ const ModesView = ({ onDone }: ModesViewProps) => { {t("prompts:createModeDialog.tools.description")}
- {availableGroups.map((group) => ( - getGroupName(g) === group)} - onChange={(e: Event | React.FormEvent) => { - const target = - (e as CustomEvent)?.detail?.target || (e.target as HTMLInputElement) - const checked = target.checked - if (checked) { - setNewModeGroups([...newModeGroups, group]) - } else { - setNewModeGroups( - newModeGroups.filter((g) => getGroupName(g) !== group), - ) - } - }}> - {t(`prompts:tools.toolNames.${group}`)} - - ))} + {availableGroups.map((group) => { + if (group === "mcp") { + return ( +
+ getGroupName(g) === group)} + onChange={(e: Event | React.FormEvent) => { + const target = + (e as CustomEvent)?.detail?.target || + (e.target as HTMLInputElement) + const checked = target.checked + if (checked) { + setNewModeGroups([...newModeGroups, group]) + } else { + setNewModeGroups( + newModeGroups.filter( + (g) => getGroupName(g) !== group, + ), + ) + } + }}> + {t(`prompts:tools.toolNames.${group}`)} + +
+ ) + } + return ( + getGroupName(g) === group)} + onChange={(e: Event | React.FormEvent) => { + const target = + (e as CustomEvent)?.detail?.target || + (e.target as HTMLInputElement) + const checked = target.checked + if (checked) { + setNewModeGroups([...newModeGroups, group]) + } else { + setNewModeGroups( + newModeGroups.filter((g) => getGroupName(g) !== group), + ) + } + }}> + {t(`prompts:tools.toolNames.${group}`)} + + ) + })}
{groupsError && (
{groupsError}
diff --git a/webview-ui/src/i18n/locales/ca/prompts.json b/webview-ui/src/i18n/locales/ca/prompts.json index 5730211daa..f041d7ea76 100644 --- a/webview-ui/src/i18n/locales/ca/prompts.json +++ b/webview-ui/src/i18n/locales/ca/prompts.json @@ -29,7 +29,19 @@ "command": "Executar comandes", "mcp": "Utilitzar MCP" }, - "noTools": "Cap" + "selectMcpServers": "Selecciona servidors MCP", + "searchMcpServers": "Cerca servidors MCP", + "requiredMcpList": "Servidors MCP requerits", + "noMcpServers": "No s'han trobat servidors MCP", + "noMatchFound": "No s'ha trobat cap coincidència", + "noTools": "Cap", + "mcpAll": "Tots", + "mcpSelectedCount": "{{included}} inclosos", + "mcpDefaultDescription": "Si no se selecciona cap servidor MCP, s'activaran tots per defecte.", + "buttons": { + "save": "Desa", + "clearAll": "Neteja-ho tot" + } }, "roleDefinition": { "title": "Definició de rol", diff --git a/webview-ui/src/i18n/locales/de/prompts.json b/webview-ui/src/i18n/locales/de/prompts.json index ce5fe66110..4f31fe3f77 100644 --- a/webview-ui/src/i18n/locales/de/prompts.json +++ b/webview-ui/src/i18n/locales/de/prompts.json @@ -29,7 +29,19 @@ "command": "Befehle ausführen", "mcp": "MCP verwenden" }, - "noTools": "Keine" + "selectMcpServers": "MCP-Server auswählen", + "searchMcpServers": "MCP-Server suchen", + "requiredMcpList": "Erforderliche MCP-Server", + "noMcpServers": "Keine MCP-Server gefunden", + "noMatchFound": "Keine Übereinstimmung gefunden", + "noTools": "Keine", + "mcpAll": "Alle", + "mcpSelectedCount": "{{included}} enthalten", + "mcpDefaultDescription": "Wenn kein MCP-Server ausgewählt ist, werden standardmäßig alle aktiviert.", + "buttons": { + "save": "Speichern", + "clearAll": "Alles löschen" + } }, "roleDefinition": { "title": "Rollendefinition", diff --git a/webview-ui/src/i18n/locales/en/prompts.json b/webview-ui/src/i18n/locales/en/prompts.json index 0ea5e133b8..a3b529626c 100644 --- a/webview-ui/src/i18n/locales/en/prompts.json +++ b/webview-ui/src/i18n/locales/en/prompts.json @@ -29,7 +29,19 @@ "command": "Run Commands", "mcp": "Use MCP" }, - "noTools": "None" + "selectMcpServers": "Select MCP Servers", + "searchMcpServers": "Search MCP Servers", + "requiredMcpList": "Required MCP Servers", + "noMcpServers": "No MCP servers found", + "noMatchFound": "No match found", + "noTools": "None", + "mcpAll": "All", + "mcpSelectedCount": "{{included}} Included", + "mcpDefaultDescription": "If no MCP server is selected, all will be enabled by default.", + "buttons": { + "save": "Save", + "clearAll": "Clear All" + } }, "roleDefinition": { "title": "Role Definition", diff --git a/webview-ui/src/i18n/locales/es/prompts.json b/webview-ui/src/i18n/locales/es/prompts.json index 26ee72b4b5..5918c8c388 100644 --- a/webview-ui/src/i18n/locales/es/prompts.json +++ b/webview-ui/src/i18n/locales/es/prompts.json @@ -29,7 +29,19 @@ "command": "Ejecutar comandos", "mcp": "Usar MCP" }, - "noTools": "Ninguna" + "selectMcpServers": "Seleccionar servidores MCP", + "searchMcpServers": "Buscar servidores MCP", + "requiredMcpList": "Servidores MCP requeridos", + "noMcpServers": "No se encontraron servidores MCP", + "noMatchFound": "No se encontraron coincidencias", + "noTools": "Ninguna", + "mcpAll": "Todos", + "mcpSelectedCount": "{{included}} incluidos", + "mcpDefaultDescription": "Si no se selecciona ningún servidor MCP, se habilitarán todos por defecto.", + "buttons": { + "save": "Guardar", + "clearAll": "Limpiar todo" + } }, "roleDefinition": { "title": "Definición de rol", diff --git a/webview-ui/src/i18n/locales/fr/prompts.json b/webview-ui/src/i18n/locales/fr/prompts.json index 3b43280c00..45e4a9c988 100644 --- a/webview-ui/src/i18n/locales/fr/prompts.json +++ b/webview-ui/src/i18n/locales/fr/prompts.json @@ -29,7 +29,19 @@ "command": "Exécuter des commandes", "mcp": "Utiliser MCP" }, - "noTools": "Aucun" + "selectMcpServers": "Sélectionner les serveurs MCP", + "searchMcpServers": "Rechercher les serveurs MCP", + "requiredMcpList": "Serveurs MCP requis", + "noMcpServers": "Aucun serveur MCP trouvé", + "noMatchFound": "Aucune correspondance trouvée", + "noTools": "Aucun", + "mcpAll": "Tous", + "mcpSelectedCount": "{{included}} inclus", + "mcpDefaultDescription": "Si aucun serveur MCP n'est sélectionné, tous seront activés par défaut.", + "buttons": { + "save": "Enregistrer", + "clearAll": "Tout effacer" + } }, "roleDefinition": { "title": "Définition du rôle", diff --git a/webview-ui/src/i18n/locales/hi/prompts.json b/webview-ui/src/i18n/locales/hi/prompts.json index bd403adde9..f9705a0d07 100644 --- a/webview-ui/src/i18n/locales/hi/prompts.json +++ b/webview-ui/src/i18n/locales/hi/prompts.json @@ -29,7 +29,19 @@ "command": "कमांड्स चलाएँ", "mcp": "MCP का उपयोग करें" }, - "noTools": "कोई नहीं" + "selectMcpServers": "MCP सर्वर चुनें", + "searchMcpServers": "MCP सर्वर खोजें", + "requiredMcpList": "आवश्यक MCP सर्वर", + "noMcpServers": "कोई MCP सर्वर नहीं मिला", + "noMatchFound": "कोई मिलान नहीं मिला", + "noTools": "कोई नहीं", + "mcpAll": "सभी", + "mcpSelectedCount": "{{included}} शामिल", + "mcpDefaultDescription": "यदि कोई MCP सर्वर चयनित नहीं है, तो सभी डिफ़ॉल्ट रूप से सक्षम होंगे।", + "buttons": { + "save": "सहेजें", + "clearAll": "सभी साफ़ करें" + } }, "roleDefinition": { "title": "भूमिका परिभाषा", diff --git a/webview-ui/src/i18n/locales/id/prompts.json b/webview-ui/src/i18n/locales/id/prompts.json index b4d45459f0..d4de99df7e 100644 --- a/webview-ui/src/i18n/locales/id/prompts.json +++ b/webview-ui/src/i18n/locales/id/prompts.json @@ -29,7 +29,19 @@ "command": "Jalankan Perintah", "mcp": "Gunakan MCP" }, - "noTools": "Tidak Ada" + "selectMcpServers": "Pilih server MCP", + "searchMcpServers": "Cari server MCP", + "requiredMcpList": "Server MCP yang Diperlukan", + "noMcpServers": "Tidak ada server MCP ditemukan", + "noMatchFound": "Tidak ada hasil cocok", + "noTools": "Tidak Ada", + "mcpAll": "Semua", + "mcpSelectedCount": "{{included}} termasuk", + "mcpDefaultDescription": "Jika tidak ada server MCP yang dipilih, semua akan diaktifkan secara default.", + "buttons": { + "save": "Simpan", + "clearAll": "Bersihkan semua" + } }, "roleDefinition": { "title": "Definisi Peran", diff --git a/webview-ui/src/i18n/locales/it/prompts.json b/webview-ui/src/i18n/locales/it/prompts.json index 57c144a650..7299f7eaa6 100644 --- a/webview-ui/src/i18n/locales/it/prompts.json +++ b/webview-ui/src/i18n/locales/it/prompts.json @@ -29,7 +29,19 @@ "command": "Esegui comandi", "mcp": "Usa MCP" }, - "noTools": "Nessuno" + "selectMcpServers": "Seleziona server MCP", + "searchMcpServers": "Cerca server MCP", + "requiredMcpList": "Server MCP richiesti", + "noMcpServers": "Nessun server MCP trovato", + "noMatchFound": "Nessuna corrispondenza trovata", + "noTools": "Nessuno", + "mcpAll": "Tutti", + "mcpSelectedCount": "{{included}} inclusi", + "mcpDefaultDescription": "Se non viene selezionato alcun server MCP, tutti saranno abilitati per impostazione predefinita.", + "buttons": { + "save": "Salva", + "clearAll": "Cancella tutto" + } }, "roleDefinition": { "title": "Definizione del ruolo", diff --git a/webview-ui/src/i18n/locales/ja/prompts.json b/webview-ui/src/i18n/locales/ja/prompts.json index 15cb64dcf2..b19a6178a7 100644 --- a/webview-ui/src/i18n/locales/ja/prompts.json +++ b/webview-ui/src/i18n/locales/ja/prompts.json @@ -29,7 +29,19 @@ "command": "コマンドを実行", "mcp": "MCP を使用" }, - "noTools": "なし" + "selectMcpServers": "MCPサーバーを選択", + "searchMcpServers": "MCPサーバーを検索", + "requiredMcpList": "必要な MCP サーバー", + "noMcpServers": "MCPサーバーが見つかりません", + "noMatchFound": "一致するものがありません", + "noTools": "なし", + "mcpAll": "すべて", + "mcpSelectedCount": "{{included}} 含まれる", + "mcpDefaultDescription": "MCP サーバーが選択されていない場合、すべてがデフォルトで有効になります。", + "buttons": { + "save": "保存", + "clearAll": "すべてクリア" + } }, "roleDefinition": { "title": "役割の定義", diff --git a/webview-ui/src/i18n/locales/ko/prompts.json b/webview-ui/src/i18n/locales/ko/prompts.json index d21107be43..4f2d0d74d2 100644 --- a/webview-ui/src/i18n/locales/ko/prompts.json +++ b/webview-ui/src/i18n/locales/ko/prompts.json @@ -29,7 +29,19 @@ "command": "명령 실행", "mcp": "MCP 사용" }, - "noTools": "없음" + "selectMcpServers": "MCP 서버 선택", + "searchMcpServers": "MCP 서버 검색", + "requiredMcpList": "필수 MCP 서버", + "noMcpServers": "MCP 서버를 찾을 수 없음", + "noMatchFound": "일치하는 항목 없음", + "noTools": "없음", + "mcpAll": "전체", + "mcpSelectedCount": "{{included}} 포함됨", + "mcpDefaultDescription": "MCP 서버를 선택하지 않으면 전체가 기본적으로 활성화됩니다.", + "buttons": { + "save": "저장", + "clearAll": "전체 해제" + } }, "roleDefinition": { "title": "역할 정의", diff --git a/webview-ui/src/i18n/locales/nl/prompts.json b/webview-ui/src/i18n/locales/nl/prompts.json index 43af1ada59..0300424571 100644 --- a/webview-ui/src/i18n/locales/nl/prompts.json +++ b/webview-ui/src/i18n/locales/nl/prompts.json @@ -29,7 +29,19 @@ "command": "Commando's uitvoeren", "mcp": "MCP gebruiken" }, - "noTools": "Geen" + "selectMcpServers": "Selecteer MCP-servers", + "searchMcpServers": "Zoek MCP-servers", + "requiredMcpList": "Vereiste MCP-servers", + "noMcpServers": "Geen MCP-servers gevonden", + "noMatchFound": "Geen overeenkomsten gevonden", + "noTools": "Geen", + "mcpAll": "Alle", + "mcpSelectedCount": "{{included}} inbegrepen", + "mcpDefaultDescription": "Als er geen MCP-server is geselecteerd, worden standaard alle ingeschakeld.", + "buttons": { + "save": "Opslaan", + "clearAll": "Alles wissen" + } }, "roleDefinition": { "title": "Roldefinitie", diff --git a/webview-ui/src/i18n/locales/pl/prompts.json b/webview-ui/src/i18n/locales/pl/prompts.json index 7bd71f49b0..2d495e7e85 100644 --- a/webview-ui/src/i18n/locales/pl/prompts.json +++ b/webview-ui/src/i18n/locales/pl/prompts.json @@ -29,7 +29,19 @@ "command": "Uruchamiaj polecenia", "mcp": "Używaj MCP" }, - "noTools": "Brak" + "selectMcpServers": "Wybierz serwery MCP", + "searchMcpServers": "Szukaj serwerów MCP", + "requiredMcpList": "Wymagane serwery MCP", + "noMcpServers": "Nie znaleziono serwerów MCP", + "noMatchFound": "Brak pasujących wyników", + "noTools": "Brak", + "mcpAll": "Wszystkie", + "mcpSelectedCount": "{{included}} uwzględnione", + "mcpDefaultDescription": "Jeśli nie wybrano żadnego serwera MCP, domyślnie wszystkie będą włączone.", + "buttons": { + "save": "Zapisz", + "clearAll": "Wyczyść wszystko" + } }, "roleDefinition": { "title": "Definicja roli", diff --git a/webview-ui/src/i18n/locales/pt-BR/prompts.json b/webview-ui/src/i18n/locales/pt-BR/prompts.json index 5bc3234c4d..7e2ccfc213 100644 --- a/webview-ui/src/i18n/locales/pt-BR/prompts.json +++ b/webview-ui/src/i18n/locales/pt-BR/prompts.json @@ -29,7 +29,19 @@ "command": "Executar comandos", "mcp": "Usar MCP" }, - "noTools": "Nenhuma" + "selectMcpServers": "Selecionar servidores MCP", + "searchMcpServers": "Buscar servidores MCP", + "requiredMcpList": "Servidores MCP necessários", + "noMcpServers": "Nenhum servidor MCP encontrado", + "noMatchFound": "Nenhuma correspondência encontrada", + "noTools": "Nenhuma", + "mcpAll": "Todos", + "mcpSelectedCount": "{{included}} incluídos", + "mcpDefaultDescription": "Se nenhum servidor MCP for selecionado, todos serão ativados por padrão.", + "buttons": { + "save": "Salvar", + "clearAll": "Limpar tudo" + } }, "roleDefinition": { "title": "Definição de função", diff --git a/webview-ui/src/i18n/locales/ru/prompts.json b/webview-ui/src/i18n/locales/ru/prompts.json index cc9210c678..fc5a7123ac 100644 --- a/webview-ui/src/i18n/locales/ru/prompts.json +++ b/webview-ui/src/i18n/locales/ru/prompts.json @@ -29,7 +29,19 @@ "command": "Выполнять команды", "mcp": "Использовать MCP" }, - "noTools": "Отсутствуют" + "selectMcpServers": "Выбери MCP-серверы", + "searchMcpServers": "Искать MCP-серверы", + "requiredMcpList": "Требуемые MCP-серверы", + "noMcpServers": "MCP-серверы не найдены", + "noMatchFound": "Совпадений не найдено", + "noTools": "Отсутствуют", + "mcpAll": "Все", + "mcpSelectedCount": "{{included}} включено", + "mcpDefaultDescription": "Если не выбран ни один MCP-сервер, по умолчанию будут активированы все.", + "buttons": { + "save": "Сохранить", + "clearAll": "Очистить всё" + } }, "roleDefinition": { "title": "Определение роли", diff --git a/webview-ui/src/i18n/locales/tr/prompts.json b/webview-ui/src/i18n/locales/tr/prompts.json index eec283977c..92695db395 100644 --- a/webview-ui/src/i18n/locales/tr/prompts.json +++ b/webview-ui/src/i18n/locales/tr/prompts.json @@ -29,7 +29,19 @@ "command": "Komutları Çalıştır", "mcp": "MCP Kullan" }, - "noTools": "Yok" + "selectMcpServers": "MCP sunucularını seç", + "searchMcpServers": "MCP sunucularını ara", + "requiredMcpList": "Gerekli MCP Sunucuları", + "noMcpServers": "MCP sunucusu bulunamadı", + "noMatchFound": "Eşleşme bulunamadı", + "noTools": "Yok", + "mcpAll": "Tümü", + "mcpSelectedCount": "{{included}} dahil", + "mcpDefaultDescription": "Hiçbir MCP sunucusu seçilmezse, varsayılan olarak tümü etkinleştirilir.", + "buttons": { + "save": "Kaydet", + "clearAll": "Tümünü temizle" + } }, "roleDefinition": { "title": "Rol Tanımı", diff --git a/webview-ui/src/i18n/locales/vi/prompts.json b/webview-ui/src/i18n/locales/vi/prompts.json index d7a38cda6f..d9179c6a43 100644 --- a/webview-ui/src/i18n/locales/vi/prompts.json +++ b/webview-ui/src/i18n/locales/vi/prompts.json @@ -29,7 +29,19 @@ "command": "Chạy lệnh", "mcp": "Sử dụng MCP" }, - "noTools": "Không có" + "selectMcpServers": "Chọn máy chủ MCP", + "searchMcpServers": "Tìm kiếm máy chủ MCP", + "requiredMcpList": "Máy chủ MCP cần thiết", + "noMcpServers": "Không tìm thấy máy chủ MCP", + "noMatchFound": "Không tìm thấy kết quả phù hợp", + "noTools": "Không có", + "mcpAll": "Tất cả", + "mcpSelectedCount": "{{included}} đã bao gồm", + "mcpDefaultDescription": "Nếu không chọn máy chủ MCP nào, tất cả sẽ được bật mặc định.", + "buttons": { + "save": "Lưu", + "clearAll": "Xóa tất cả" + } }, "roleDefinition": { "title": "Định nghĩa vai trò", diff --git a/webview-ui/src/i18n/locales/zh-CN/prompts.json b/webview-ui/src/i18n/locales/zh-CN/prompts.json index c21c22b7bd..45af8136ed 100644 --- a/webview-ui/src/i18n/locales/zh-CN/prompts.json +++ b/webview-ui/src/i18n/locales/zh-CN/prompts.json @@ -29,7 +29,19 @@ "command": "运行命令", "mcp": "MCP服务" }, - "noTools": "无" + "selectMcpServers": "选择 MCP 服务", + "searchMcpServers": "搜索 MCP 服务", + "requiredMcpList": "所需 MCP 服务", + "noMcpServers": "未发现 MCP 服务", + "noMatchFound": "无匹配结果", + "noTools": "无", + "mcpAll": "全部", + "mcpSelectedCount": "{{included}} 已包含", + "mcpDefaultDescription": "如果未选择任何 MCP 服务,将默认启用全部。", + "buttons": { + "save": "保存", + "clearAll": "清除全部" + } }, "roleDefinition": { "title": "角色定义", diff --git a/webview-ui/src/i18n/locales/zh-TW/prompts.json b/webview-ui/src/i18n/locales/zh-TW/prompts.json index 47a32d7d83..0687e8e091 100644 --- a/webview-ui/src/i18n/locales/zh-TW/prompts.json +++ b/webview-ui/src/i18n/locales/zh-TW/prompts.json @@ -29,7 +29,19 @@ "command": "執行命令", "mcp": "使用 MCP" }, - "noTools": "無" + "selectMcpServers": "選擇 MCP 伺服器", + "searchMcpServers": "搜尋 MCP 伺服器", + "requiredMcpList": "所需 MCP 伺服器", + "noMcpServers": "未找到 MCP 伺服器", + "noMatchFound": "沒有符合的結果", + "noTools": "無", + "mcpAll": "全部", + "mcpSelectedCount": "{{included}} 已包含", + "mcpDefaultDescription": "若未選擇任何 MCP 伺服器,則預設啟用全部。", + "buttons": { + "save": "儲存", + "clearAll": "清除全部" + } }, "roleDefinition": { "title": "角色定義",