fix: validate MCP tool exists before execution (#7632)

Co-authored-by: Roo Code <roomote@roocode.com>
Co-authored-by: Daniel Riccio <ricciodaniel98@gmail.com>
This commit is contained in:
roomote[bot] 2025-09-04 17:44:31 -04:00 committed by GitHub
parent 72502d8f1a
commit 7935c94827
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 460 additions and 18 deletions

View file

@ -72,6 +72,16 @@ Otherwise, if you have not completed the task and do not need additional informa
invalidMcpToolArgumentError: (serverName: string, toolName: string) =>
`Invalid JSON argument used with ${serverName} for ${toolName}. Please retry with a properly formatted JSON argument.`,
unknownMcpToolError: (serverName: string, toolName: string, availableTools: string[]) => {
const toolsList = availableTools.length > 0 ? availableTools.join(", ") : "No tools available"
return `Tool '${toolName}' does not exist on server '${serverName}'.\n\nAvailable tools on this server: ${toolsList}\n\nPlease use one of the available tools or check if the server is properly configured.`
},
unknownMcpServerError: (serverName: string, availableServers: string[]) => {
const serversList = availableServers.length > 0 ? availableServers.join(", ") : "No servers available"
return `Server '${serverName}' is not configured. Available servers: ${serversList}`
},
toolResult: (
text: string,
images?: string[],

View file

@ -10,6 +10,14 @@ vi.mock("../../prompts/responses", () => ({
toolResult: vi.fn((result: string) => `Tool result: ${result}`),
toolError: vi.fn((error: string) => `Tool error: ${error}`),
invalidMcpToolArgumentError: vi.fn((server: string, tool: string) => `Invalid args for ${server}:${tool}`),
unknownMcpToolError: vi.fn((server: string, tool: string, availableTools: string[]) => {
const toolsList = availableTools.length > 0 ? availableTools.join(", ") : "No tools available"
return `Tool '${tool}' does not exist on server '${server}'. Available tools: ${toolsList}`
}),
unknownMcpServerError: vi.fn((server: string, availableServers: string[]) => {
const list = availableServers.length > 0 ? availableServers.join(", ") : "No servers available"
return `Server '${server}' is not configured. Available servers: ${list}`
}),
},
}))
@ -18,6 +26,12 @@ vi.mock("../../../i18n", () => ({
if (key === "mcp:errors.invalidJsonArgument" && params?.toolName) {
return `Roo tried to use ${params.toolName} with an invalid JSON argument. Retrying...`
}
if (key === "mcp:errors.toolNotFound" && params) {
return `Tool '${params.toolName}' does not exist on server '${params.serverName}'. Available tools: ${params.availableTools}`
}
if (key === "mcp:errors.serverNotFound" && params) {
return `MCP server '${params.serverName}' is not configured. Available servers: ${params.availableServers}`
}
return key
}),
}))
@ -40,6 +54,7 @@ describe("useMcpToolTool", () => {
deref: vi.fn().mockReturnValue({
getMcpHub: vi.fn().mockReturnValue({
callTool: vi.fn(),
getAllServers: vi.fn().mockReturnValue([]),
}),
postMessageToWebview: vi.fn(),
}),
@ -224,6 +239,10 @@ describe("useMcpToolTool", () => {
partial: false,
}
// Ensure validation does not fail due to unknown server by returning no provider once
// This makes validateToolExists return isValid: true and proceed to askApproval
mockProviderRef.deref.mockReturnValueOnce(undefined as any)
mockAskApproval.mockResolvedValue(false)
await useMcpToolTool(
@ -252,6 +271,19 @@ describe("useMcpToolTool", () => {
partial: false,
}
// Ensure validation passes so askApproval is reached and throws
mockProviderRef.deref.mockReturnValueOnce({
getMcpHub: () => ({
getAllServers: vi
.fn()
.mockReturnValue([
{ name: "test_server", tools: [{ name: "test_tool", description: "desc" }] },
]),
callTool: vi.fn(),
}),
postMessageToWebview: vi.fn(),
})
const error = new Error("Unexpected error")
mockAskApproval.mockRejectedValue(error)
@ -266,5 +298,239 @@ describe("useMcpToolTool", () => {
expect(mockHandleError).toHaveBeenCalledWith("executing MCP tool", error)
})
it("should reject unknown tool names", async () => {
// Reset consecutiveMistakeCount for this test
mockTask.consecutiveMistakeCount = 0
const mockServers = [
{
name: "test-server",
tools: [
{ name: "existing-tool-1", description: "Tool 1" },
{ name: "existing-tool-2", description: "Tool 2" },
],
},
]
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
getAllServers: vi.fn().mockReturnValue(mockServers),
callTool: vi.fn(),
}),
postMessageToWebview: vi.fn(),
})
const block: ToolUse = {
type: "tool_use",
name: "use_mcp_tool",
params: {
server_name: "test-server",
tool_name: "non-existing-tool",
arguments: JSON.stringify({ test: "data" }),
},
partial: false,
}
await useMcpToolTool(
mockTask as Task,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockTask.consecutiveMistakeCount).toBe(1)
expect(mockTask.recordToolError).toHaveBeenCalledWith("use_mcp_tool")
expect(mockTask.say).toHaveBeenCalledWith("error", expect.stringContaining("does not exist"))
// Check that the error message contains available tools
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("existing-tool-1"))
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("existing-tool-2"))
})
it("should handle server with no tools", async () => {
// Reset consecutiveMistakeCount for this test
mockTask.consecutiveMistakeCount = 0
const mockServers = [
{
name: "test-server",
tools: [],
},
]
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
getAllServers: vi.fn().mockReturnValue(mockServers),
callTool: vi.fn(),
}),
postMessageToWebview: vi.fn(),
})
const block: ToolUse = {
type: "tool_use",
name: "use_mcp_tool",
params: {
server_name: "test-server",
tool_name: "any-tool",
arguments: JSON.stringify({ test: "data" }),
},
partial: false,
}
await useMcpToolTool(
mockTask as Task,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockTask.consecutiveMistakeCount).toBe(1)
expect(mockTask.recordToolError).toHaveBeenCalledWith("use_mcp_tool")
expect(mockTask.say).toHaveBeenCalledWith("error", expect.stringContaining("does not exist"))
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("No tools available"))
})
it("should allow valid tool names", async () => {
// Reset consecutiveMistakeCount for this test
mockTask.consecutiveMistakeCount = 0
const mockServers = [
{
name: "test-server",
tools: [{ name: "valid-tool", description: "Valid Tool" }],
},
]
const mockToolResult = {
content: [{ type: "text", text: "Tool executed successfully" }],
}
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
getAllServers: vi.fn().mockReturnValue(mockServers),
callTool: vi.fn().mockResolvedValue(mockToolResult),
}),
postMessageToWebview: vi.fn(),
})
const block: ToolUse = {
type: "tool_use",
name: "use_mcp_tool",
params: {
server_name: "test-server",
tool_name: "valid-tool",
arguments: JSON.stringify({ test: "data" }),
},
partial: false,
}
mockAskApproval.mockResolvedValue(true)
await useMcpToolTool(
mockTask as Task,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
expect(mockTask.consecutiveMistakeCount).toBe(0)
expect(mockTask.recordToolError).not.toHaveBeenCalled()
expect(mockTask.say).toHaveBeenCalledWith("mcp_server_request_started")
expect(mockTask.say).toHaveBeenCalledWith("mcp_server_response", "Tool executed successfully")
})
it("should reject unknown server names with available servers listed", async () => {
// Arrange
mockTask.consecutiveMistakeCount = 0
const mockServers = [{ name: "s1", tools: [] }]
const callToolMock = vi.fn()
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
getAllServers: vi.fn().mockReturnValue(mockServers),
callTool: callToolMock,
}),
postMessageToWebview: vi.fn(),
})
const block: ToolUse = {
type: "tool_use",
name: "use_mcp_tool",
params: {
server_name: "unknown",
tool_name: "any-tool",
arguments: "{}",
},
partial: false,
}
// Act
await useMcpToolTool(
mockTask as Task,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Assert
expect(mockTask.consecutiveMistakeCount).toBe(1)
expect(mockTask.recordToolError).toHaveBeenCalledWith("use_mcp_tool")
expect(mockTask.say).toHaveBeenCalledWith("error", expect.stringContaining("not configured"))
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("s1"))
expect(callToolMock).not.toHaveBeenCalled()
expect(mockAskApproval).not.toHaveBeenCalled()
})
it("should reject unknown server names when no servers are available", async () => {
// Arrange
mockTask.consecutiveMistakeCount = 0
const callToolMock = vi.fn()
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
getAllServers: vi.fn().mockReturnValue([]),
callTool: callToolMock,
}),
postMessageToWebview: vi.fn(),
})
const block: ToolUse = {
type: "tool_use",
name: "use_mcp_tool",
params: {
server_name: "unknown",
tool_name: "any-tool",
arguments: "{}",
},
partial: false,
}
// Act
await useMcpToolTool(
mockTask as Task,
block,
mockAskApproval,
mockHandleError,
mockPushToolResult,
mockRemoveClosingTag,
)
// Assert
expect(mockTask.consecutiveMistakeCount).toBe(1)
expect(mockTask.recordToolError).toHaveBeenCalledWith("use_mcp_tool")
expect(mockTask.say).toHaveBeenCalledWith("error", expect.stringContaining("not configured"))
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("No servers available"))
expect(callToolMock).not.toHaveBeenCalled()
expect(mockAskApproval).not.toHaveBeenCalled()
})
})
})

