diff --git a/packages/types/src/mode.ts b/packages/types/src/mode.ts index 88dcbb9574..d4cb347189 100644 --- a/packages/types/src/mode.ts +++ b/packages/types/src/mode.ts @@ -26,6 +26,23 @@ export const groupOptionsSchema = z.object({ { message: "Invalid regular expression pattern" }, ), description: z.string().optional(), + mcp: z + .object({ + included: z.array( + z.union([ + z.string(), + z.record( + z.string(), + z.object({ + allowedTools: z.array(z.string()).optional(), // not used yet + disallowedTools: z.array(z.string()).optional(), // not used yet + }), + ), + ]), + ), + description: z.string().optional(), + }) + .optional(), }) export type GroupOptions = z.infer diff --git a/src/core/prompts/sections/mcp-servers.ts b/src/core/prompts/sections/mcp-servers.ts index 643233ab6f..f5eb4d90f2 100644 --- a/src/core/prompts/sections/mcp-servers.ts +++ b/src/core/prompts/sections/mcp-servers.ts @@ -1,20 +1,79 @@ 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 "" } + // Get MCP configuration for current mode + let mcpIncludedList: string[] | undefined + + if (currentMode) { + // Find MCP group configuration + const mcpGroup = currentMode.groups.find((group: GroupEntry) => { + if (Array.isArray(group) && group.length === 2 && group[0] === "mcp") { + return true + } + return getGroupName(group) === "mcp" + }) + + // If MCP group configuration is found, get mcpIncludedList from mcp.included + if (mcpGroup && Array.isArray(mcpGroup) && mcpGroup.length === 2) { + const options = mcpGroup[1] as { mcp?: { included?: unknown[] } } + mcpIncludedList = Array.isArray(options.mcp?.included) + ? options.mcp.included.filter((item: unknown): item is string => typeof item === "string") + : undefined + } + } + + const filteredServers = memoizeFilteredServers(mcpHub, mcpIncludedList) + const connectedServers = - mcpHub.getServers().length > 0 - ? `${mcpHub - .getServers() - .filter((server) => server.status === "connected") + filteredServers.length > 0 + ? `${filteredServers .map((server) => { const tools = server.tools ?.filter((tool) => tool.enabledForPrompt !== false) 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/webview-ui/src/components/modes/McpSelector.tsx b/webview-ui/src/components/modes/McpSelector.tsx new file mode 100644 index 0000000000..4baa3012fd --- /dev/null +++ b/webview-ui/src/components/modes/McpSelector.tsx @@ -0,0 +1,256 @@ +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, GroupOptions } 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 + } + + const mcpGroupArr = currentMode.groups?.find( + (g: GroupEntry): g is ["mcp", GroupOptions] => Array.isArray(g) && g.length === 2 && g[0] === "mcp", + ) + + const rawGroupOptions: GroupOptions | undefined = mcpGroupArr ? mcpGroupArr[1] : undefined + + const included = Array.isArray(rawGroupOptions?.mcp?.included) + ? (rawGroupOptions.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[] { + let mcpGroupFound = false + const newGroups = groups + .map((g) => { + if (Array.isArray(g) && g[0] === group) { + mcpGroupFound = true + return [ + group, + { + ...(g[1] || {}), + mcp: mcpIncludedList.length > 0 ? { included: mcpIncludedList } : undefined, + }, + ] as GroupEntry + } + if (typeof g === "string" && g === group) { + mcpGroupFound = true + return [ + group, + { + mcp: mcpIncludedList.length > 0 ? { included: mcpIncludedList } : undefined, + }, + ] as GroupEntry + } + return g + }) + .filter((g) => g !== undefined) + + if (!mcpGroupFound && group === "mcp") { + const groupsWithoutSimpleMcp = newGroups.filter((g) => g !== "mcp") + groupsWithoutSimpleMcp.push([ + "mcp", + { + mcp: mcpIncludedList.length > 0 ? { included: mcpIncludedList } : undefined, + }, + ]) + return groupsWithoutSimpleMcp as GroupEntry[] + } else { + return newGroups 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")}
+ )} +
+ + {mcpServers + .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..f7e4739fe1 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) @@ -75,6 +76,7 @@ const ModesView = ({ onDone }: ModesViewProps) => { customInstructions, setCustomInstructions, customModes, + mcpServers, } = useExtensionState() // Use a local state to track the visually active mode @@ -1018,33 +1020,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 +1539,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": "角色定義",