fix: better mcp tool match and feedback (#8825)

* feat(mcp): 添加多工具匹配时的警告提示

当匹配到多个MCP工具或未匹配到所需工具时,显示相应的警告信息。同时在i18n中添加对应的翻译字段。

* feat(i18n): 添加MCP工具警告信息和模型列表刷新功能的多语言支持

* fix(mcp): 修复工具调用解析错误并优化日志消息

添加对工具调用解析错误的处理,当解析失败时显示错误信息
统一工具调用相关的日志消息格式,使用字符串插值替代拼接

* feat(i18n): 为MCP工具添加解析错误的多语言支持
This commit is contained in:
Phantom 2025-08-04 23:08:37 +08:00 committed by GitHub
parent d8d0ab5fc4
commit 636a430eb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 126 additions and 11 deletions

View File

@ -383,6 +383,15 @@
"settings": "Web Search Settings"
}
},
"mcp": {
"error": {
"parse_tool_call": "Unable to convert to a valid tool call format: {{toolCall}}"
},
"warning": {
"multiple_tools": "Multiple matching MCP tools exist, {{tool}} has been selected",
"no_tool": "No matching MCP tool found for {{tool}}"
}
},
"message": {
"new": {
"branch": {

View File

@ -383,6 +383,15 @@
"settings": "ウェブ検索設定"
}
},
"mcp": {
"error": {
"parse_tool_call": "有効なツール呼び出し形式に変換できません:{{toolCall}}"
},
"warning": {
"multiple_tools": "複数の一致するMCPツールが存在するため、{{tool}} が選択されました",
"no_tool": "必要なMCPツール {{tool}} が見つかりません"
}
},
"message": {
"new": {
"branch": {

View File

@ -383,6 +383,15 @@
"settings": "Настройки веб-поиска"
}
},
"mcp": {
"error": {
"parse_tool_call": "Не удалось преобразовать в действительный формат вызова инструмента: {{toolCall}}"
},
"warning": {
"multiple_tools": "Существует несколько совпадающих инструментов MCP, выбран {{tool}}",
"no_tool": "Не удалось сопоставить требуемый инструмент MCP {{tool}}"
}
},
"message": {
"new": {
"branch": {

View File

@ -383,6 +383,15 @@
"settings": "网络搜索设置"
}
},
"mcp": {
"error": {
"parse_tool_call": "无法转换为有效的工具调用格式:{{toolCall}}"
},
"warning": {
"multiple_tools": "存在多个匹配的MCP工具已选择 {{tool}}",
"no_tool": "未匹配到所需的MCP工具 {{tool}}"
}
},
"message": {
"new": {
"branch": {

View File

@ -383,6 +383,15 @@
"settings": "網路搜尋設定"
}
},
"mcp": {
"error": {
"parse_tool_call": "無法轉換為有效的工具呼叫格式:{{toolCall}}"
},
"warning": {
"multiple_tools": "存在多個匹配的MCP工具已選擇 {{tool}}",
"no_tool": "未匹配到所需的MCP工具 {{tool}}"
}
},
"message": {
"new": {
"branch": {

View File

@ -383,6 +383,15 @@
"settings": "Ρυθμίσεις αναζήτησης στο διαδίκτυο"
}
},
"mcp": {
"error": {
"parse_tool_call": "Δεν είναι δυνατή η μετατροπή σε έγκυρη μορφή κλήσης εργαλείου: {{toolCall}}"
},
"warning": {
"multiple_tools": "Υπάρχουν πολλαπλά εργαλεία MCP που ταιριάζουν, επιλέχθηκε το {{tool}}",
"no_tool": "Δεν βρέθηκε το απαιτούμενο εργαλείο MCP {{tool}}"
}
},
"message": {
"new": {
"branch": {
@ -2991,6 +3000,7 @@
"label": "Προσθήκη μοντέλων από τη λίστα"
},
"add_whole_group": "Προσθήκη ολόκληρης ομάδας",
"refetch_list": "Επαναλήψτε τη λήψη της λίστας μοντέλων",
"remove_listed": "Αφαίρεση μοντέλων από τη λίστα",
"remove_model": "Αφαίρεση Μοντέλου",
"remove_whole_group": "Αφαίρεση ολόκληρης ομάδας"

View File

@ -383,6 +383,15 @@
"settings": "Configuración de búsqueda en red"
}
},
"mcp": {
"error": {
"parse_tool_call": "No se puede convertir al formato de llamada de herramienta válido: {{toolCall}}"
},
"warning": {
"multiple_tools": "Existen múltiples herramientas MCP coincidentes, se ha seleccionado {{tool}}",
"no_tool": "No se encontró la herramienta MCP requerida {{tool}}"
}
},
"message": {
"new": {
"branch": {
@ -2991,6 +3000,7 @@
"label": "Agregar modelo en la lista"
},
"add_whole_group": "Agregar todo el grupo",
"refetch_list": "Volver a obtener la lista de modelos",
"remove_listed": "Eliminar modelo de la lista",
"remove_model": "Eliminar modelo",
"remove_whole_group": "Eliminar todo el grupo"

View File

@ -383,6 +383,15 @@
"settings": "Paramètres de recherche en ligne"
}
},
"mcp": {
"error": {
"parse_tool_call": "Impossible de convertir au format d'appel d'outil valide : {{toolCall}}"
},
"warning": {
"multiple_tools": "Il existe plusieurs outils MCP correspondants, {{tool}} a été sélectionné",
"no_tool": "Aucun outil MCP requis {{tool}} n'a été trouvé"
}
},
"message": {
"new": {
"branch": {
@ -2991,6 +3000,7 @@
"label": "Ajouter le modèle dans la liste"
},
"add_whole_group": "Ajouter tout le groupe",
"refetch_list": "Récupérer à nouveau la liste des modèles",
"remove_listed": "Supprimer un modèle de la liste",
"remove_model": "Supprimer le modèle",
"remove_whole_group": "Supprimer tout le groupe"

View File

@ -383,6 +383,15 @@
"settings": "Configurações de Pesquisa na Web"
}
},
"mcp": {
"error": {
"parse_tool_call": "Não é possível converter para um formato de chamada de ferramenta válido: {{toolCall}}"
},
"warning": {
"multiple_tools": "Existem várias ferramentas MCP correspondentes, a ferramenta {{tool}} foi selecionada",
"no_tool": "Nenhuma ferramenta MCP necessária correspondente encontrada {{tool}}"
}
},
"message": {
"new": {
"branch": {
@ -2991,6 +3000,7 @@
"label": "Adicionar modelo da lista"
},
"add_whole_group": "Adicionar todo o grupo",
"refetch_list": "Obter novamente a lista de modelos",
"remove_listed": "Remover modelo da lista",
"remove_model": "Remover Modelo",
"remove_whole_group": "Remover todo o grupo"

View File

@ -18,6 +18,7 @@ import {
import type { MCPToolCompleteChunk, MCPToolInProgressChunk, MCPToolPendingChunk } from '@renderer/types/chunk'
import { ChunkType } from '@renderer/types/chunk'
import { AwsBedrockSdkMessageParam, AwsBedrockSdkTool, AwsBedrockSdkToolCall } from '@renderer/types/sdk'
import { t } from 'i18next'
import { isArray, isObject, pull, transform } from 'lodash'
import { nanoid } from 'nanoid'
import OpenAI from 'openai'
@ -253,20 +254,33 @@ export function openAIToolsToMcpTool(
mcpTools: MCPTool[],
toolCall: OpenAI.Responses.ResponseFunctionToolCall | ChatCompletionMessageToolCall
): MCPTool | undefined {
const tool = mcpTools.find((mcpTool) => {
let toolName = ''
try {
if ('name' in toolCall) {
return mcpTool.id === toolCall.name || mcpTool.name === toolCall.name
toolName = toolCall.name
} else {
return mcpTool.id === toolCall.function.name || mcpTool.name === toolCall.function.name
toolName = toolCall.function.name
}
} catch (error) {
logger.error(`Error parsing tool call: ${toolCall}`, error as Error)
window.message.error(t('chat.mcp.error.parse_tool_call', { toolCall: toolCall }))
return undefined
}
const tools = mcpTools.filter((mcpTool) => {
return mcpTool.id === toolName || mcpTool.name === toolName
})
if (tools.length > 1) {
logger.warn(`Multiple MCP Tools found for tool call: ${toolName}`)
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
}
if (!tool) {
logger.warn('No MCP Tool found for tool call:', toolCall)
if (tools.length === 0) {
logger.warn(`No MCP Tool found for tool call: ${toolName}`)
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolName }))
return undefined
}
return tool
return tools[0]
}
export async function callBuiltInTool(toolResponse: MCPToolResponse): Promise<MCPCallToolResponse | undefined> {
@ -358,11 +372,17 @@ export function mcpToolsToAnthropicTools(mcpTools: MCPTool[]): Array<ToolUnion>
export function anthropicToolUseToMcpTool(mcpTools: MCPTool[] | undefined, toolUse: ToolUseBlock): MCPTool | undefined {
if (!mcpTools) return undefined
const tool = mcpTools.find((tool) => tool.id === toolUse.name)
if (!tool) {
const tools = mcpTools.filter((tool) => tool.id === toolUse.name)
if (tools.length === 0) {
logger.warn(`No MCP Tool found for tool call: ${toolUse.name}`)
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolUse.name }))
return undefined
}
return tool
if (tools.length > 1) {
logger.warn(`Multiple MCP Tools found for tool call: ${toolUse.name}`)
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
}
return tools[0]
}
/**
@ -424,9 +444,19 @@ export function geminiFunctionCallToMcpTool(
const toolName = toolCall.name || toolCall.id
if (!toolName) return undefined
const tool = mcpTools.find((tool) => tool.id.includes(toolName) || tool.name.includes(toolName))
const tools = mcpTools.filter((tool) => tool.id.includes(toolName) || tool.name.includes(toolName))
if (tools.length > 1) {
logger.warn(`Multiple MCP Tools found for tool call: ${toolName}`)
window.message.warning(t('chat.mcp.warning.multiple_tools', { tool: tools[0].name }))
}
return tool
if (tools.length === 0) {
logger.warn(`No MCP Tool found for tool call: ${toolName}`)
window.message.warning(t('chat.mcp.warning.no_tool', { tool: toolName }))
return undefined
}
return tools[0]
}
export function upsertMCPToolResponse(