View file

@ -81,6 +81,112 @@ async function validateParams(
}
}
async function validateToolExists(
cline: Task,
serverName: string,
toolName: string,
pushToolResult: PushToolResult,
): Promise<{ isValid: boolean; availableTools?: string[] }> {
try {
// Get the MCP hub to access server information
const provider = cline.providerRef.deref()
const mcpHub = provider?.getMcpHub()
if (!mcpHub) {
// If we can't get the MCP hub, we can't validate, so proceed with caution
return { isValid: true }
}
// Get all servers to find the specific one
const servers = mcpHub.getAllServers()
const server = servers.find((s) => s.name === serverName)
if (!server) {
// Fail fast when server is unknown
const availableServersArray = servers.map((s) => s.name)
const availableServers =
availableServersArray.length > 0 ? availableServersArray.join(", ") : "No servers available"
cline.consecutiveMistakeCount++
cline.recordToolError("use_mcp_tool")
await cline.say("error", t("mcp:errors.serverNotFound", { serverName, availableServers }))
pushToolResult(formatResponse.unknownMcpServerError(serverName, availableServersArray))
return { isValid: false, availableTools: [] }
}
// Check if the server has tools defined
if (!server.tools || server.tools.length === 0) {
// No tools available on this server
cline.consecutiveMistakeCount++
cline.recordToolError("use_mcp_tool")
await cline.say(
"error",
t("mcp:errors.toolNotFound", {
toolName,
serverName,
availableTools: "No tools available",
}),
)
pushToolResult(formatResponse.unknownMcpToolError(serverName, toolName, []))
return { isValid: false, availableTools: [] }
}
// Check if the requested tool exists
const tool = server.tools.find((tool) => tool.name === toolName)
if (!tool) {
// Tool not found - provide list of available tools
const availableToolNames = server.tools.map((tool) => tool.name)
cline.consecutiveMistakeCount++
cline.recordToolError("use_mcp_tool")
await cline.say(
"error",
t("mcp:errors.toolNotFound", {
toolName,
serverName,
availableTools: availableToolNames.join(", "),
}),
)
pushToolResult(formatResponse.unknownMcpToolError(serverName, toolName, availableToolNames))
return { isValid: false, availableTools: availableToolNames }
}
// Check if the tool is disabled (enabledForPrompt is false)
if (tool.enabledForPrompt === false) {
// Tool is disabled - only show enabled tools
const enabledTools = server.tools.filter((t) => t.enabledForPrompt !== false)
const enabledToolNames = enabledTools.map((t) => t.name)
cline.consecutiveMistakeCount++
cline.recordToolError("use_mcp_tool")
await cline.say(
"error",
t("mcp:errors.toolDisabled", {
toolName,
serverName,
availableTools:
enabledToolNames.length > 0 ? enabledToolNames.join(", ") : "No enabled tools available",
}),
)
pushToolResult(formatResponse.unknownMcpToolError(serverName, toolName, enabledToolNames))
return { isValid: false, availableTools: enabledToolNames }
}
// Tool exists and is enabled
return { isValid: true, availableTools: server.tools.map((tool) => tool.name) }
} catch (error) {
// If there's an error during validation, log it but don't block the tool execution
// The actual tool call might still fail with a proper error
console.error("Error validating MCP tool existence:", error)
return { isValid: true }
}
}
async function sendExecutionStatus(cline: Task, status: McpExecutionStatus): Promise<void> {
const clineProvider = await cline.providerRef.deref()
clineProvider?.postMessageToWebview({
@ -193,6 +299,12 @@ export async function useMcpToolTool(
const { serverName, toolName, parsedArguments } = validation
// Validate that the tool exists on the server
const toolValidation = await validateToolExists(cline, serverName, toolName, pushToolResult)
if (!toolValidation.isValid) {
return
}
// Reset mistake count on successful validation
cline.consecutiveMistakeCount = 0

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo ha intentat utilitzar {{toolName}} amb un argument JSON no vàlid. Tornant a intentar...",
"refresh_after_disable": "Ha fallat l'actualització de les connexions MCP després de desactivar",
"refresh_after_enable": "Ha fallat l'actualització de les connexions MCP després d'activar",
"disconnect_servers_partial": "Ha fallat la desconnexió de {{count}} servidor(s) MCP. Comprova la sortida per més detalls."
"disconnect_servers_partial": "Ha fallat la desconnexió de {{count}} servidor(s) MCP. Comprova la sortida per més detalls.",
"toolNotFound": "L'eina '{{toolName}}' no existeix al servidor '{{serverName}}'. Eines disponibles: {{availableTools}}",
"serverNotFound": "El servidor MCP '{{serverName}}' no està configurat. Servidors disponibles: {{availableServers}}",
"toolDisabled": "L'eina '{{toolName}}' del servidor '{{serverName}}' està desactivada. Eines activades disponibles: {{availableTools}}"
},
"info": {
"server_restarting": "Reiniciant el servidor MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo hat versucht, {{toolName}} mit einem ungültigen JSON-Argument zu verwenden. Wiederhole...",
"refresh_after_disable": "Fehler beim Aktualisieren der MCP-Verbindungen nach dem Deaktivieren",
"refresh_after_enable": "Fehler beim Aktualisieren der MCP-Verbindungen nach dem Aktivieren",
"disconnect_servers_partial": "Fehler beim Trennen von {{count}} MCP-Server(n). Überprüfe die Ausgabe für Details."
"disconnect_servers_partial": "Fehler beim Trennen von {{count}} MCP-Server(n). Überprüfe die Ausgabe für Details.",
"toolNotFound": "Tool '{{toolName}}' existiert nicht auf Server '{{serverName}}'. Verfügbare Tools: {{availableTools}}",
"serverNotFound": "MCP-Server '{{serverName}}' ist nicht konfiguriert. Verfügbare Server: {{availableServers}}",
"toolDisabled": "Tool '{{toolName}}' auf Server '{{serverName}}' ist deaktiviert. Verfügbare aktivierte Tools: {{availableTools}}"
},
"info": {
"server_restarting": "MCP-Server {{serverName}} wird neu gestartet...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo tried to use {{toolName}} with an invalid JSON argument. Retrying...",
"refresh_after_disable": "Failed to refresh MCP connections after disabling",
"refresh_after_enable": "Failed to refresh MCP connections after enabling",
"disconnect_servers_partial": "Failed to disconnect {{count}} MCP server(s). Check the output for details."
"disconnect_servers_partial": "Failed to disconnect {{count}} MCP server(s). Check the output for details.",
"toolNotFound": "Tool '{{toolName}}' does not exist on server '{{serverName}}'. Available tools: {{availableTools}}",
"serverNotFound": "MCP server '{{serverName}}' is not configured. Available servers: {{availableServers}}",
"toolDisabled": "Tool '{{toolName}}' on server '{{serverName}}' is disabled. Available enabled tools: {{availableTools}}"
},
"info": {
"server_restarting": "Restarting {{serverName}} MCP server...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo intentó usar {{toolName}} con un argumento JSON no válido. Reintentando...",
"refresh_after_disable": "Error al actualizar las conexiones MCP después de desactivar",
"refresh_after_enable": "Error al actualizar las conexiones MCP después de activar",
"disconnect_servers_partial": "Error al desconectar {{count}} servidor(es) MCP. Revisa la salida para más detalles."
"disconnect_servers_partial": "Error al desconectar {{count}} servidor(es) MCP. Revisa la salida para más detalles.",
"toolNotFound": "La herramienta '{{toolName}}' no existe en el servidor '{{serverName}}'. Herramientas disponibles: {{availableTools}}",
"serverNotFound": "El servidor MCP '{{serverName}}' no está configurado. Servidores disponibles: {{availableServers}}",
"toolDisabled": "La herramienta '{{toolName}}' del servidor '{{serverName}}' está desactivada. Herramientas activadas disponibles: {{availableTools}}"
},
"info": {
"server_restarting": "Reiniciando el servidor MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo a essayé d'utiliser {{toolName}} avec un argument JSON invalide. Nouvelle tentative...",
"refresh_after_disable": "Échec du rafraîchissement des connexions MCP après désactivation",
"refresh_after_enable": "Échec du rafraîchissement des connexions MCP après activation",
"disconnect_servers_partial": "Échec de la déconnexion de {{count}} serveur(s) MCP. Vérifiez la sortie pour plus de détails."
"disconnect_servers_partial": "Échec de la déconnexion de {{count}} serveur(s) MCP. Vérifiez la sortie pour plus de détails.",
"toolNotFound": "L'outil '{{toolName}}' n'existe pas sur le serveur '{{serverName}}'. Outils disponibles : {{availableTools}}",
"serverNotFound": "Le serveur MCP '{{serverName}}' n'est pas configuré. Serveurs disponibles : {{availableServers}}",
"toolDisabled": "L'outil '{{toolName}}' sur le serveur '{{serverName}}' est désactivé. Outils activés disponibles : {{availableTools}}"
},
"info": {
"server_restarting": "Redémarrage du serveur MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo ने {{toolName}} को अमान्य JSON आर्गुमेंट के साथ उपयोग करने की कोशिश की। फिर से कोशिश कर रहा है...",
"refresh_after_disable": "अक्षम करने के बाद MCP कनेक्शन रीफ्रेश करने में विफल",
"refresh_after_enable": "सक्षम करने के बाद MCP कनेक्शन रीफ्रेश करने में विफल",
"disconnect_servers_partial": "{{count}} MCP सर्वर डिस्कनेक्ट करने में विफल। विवरण के लिए आउटपुट देखें।"
"disconnect_servers_partial": "{{count}} MCP सर्वर डिस्कनेक्ट करने में विफल। विवरण के लिए आउटपुट देखें।",
"toolNotFound": "टूल '{{toolName}}' सर्वर '{{serverName}}' पर मौजूद नहीं है। उपलब्ध टूल: {{availableTools}}",
"serverNotFound": "MCP सर्वर '{{serverName}}' कॉन्फ़िगर नहीं है। उपलब्ध सर्वर: {{availableServers}}",
"toolDisabled": "सर्वर '{{serverName}}' पर टूल '{{toolName}}' अक्षम है। उपलब्ध सक्षम टूल: {{availableTools}}"
},
"info": {
"server_restarting": "{{serverName}} MCP सर्वर पुनः प्रारंभ हो रहा है...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo mencoba menggunakan {{toolName}} dengan argumen JSON yang tidak valid. Mencoba lagi...",
"refresh_after_disable": "Gagal me-refresh koneksi MCP setelah menonaktifkan",
"refresh_after_enable": "Gagal me-refresh koneksi MCP setelah mengaktifkan",
"disconnect_servers_partial": "Gagal memutus koneksi {{count}} server MCP. Periksa output untuk detailnya."
"disconnect_servers_partial": "Gagal memutus koneksi {{count}} server MCP. Periksa output untuk detailnya.",
"toolNotFound": "Tool '{{toolName}}' tidak ada di server '{{serverName}}'. Tool yang tersedia: {{availableTools}}",
"serverNotFound": "Server MCP '{{serverName}}' tidak dikonfigurasi. Server yang tersedia: {{availableServers}}",
"toolDisabled": "Tool '{{toolName}}' di server '{{serverName}}' dinonaktifkan. Tool aktif yang tersedia: {{availableTools}}"
},
"info": {
"server_restarting": "Merestart server MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo ha tentato di usare {{toolName}} con un argomento JSON non valido. Riprovo...",
"refresh_after_disable": "Impossibile aggiornare le connessioni MCP dopo la disattivazione",
"refresh_after_enable": "Impossibile aggiornare le connessioni MCP dopo l'attivazione",
"disconnect_servers_partial": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli."
"disconnect_servers_partial": "Impossibile disconnettere {{count}} server MCP. Controlla l'output per i dettagli.",
"toolNotFound": "Lo strumento '{{toolName}}' non esiste sul server '{{serverName}}'. Strumenti disponibili: {{availableTools}}",
"serverNotFound": "Il server MCP '{{serverName}}' non è configurato. Server disponibili: {{availableServers}}",
"toolDisabled": "Lo strumento '{{toolName}}' sul server '{{serverName}}' è disabilitato. Strumenti abilitati disponibili: {{availableTools}}"
},
"info": {
"server_restarting": "Riavvio del server MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Rooが無効なJSON引数で{{toolName}}を使用しようとしました。再試行中...",
"refresh_after_disable": "無効化後にMCP接続の更新に失敗しました",
"refresh_after_enable": "有効化後にMCP接続の更新に失敗しました",
"disconnect_servers_partial": "{{count}}個のMCPサーバーの切断に失敗しました。詳細は出力を確認してください。"
"disconnect_servers_partial": "{{count}}個のMCPサーバーの切断に失敗しました。詳細は出力を確認してください。",
"toolNotFound": "ツール '{{toolName}}' はサーバー '{{serverName}}' に存在しません。利用可能なツール: {{availableTools}}",
"serverNotFound": "MCPサーバー '{{serverName}}' は設定されていません。利用可能なサーバー: {{availableServers}}",
"toolDisabled": "サーバー '{{serverName}}' のツール '{{toolName}}' は無効です。利用可能な有効なツール: {{availableTools}}"
},
"info": {
"server_restarting": "MCPサーバー{{serverName}}を再起動中...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo가 유효하지 않은 JSON 인자로 {{toolName}}을(를) 사용하려고 했습니다. 다시 시도 중...",
"refresh_after_disable": "비활성화 후 MCP 연결 새로 고침 실패",
"refresh_after_enable": "활성화 후 MCP 연결 새로 고침 실패",
"disconnect_servers_partial": "{{count}}개의 MCP 서버 연결 해제 실패. 자세한 내용은 출력을 확인하세요."
"disconnect_servers_partial": "{{count}}개의 MCP 서버 연결 해제 실패. 자세한 내용은 출력을 확인하세요.",
"toolNotFound": "도구 '{{toolName}}'이(가) 서버 '{{serverName}}'에 존재하지 않습니다. 사용 가능한 도구: {{availableTools}}",
"serverNotFound": "MCP 서버 '{{serverName}}'이(가) 구성되지 않았습니다. 사용 가능한 서버: {{availableServers}}",
"toolDisabled": "서버 '{{serverName}}'의 도구 '{{toolName}}'이(가) 비활성화되었습니다. 사용 가능한 활성화된 도구: {{availableTools}}"
},
"info": {
"server_restarting": "{{serverName}} MCP 서버를 재시작하는 중...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo probeerde {{toolName}} te gebruiken met een ongeldig JSON-argument. Opnieuw proberen...",
"refresh_after_disable": "Vernieuwen van MCP-verbindingen na uitschakelen mislukt",
"refresh_after_enable": "Vernieuwen van MCP-verbindingen na inschakelen mislukt",
"disconnect_servers_partial": "Loskoppelen van {{count}} MCP-server(s) mislukt. Controleer de uitvoer voor details."
"disconnect_servers_partial": "Loskoppelen van {{count}} MCP-server(s) mislukt. Controleer de uitvoer voor details.",
"toolNotFound": "Tool '{{toolName}}' bestaat niet op server '{{serverName}}'. Beschikbare tools: {{availableTools}}",
"serverNotFound": "MCP-server '{{serverName}}' is niet geconfigureerd. Beschikbare servers: {{availableServers}}",
"toolDisabled": "Tool '{{toolName}}' op server '{{serverName}}' is uitgeschakeld. Beschikbare ingeschakelde tools: {{availableTools}}"
},
"info": {
"server_restarting": "{{serverName}} MCP-server wordt opnieuw gestart...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo próbował użyć {{toolName}} z nieprawidłowym argumentem JSON. Ponawianie...",
"refresh_after_disable": "Nie udało się odświeżyć połączeń MCP po wyłączeniu",
"refresh_after_enable": "Nie udało się odświeżyć połączeń MCP po włączeniu",
"disconnect_servers_partial": "Nie udało się odłączyć {{count}} serwera(ów) MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły."
"disconnect_servers_partial": "Nie udało się odłączyć {{count}} serwera(ów) MCP. Sprawdź dane wyjściowe, aby uzyskać szczegóły.",
"toolNotFound": "Narzędzie '{{toolName}}' nie istnieje na serwerze '{{serverName}}'. Dostępne narzędzia: {{availableTools}}",
"serverNotFound": "Serwer MCP '{{serverName}}' nie jest skonfigurowany. Dostępne serwery: {{availableServers}}",
"toolDisabled": "Narzędzie '{{toolName}}' na serwerze '{{serverName}}' jest wyłączone. Dostępne włączone narzędzia: {{availableTools}}"
},
"info": {
"server_restarting": "Ponowne uruchamianie serwera MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo tentou usar {{toolName}} com um argumento JSON inválido. Tentando novamente...",
"refresh_after_disable": "Falha ao atualizar as conexões MCP após desativar",
"refresh_after_enable": "Falha ao atualizar as conexões MCP após ativar",
"disconnect_servers_partial": "Falha ao desconectar {{count}} servidor(es) MCP. Verifique a saída para detalhes."
"disconnect_servers_partial": "Falha ao desconectar {{count}} servidor(es) MCP. Verifique a saída para detalhes.",
"toolNotFound": "A ferramenta '{{toolName}}' não existe no servidor '{{serverName}}'. Ferramentas disponíveis: {{availableTools}}",
"serverNotFound": "O servidor MCP '{{serverName}}' não está configurado. Servidores disponíveis: {{availableServers}}",
"toolDisabled": "A ferramenta '{{toolName}}' no servidor '{{serverName}}' está desabilitada. Ferramentas habilitadas disponíveis: {{availableTools}}"
},
"info": {
"server_restarting": "Reiniciando o servidor MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo попытался использовать {{toolName}} с недопустимым JSON-аргументом. Повторная попытка...",
"refresh_after_disable": "Не удалось обновить соединения MCP после отключения",
"refresh_after_enable": "Не удалось обновить соединения MCP после включения",
"disconnect_servers_partial": "Не удалось отключить {{count}} MCP сервер(ов). Проверьте вывод для получения подробностей."
"disconnect_servers_partial": "Не удалось отключить {{count}} MCP сервер(ов). Проверьте вывод для получения подробностей.",
"toolNotFound": "Инструмент '{{toolName}}' не существует на сервере '{{serverName}}'. Доступные инструменты: {{availableTools}}",
"serverNotFound": "MCP сервер '{{serverName}}' не настроен. Доступные серверы: {{availableServers}}",
"toolDisabled": "Инструмент '{{toolName}}' на сервере '{{serverName}}' отключен. Доступные включенные инструменты: {{availableTools}}"
},
"info": {
"server_restarting": "Перезапуск сервера MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo, {{toolName}} aracını geçersiz bir JSON argümanıyla kullanmaya çalıştı. Tekrar deneniyor...",
"refresh_after_disable": "Devre dışı bıraktıktan sonra MCP bağlantıları yenilenemedi",
"refresh_after_enable": "Etkinleştirdikten sonra MCP bağlantıları yenilenemedi",
"disconnect_servers_partial": "{{count}} MCP sunucusu bağlantısı kesilemedi. Ayrıntılar için çıktıyı kontrol edin."
"disconnect_servers_partial": "{{count}} MCP sunucusu bağlantısı kesilemedi. Ayrıntılar için çıktıyı kontrol edin.",
"toolNotFound": "Araç '{{toolName}}' sunucu '{{serverName}}' üzerinde mevcut değil. Mevcut araçlar: {{availableTools}}",
"serverNotFound": "MCP sunucusu '{{serverName}}' yapılandırılmamış. Mevcut sunucular: {{availableServers}}",
"toolDisabled": "Sunucu '{{serverName}}' üzerindeki araç '{{toolName}}' devre dışı. Mevcut etkin araçlar: {{availableTools}}"
},
"info": {
"server_restarting": "{{serverName}} MCP sunucusu yeniden başlatılıyor...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo đã cố gắng sử dụng {{toolName}} với tham số JSON không hợp lệ. Đang thử lại...",
"refresh_after_disable": "Không thể làm mới kết nối MCP sau khi vô hiệu hóa",
"refresh_after_enable": "Không thể làm mới kết nối MCP sau khi kích hoạt",
"disconnect_servers_partial": "Không thể ngắt kết nối {{count}} máy chủ MCP. Kiểm tra đầu ra để biết chi tiết."
"disconnect_servers_partial": "Không thể ngắt kết nối {{count}} máy chủ MCP. Kiểm tra đầu ra để biết chi tiết.",
"toolNotFound": "Công cụ '{{toolName}}' không tồn tại trên máy chủ '{{serverName}}'. Công cụ có sẵn: {{availableTools}}",
"serverNotFound": "Máy chủ MCP '{{serverName}}' chưa được cấu hình. Máy chủ có sẵn: {{availableServers}}",
"toolDisabled": "Công cụ '{{toolName}}' trên máy chủ '{{serverName}}' đã bị vô hiệu hóa. Công cụ đã kích hoạt có sẵn: {{availableTools}}"
},
"info": {
"server_restarting": "Đang khởi động lại máy chủ MCP {{serverName}}...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo 尝试使用无效的 JSON 参数调用 {{toolName}}。正在重试...",
"refresh_after_disable": "禁用后刷新 MCP 连接失败",
"refresh_after_enable": "启用后刷新 MCP 连接失败",
"disconnect_servers_partial": "断开 {{count}} 个 MCP 服务器失败。请查看输出了解详情。"
"disconnect_servers_partial": "断开 {{count}} 个 MCP 服务器失败。请查看输出了解详情。",
"toolNotFound": "工具 '{{toolName}}' 在服务器 '{{serverName}}' 上不存在。可用工具: {{availableTools}}",
"serverNotFound": "MCP 服务器 '{{serverName}}' 未配置。可用服务器: {{availableServers}}",
"toolDisabled": "服务器 '{{serverName}}' 上的工具 '{{toolName}}' 已禁用。可用的已启用工具: {{availableTools}}"
},
"info": {
"server_restarting": "正在重启{{serverName}}MCP服务器...",

View file

@ -8,7 +8,10 @@
"invalidJsonArgument": "Roo 嘗試使用無效的 JSON 參數呼叫 {{toolName}}。正在重試...",
"refresh_after_disable": "停用後重新整理 MCP 連線失敗",
"refresh_after_enable": "啟用後重新整理 MCP 連線失敗",
"disconnect_servers_partial": "斷開 {{count}} 個 MCP 伺服器失敗。請查看輸出了解詳情。"
"disconnect_servers_partial": "斷開 {{count}} 個 MCP 伺服器失敗。請查看輸出了解詳情。",
"toolNotFound": "工具 '{{toolName}}' 在伺服器 '{{serverName}}' 上不存在。可用工具: {{availableTools}}",
"serverNotFound": "MCP 伺服器 '{{serverName}}' 未設定。可用伺服器: {{availableServers}}",
"toolDisabled": "伺服器 '{{serverName}}' 上的工具 '{{toolName}}' 已停用。可用的已啟用工具: {{availableTools}}"
},
"info": {
"server_restarting": "正在重啟{{serverName}}MCP 伺服器...",