feat: add mcp Execute Tool

This commit is contained in:
xu-ya 2025-11-18 15:07:37 +08:00
parent 8d227a5164
commit 304ab82e86
13 changed files with 307 additions and 78 deletions

View File

@ -48,7 +48,8 @@ export default defineConfig([
'@eslint-react/no-unstable-context-value': 'off',
'@eslint-react/hooks-extra/prefer-use-state-lazy-initialization': 'off',
'@eslint-react/hooks-extra/no-unnecessary-use-prefix': 'off',
'@eslint-react/no-children-to-array': 'off'
'@eslint-react/no-children-to-array': 'off',
'@eslint-react/dom/no-unsafe-iframe-sandbox': 'off'
}
},
{

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Available Tools",
"enable": "Enable Tool",
"execute": {
"button": "Execute",
"copied": "Copied to clipboard",
"copy": "Copy",
"copyFailed": "Failed to copy",
"error": {
"invalidJson": "Invalid JSON format: {{error}}",
"noToolOrServer": "Tool or server not found"
},
"execute": "Execute",
"label": "Execute",
"params": "Parameters (JSON)",
"paramsPlaceholder": "Enter JSON parameters...",
"result": {
"error": "Error Result",
"success": "Result",
"text": "Text"
},
"table": {
"name": "Name",
"value": "Value"
},
"title": "Execute Tool: {{name}}",
"tooltip": "Execute tool with custom parameters",
"view": {
"formatted": "Formatted",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Allowed Values"
@ -3985,36 +4014,7 @@
},
"loadError": "Get tools Error",
"noToolsAvailable": "No tools available",
"run": "Run",
"execute": {
"label": "Execute",
"button": "Execute",
"tooltip": "Execute tool with custom parameters",
"title": "Execute Tool: {{name}}",
"params": "Parameters (JSON)",
"paramsPlaceholder": "Enter JSON parameters...",
"execute": "Execute",
"copied": "Copied to clipboard",
"copyFailed": "Failed to copy",
"copy": "Copy",
"result": {
"success": "Result",
"error": "Error Result",
"text": "Text"
},
"view": {
"json": "JSON",
"formatted": "Formatted"
},
"table": {
"name": "Name",
"value": "Value"
},
"error": {
"noToolOrServer": "Tool or server not found",
"invalidJson": "Invalid JSON format: {{error}}"
}
}
"run": "Run"
},
"type": "Type",
"types": {

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "可用工具",
"enable": "启用工具",
"execute": {
"button": "执行",
"copied": "已复制到剪贴板",
"copy": "复制",
"copyFailed": "复制失败",
"error": {
"invalidJson": "无效的 JSON 格式: {{error}}",
"noToolOrServer": "未找到工具或服务器"
},
"execute": "执行",
"label": "执行",
"params": "参数 (JSON)",
"paramsPlaceholder": "输入 JSON 参数...",
"result": {
"error": "错误结果",
"success": "结果",
"text": "文本"
},
"table": {
"name": "名称",
"value": "值"
},
"title": "执行工具: {{name}}",
"tooltip": "使用自定义参数执行工具",
"view": {
"formatted": "美化",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "允许的值"
@ -3985,36 +4014,7 @@
},
"loadError": "获取工具失败",
"noToolsAvailable": "无可用工具",
"run": "运行",
"execute": {
"label": "执行",
"button": "执行",
"tooltip": "使用自定义参数执行工具",
"title": "执行工具: {{name}}",
"params": "参数 (JSON)",
"paramsPlaceholder": "输入 JSON 参数...",
"execute": "执行",
"copied": "已复制到剪贴板",
"copyFailed": "复制失败",
"copy": "复制",
"result": {
"success": "结果",
"error": "错误结果",
"text": "文本"
},
"view": {
"json": "JSON",
"formatted": "美化"
},
"table": {
"name": "名称",
"value": "值"
},
"error": {
"noToolOrServer": "未找到工具或服务器",
"invalidJson": "无效的 JSON 格式: {{error}}"
}
}
"run": "运行"
},
"type": "类型",
"types": {

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "可用工具",
"enable": "啟用工具",
"execute": {
"button": "執行",
"copied": "已複製到剪貼板",
"copy": "複製",
"copyFailed": "複製失敗",
"error": {
"invalidJson": "無效的 JSON 格式: {{error}}",
"noToolOrServer": "未找到工具或伺服器"
},
"execute": "執行",
"label": "執行",
"params": "參數 (JSON)",
"paramsPlaceholder": "輸入 JSON 參數...",
"result": {
"error": "錯誤結果",
"success": "結果",
"text": "文字"
},
"table": {
"name": "名稱",
"value": "值"
},
"title": "執行工具: {{name}}",
"tooltip": "使用自訂參數執行工具",
"view": {
"formatted": "美化",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "允許的值"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Verfügbare Tools",
"enable": "Tool aktivieren",
"execute": {
"button": "Ausführen",
"copied": "In Zwischenablage kopiert",
"copy": "Kopieren",
"copyFailed": "Kopieren fehlgeschlagen",
"error": {
"invalidJson": "Ungültiges JSON-Format: {{error}}",
"noToolOrServer": "Tool oder Server nicht gefunden"
},
"execute": "Ausführen",
"label": "Ausführen",
"params": "Parameter (JSON)",
"paramsPlaceholder": "JSON-Parameter eingeben...",
"result": {
"error": "Fehlerergebnis",
"success": "Ergebnis",
"text": "Text"
},
"table": {
"name": "Name",
"value": "Wert"
},
"title": "Tool ausführen: {{name}}",
"tooltip": "Tool mit benutzerdefinierten Parametern ausführen",
"view": {
"formatted": "Formatiert",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Erlaubte Werte"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Διαθέσιμα Εργαλεία",
"enable": "Ενεργοποίηση εργαλείου",
"execute": {
"button": "Εκτέλεση",
"copied": "Αντιγράφηκε στο πρόχειρο",
"copy": "Αντιγραφή",
"copyFailed": "Αποτυχία αντιγραφής",
"error": {
"invalidJson": "Μη έγκυρη μορφή JSON: {{error}}",
"noToolOrServer": "Εργαλείο ή διακομιστής δεν βρέθηκε"
},
"execute": "Εκτέλεση",
"label": "Εκτέλεση",
"params": "Παράμετροι (JSON)",
"paramsPlaceholder": "Εισαγάγετε παραμέτρους JSON...",
"result": {
"error": "Αποτέλεσμα σφάλματος",
"success": "Αποτέλεσμα",
"text": "Κείμενο"
},
"table": {
"name": "Όνομα",
"value": "Τιμή"
},
"title": "Εκτέλεση εργαλείου: {{name}}",
"tooltip": "Εκτέλεση εργαλείου με προσαρμοσμένες παραμέτρους",
"view": {
"formatted": "Μορφοποιημένο",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Επιτρεπόμενες τιμές"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Herramientas disponibles",
"enable": "Habilitar herramienta",
"execute": {
"button": "Ejecutar",
"copied": "Copiado al portapapeles",
"copy": "Copiar",
"copyFailed": "Error al copiar",
"error": {
"invalidJson": "Formato JSON inválido: {{error}}",
"noToolOrServer": "Herramienta o servidor no encontrado"
},
"execute": "Ejecutar",
"label": "Ejecutar",
"params": "Parámetros (JSON)",
"paramsPlaceholder": "Ingrese parámetros JSON...",
"result": {
"error": "Resultado de error",
"success": "Resultado",
"text": "Texto"
},
"table": {
"name": "Nombre",
"value": "Valor"
},
"title": "Ejecutar herramienta: {{name}}",
"tooltip": "Ejecutar herramienta con parámetros personalizados",
"view": {
"formatted": "Formateado",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Valores permitidos"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Outils disponibles",
"enable": "Activer l'outil",
"execute": {
"button": "Exécuter",
"copied": "Copié dans le presse-papiers",
"copy": "Copier",
"copyFailed": "Échec de la copie",
"error": {
"invalidJson": "Format JSON invalide: {{error}}",
"noToolOrServer": "Outil ou serveur introuvable"
},
"execute": "Exécuter",
"label": "Exécuter",
"params": "Paramètres (JSON)",
"paramsPlaceholder": "Entrez les paramètres JSON...",
"result": {
"error": "Résultat d'erreur",
"success": "Résultat",
"text": "Texte"
},
"table": {
"name": "Nom",
"value": "Valeur"
},
"title": "Exécuter l'outil: {{name}}",
"tooltip": "Exécuter l'outil avec des paramètres personnalisés",
"view": {
"formatted": "Formaté",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Valeurs autorisées"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "利用可能なツール",
"enable": "ツールを有効にする",
"execute": {
"button": "実行",
"copied": "クリップボードにコピーしました",
"copy": "コピー",
"copyFailed": "コピーに失敗しました",
"error": {
"invalidJson": "無効なJSON形式: {{error}}",
"noToolOrServer": "ツールまたはサーバーが見つかりません"
},
"execute": "実行",
"label": "実行",
"params": "パラメータ (JSON)",
"paramsPlaceholder": "JSONパラメータを入力...",
"result": {
"error": "エラー結果",
"success": "結果",
"text": "テキスト"
},
"table": {
"name": "名前",
"value": "値"
},
"title": "ツールを実行: {{name}}",
"tooltip": "カスタムパラメータでツールを実行",
"view": {
"formatted": "フォーマット済み",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "許可された値"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Ferramentas Disponíveis",
"enable": "Habilitar Ferramenta",
"execute": {
"button": "Executar",
"copied": "Copiado para a área de transferência",
"copy": "Copiar",
"copyFailed": "Falha ao copiar",
"error": {
"invalidJson": "Formato JSON inválido: {{error}}",
"noToolOrServer": "Ferramenta ou servidor não encontrado"
},
"execute": "Executar",
"label": "Executar",
"params": "Parâmetros (JSON)",
"paramsPlaceholder": "Digite os parâmetros JSON...",
"result": {
"error": "Resultado de erro",
"success": "Resultado",
"text": "Texto"
},
"table": {
"name": "Nome",
"value": "Valor"
},
"title": "Executar ferramenta: {{name}}",
"tooltip": "Executar ferramenta com parâmetros personalizados",
"view": {
"formatted": "Formatado",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Valores permitidos"

View File

@ -3977,6 +3977,35 @@
},
"availableTools": "Доступные инструменты",
"enable": "Включить инструмент",
"execute": {
"button": "Выполнить",
"copied": "Скопировано в буфер обмена",
"copy": "Копировать",
"copyFailed": "Не удалось скопировать",
"error": {
"invalidJson": "Неверный формат JSON: {{error}}",
"noToolOrServer": "Инструмент или сервер не найден"
},
"execute": "Выполнить",
"label": "Выполнить",
"params": "Параметры (JSON)",
"paramsPlaceholder": "Введите параметры JSON...",
"result": {
"error": "Результат ошибки",
"success": "Результат",
"text": "Текст"
},
"table": {
"name": "Имя",
"value": "Значение"
},
"title": "Выполнить инструмент: {{name}}",
"tooltip": "Выполнить инструмент с пользовательскими параметрами",
"view": {
"formatted": "Форматированный",
"json": "JSON"
}
},
"inputSchema": {
"enum": {
"allowedValues": "Допустимые значения"

View File

@ -1,18 +1,18 @@
import 'katex/dist/katex.min.css'
import type { MCPServer, MCPTool } from '@renderer/types'
import { loggerService } from '@logger'
import { Button, Flex, Input, Modal, Space, Table, Typography, message } from 'antd'
import type { MCPServer, MCPTool } from '@renderer/types'
import { Button, Flex, Input, message, Modal, Space, Table, Typography } from 'antd'
import type { ColumnsType } from 'antd/es/table'
import { Copy, Play, Sparkles, Code as CodeIcon } from 'lucide-react'
import { useState, useMemo, useEffect } from 'react'
import { Code as CodeIcon, Copy, Play, Sparkles } from 'lucide-react'
import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
import rehypeRaw from 'rehype-raw'
import remarkCjkFriendly from 'remark-cjk-friendly'
import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
const logger = loggerService.withContext('ExecuteToolModal')
@ -47,7 +47,10 @@ const ExecuteToolModal: React.FC<ExecuteToolModalProps> = ({ open, tool, server,
// 为每个属性生成默认值或示例
Object.keys(properties).forEach((key) => {
const prop = properties[key]
const prop = properties[key] as {
type?: string
default?: any
}
if (prop.type === 'string') {
params[key] = prop.default || ''
} else if (prop.type === 'number') {
@ -79,12 +82,7 @@ const ExecuteToolModal: React.FC<ExecuteToolModalProps> = ({ open, tool, server,
// 检测 HTML 特征(优先检测,因为 HTML 可能包含其他格式)
// 检查是否包含完整的 HTML 文档结构或大量 HTML 标签
const htmlDocumentPatterns = [
/<!DOCTYPE\s+html/i,
/<html[\s>]/i,
/<head[\s>]/i,
/<body[\s>]/i
]
const htmlDocumentPatterns = [/<!DOCTYPE\s+html/i, /<html[\s>]/i, /<head[\s>]/i, /<body[\s>]/i]
const hasHtmlDocument = htmlDocumentPatterns.some((pattern) => pattern.test(text))
@ -313,9 +311,7 @@ const ExecuteToolModal: React.FC<ExecuteToolModalProps> = ({ open, tool, server,
<Space direction="vertical" size="large" style={{ width: '100%' }}>
{/* 参数输入 */}
<div>
<Typography.Title level={5}>
{t('settings.mcp.tools.execute.params', 'Parameters (JSON)')}
</Typography.Title>
<Typography.Title level={5}>{t('settings.mcp.tools.execute.params', 'Parameters (JSON)')}</Typography.Title>
<Input.TextArea
value={paramsJson}
onChange={(e) => setParamsJson(e.target.value)}
@ -435,4 +431,3 @@ const ExecuteToolModal: React.FC<ExecuteToolModalProps> = ({ open, tool, server,
}
export default ExecuteToolModal

View File

@ -5,6 +5,7 @@ import type { ColumnsType } from 'antd/es/table'
import { Hammer, Info, Play, Zap } from 'lucide-react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import ExecuteToolModal from './ExecuteToolModal'
interface MCPToolsSectionProps {