mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Support specifying available and unavailable MCP servers in custom mode
This commit is contained in:
parent
1237eb825b
commit
d474779023
23 changed files with 693 additions and 68 deletions
|
|
@ -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<typeof groupOptionsSchema>
|
||||
|
|
|
|||
|
|
@ -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<string> {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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(""),
|
||||
])
|
||||
|
||||
|
|
|
|||
256
webview-ui/src/components/modes/McpSelector.tsx
Normal file
256
webview-ui/src/components/modes/McpSelector.tsx
Normal file
|
|
@ -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<McpSelectorProps> = ({
|
||||
group,
|
||||
isEnabled,
|
||||
isCustomMode,
|
||||
mcpServers,
|
||||
currentMode,
|
||||
visualMode,
|
||||
customModes,
|
||||
findModeBySlug,
|
||||
updateCustomMode,
|
||||
}) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
// State
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
const [mcpIncludedList, setMcpIncludedList] = useState<string[]>([])
|
||||
const [searchValue, setSearchValue] = useState("")
|
||||
const searchInputRef = useRef<HTMLInputElement | null>(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 (
|
||||
<Popover
|
||||
open={isDialogOpen}
|
||||
onOpenChange={(open) => {
|
||||
setIsDialogOpen(open)
|
||||
// Reset search box
|
||||
if (!open) {
|
||||
setTimeout(() => {
|
||||
setSearchValue("")
|
||||
}, 100)
|
||||
}
|
||||
}}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="secondary" size="sm" style={{ marginLeft: 4 }} className="flex items-center gap-1">
|
||||
{/* Dynamically display button text */}
|
||||
{mcpIncludedList.length === 0
|
||||
? t("prompts:tools.mcpAll")
|
||||
: t("prompts:tools.mcpSelectedCount", {
|
||||
included: mcpIncludedList.length,
|
||||
})}
|
||||
<ChevronsUpDown className="opacity-50 size-3" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0 w-[400px] bg-vscode-editor-background">
|
||||
<Command>
|
||||
<div className="flex items-center border-b border-vscode-input-border p-2">
|
||||
<div className="font-medium text-sm flex-1">{t("prompts:tools.selectMcpServers")}</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="secondary" size="sm" onClick={() => setMcpIncludedList([])}>
|
||||
{t("prompts:tools.buttons.clearAll")}
|
||||
</Button>
|
||||
<Button variant="default" size="sm" onClick={handleSave}>
|
||||
{t("prompts:tools.buttons.save")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<CommandInput
|
||||
ref={searchInputRef}
|
||||
value={searchValue}
|
||||
onValueChange={setSearchValue}
|
||||
placeholder={t("prompts:tools.searchMcpServers")}
|
||||
className="h-9 mr-4"
|
||||
/>
|
||||
{searchValue.length > 0 && (
|
||||
<div className="absolute right-2 top-0 bottom-0 flex items-center justify-center">
|
||||
<X
|
||||
className="text-vscode-input-foreground opacity-50 hover:opacity-100 size-4 p-0.5 cursor-pointer"
|
||||
onClick={() => {
|
||||
setSearchValue("")
|
||||
searchInputRef.current?.focus()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="border-b border-vscode-input-border p-2">
|
||||
<div className="text-sm font-medium text-vscode-foreground mb-2">
|
||||
{t("prompts:tools.requiredMcpList")}
|
||||
</div>
|
||||
<div className="text-sm text-vscode-descriptionForeground mb-2">
|
||||
{t("prompts:tools.mcpDefaultDescription")}
|
||||
</div>
|
||||
<CommandList className="max-h-[150px] overflow-auto bg-vscode-editorWidget-background">
|
||||
<CommandEmpty>
|
||||
{mcpServers.length === 0 ? (
|
||||
<div className="py-2 px-2 text-sm text-vscode-descriptionForeground">
|
||||
{t("prompts:tools.noMcpServers")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="py-2 px-2 text-sm">{t("prompts:tools.noMatchFound")}</div>
|
||||
)}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{mcpServers
|
||||
.filter(
|
||||
(server) =>
|
||||
!searchValue ||
|
||||
server.name.toLowerCase().includes(searchValue.toLowerCase()),
|
||||
)
|
||||
.map((server) => (
|
||||
<CommandItem
|
||||
key={`included-${server.name}`}
|
||||
value={`included-${server.name}`}
|
||||
onSelect={() => {
|
||||
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">
|
||||
<div className="flex items-center flex-1 gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={mcpIncludedList.includes(server.name)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
const isIncluded = mcpIncludedList.includes(server.name)
|
||||
if (isIncluded) {
|
||||
setMcpIncludedList(
|
||||
mcpIncludedList.filter((n) => n !== server.name),
|
||||
)
|
||||
} else {
|
||||
setMcpIncludedList([...mcpIncludedList, server.name])
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span>{server.name}</span>
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</div>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
export default McpSelector
|
||||
|
|
@ -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 (
|
||||
<div
|
||||
key={group}
|
||||
className="col-span-2"
|
||||
style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={isGroupEnabled}
|
||||
onChange={handleGroupChange(
|
||||
group,
|
||||
Boolean(isCustomMode),
|
||||
customMode,
|
||||
)}
|
||||
disabled={!isCustomMode}>
|
||||
{t(`prompts:tools.toolNames.${group}`)}
|
||||
</VSCodeCheckbox>
|
||||
{isGroupEnabled && isCustomMode && (
|
||||
<McpSelector
|
||||
group={group}
|
||||
isEnabled={isGroupEnabled}
|
||||
isCustomMode={Boolean(isCustomMode)}
|
||||
mcpServers={mcpServers}
|
||||
currentMode={currentMode}
|
||||
visualMode={visualMode}
|
||||
customModes={customModes}
|
||||
findModeBySlug={findModeBySlug}
|
||||
updateCustomMode={updateCustomMode}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={isGroupEnabled}
|
||||
onChange={handleGroupChange(group, Boolean(isCustomMode), customMode)}
|
||||
disabled={!isCustomMode}>
|
||||
{t(`prompts:tools.toolNames.${group}`)}
|
||||
{group === "edit" && (
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-0.5">
|
||||
{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}/`
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
)}
|
||||
</VSCodeCheckbox>
|
||||
<div key={group} style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={isGroupEnabled}
|
||||
onChange={handleGroupChange(
|
||||
group,
|
||||
Boolean(isCustomMode),
|
||||
customMode,
|
||||
)}
|
||||
disabled={!isCustomMode}>
|
||||
{t(`prompts:tools.toolNames.${group}`)}
|
||||
{group === "edit" && (
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-0.5">
|
||||
{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}/`
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
)}
|
||||
</VSCodeCheckbox>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
|
@ -1494,25 +1539,57 @@ const ModesView = ({ onDone }: ModesViewProps) => {
|
|||
{t("prompts:createModeDialog.tools.description")}
|
||||
</div>
|
||||
<div className="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2">
|
||||
{availableGroups.map((group) => (
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={newModeGroups.some((g) => getGroupName(g) === group)}
|
||||
onChange={(e: Event | React.FormEvent<HTMLElement>) => {
|
||||
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}`)}
|
||||
</VSCodeCheckbox>
|
||||
))}
|
||||
{availableGroups.map((group) => {
|
||||
if (group === "mcp") {
|
||||
return (
|
||||
<div
|
||||
key={group}
|
||||
className="col-span-2"
|
||||
style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={newModeGroups.some((g) => getGroupName(g) === group)}
|
||||
onChange={(e: Event | React.FormEvent<HTMLElement>) => {
|
||||
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}`)}
|
||||
</VSCodeCheckbox>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<VSCodeCheckbox
|
||||
key={group}
|
||||
checked={newModeGroups.some((g) => getGroupName(g) === group)}
|
||||
onChange={(e: Event | React.FormEvent<HTMLElement>) => {
|
||||
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}`)}
|
||||
</VSCodeCheckbox>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{groupsError && (
|
||||
<div className="text-xs text-vscode-errorForeground mt-1">{groupsError}</div>
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/ca/prompts.json
generated
14
webview-ui/src/i18n/locales/ca/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/de/prompts.json
generated
14
webview-ui/src/i18n/locales/de/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/es/prompts.json
generated
14
webview-ui/src/i18n/locales/es/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/fr/prompts.json
generated
14
webview-ui/src/i18n/locales/fr/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/hi/prompts.json
generated
14
webview-ui/src/i18n/locales/hi/prompts.json
generated
|
|
@ -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": "भूमिका परिभाषा",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/id/prompts.json
generated
14
webview-ui/src/i18n/locales/id/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/it/prompts.json
generated
14
webview-ui/src/i18n/locales/it/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/ja/prompts.json
generated
14
webview-ui/src/i18n/locales/ja/prompts.json
generated
|
|
@ -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": "役割の定義",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/ko/prompts.json
generated
14
webview-ui/src/i18n/locales/ko/prompts.json
generated
|
|
@ -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": "역할 정의",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/nl/prompts.json
generated
14
webview-ui/src/i18n/locales/nl/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/pl/prompts.json
generated
14
webview-ui/src/i18n/locales/pl/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/pt-BR/prompts.json
generated
14
webview-ui/src/i18n/locales/pt-BR/prompts.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/ru/prompts.json
generated
14
webview-ui/src/i18n/locales/ru/prompts.json
generated
|
|
@ -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": "Определение роли",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/tr/prompts.json
generated
14
webview-ui/src/i18n/locales/tr/prompts.json
generated
|
|
@ -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ı",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/vi/prompts.json
generated
14
webview-ui/src/i18n/locales/vi/prompts.json
generated
|
|
@ -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ò",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/zh-CN/prompts.json
generated
14
webview-ui/src/i18n/locales/zh-CN/prompts.json
generated
|
|
@ -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": "角色定义",
|
||||
|
|
|
|||
14
webview-ui/src/i18n/locales/zh-TW/prompts.json
generated
14
webview-ui/src/i18n/locales/zh-TW/prompts.json
generated
|
|
@ -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": "角色定義",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue