feat: add disable MCP server functionality and update translations (#6398)

* feat: add disable MCP server functionality and update translations

* feat: update MCPToolsButton and WebSearchButton to use CircleX icon and change labels to 'close'

---------

Co-authored-by: kangfenmao <kangfenmao@qq.com>
This commit is contained in:
自由的世界人 2025-05-24 16:00:55 +08:00 committed by GitHub
parent 17be88373e
commit f27e66a399
7 changed files with 43 additions and 17 deletions

View File

@ -1305,6 +1305,8 @@
"stdio": "Standard Input/Output (stdio)",
"inMemory": "Memory",
"config_description": "Configure Model Context Protocol servers",
"disable": "Disable MCP Server",
"disable.description": "Do not enable MCP server functionality",
"deleteError": "Failed to delete server",
"deleteSuccess": "Server deleted successfully",
"dependenciesInstall": "Install Dependencies",

View File

@ -599,9 +599,8 @@
"delete.confirm.content": "選択した{{count}}件のメッセージを削除しますか?",
"delete.failed": "削除に失敗しました",
"delete.success": "削除が成功しました",
"error.chunk_overlap_too_large": "チャンクの重なりは、チャンクサイズを超えることはできません",
"empty_url": "画像をダウンロードできません。プロンプトに不適切なコンテンツや禁止用語が含まれている可能性があります",
"error.chunk_overlap_too_large": "チャンクのオーバーラップがチャンクサイズより大きくなることはできません",
"empty_url": "画像をダウンロードできません。プロンプトに不適切なコンテンツや禁止用語が含まれている可能性があります",
"error.dimension_too_large": "内容のサイズが大きすぎます",
"error.enter.api.host": "APIホストを入力してください",
"error.enter.api.key": "APIキーを入力してください",
@ -1302,6 +1301,8 @@
"stdio": "標準入力/出力 (stdio)",
"inMemory": "メモリ",
"config_description": "モデルコンテキストプロトコルサーバーの設定",
"disable": "MCPサーバーを無効にする",
"disable.description": "MCP機能を有効にしない",
"deleteError": "サーバーの削除に失敗しました",
"deleteSuccess": "サーバーが正常に削除されました",
"dependenciesInstall": "依存関係をインストール",

View File

@ -885,8 +885,7 @@
"number_images_tip": "Количество увеличенных результатов для генерации",
"seed_tip": "Контролирует случайный характер увеличения изображений для воспроизводимых результатов",
"magic_prompt_option_tip": "Улучшает увеличение изображений с помощью интеллектуального оптимизирования промптов"
},
"rendering_speed": "Скорость рендеринга"
}
},
"prompts": {
"explanation": "Объясните мне этот концепт",
@ -1302,6 +1301,8 @@
"stdio": "Стандартный ввод/вывод (stdio)",
"inMemory": "Память",
"config_description": "Настройка серверов протокола контекста модели",
"disable": "Отключить сервер MCP",
"disable.description": "Не включать функциональность сервера MCP",
"deleteError": "Не удалось удалить сервер",
"deleteSuccess": "Сервер успешно удален",
"dependenciesInstall": "Установить зависимости",

View File

@ -1305,6 +1305,8 @@
"stdio": "标准输入/输出 (stdio)",
"inMemory": "内存",
"config_description": "配置模型上下文协议服务器",
"disable": "不使用 MCP 服务器",
"disable.description": "不启用 MCP 服务功能",
"deleteError": "删除服务器失败",
"deleteSuccess": "服务器删除成功",
"dependenciesInstall": "安装依赖项",

View File

@ -1305,6 +1305,8 @@
"stdio": "標準輸入/輸出 (stdio)",
"inMemory": "記憶體",
"config_description": "設定模型上下文協議伺服器",
"disable": "不使用 MCP 伺服器",
"disable.description": "不啟用 MCP 服務功能",
"deleteError": "刪除伺服器失敗",
"deleteSuccess": "伺服器刪除成功",
"dependenciesInstall": "安裝相依套件",

View File

@ -4,9 +4,8 @@ import { useMCPServers } from '@renderer/hooks/useMCPServers'
import { EventEmitter } from '@renderer/services/EventService'
import { Assistant, MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
import { Form, Input, Tooltip } from 'antd'
import { Plus, SquareTerminal } from 'lucide-react'
import { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import React from 'react'
import { CircleX, Plus, SquareTerminal } from 'lucide-react'
import React, { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router'
@ -132,9 +131,6 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
() => activedMcpServers.filter((server) => mcpServers.some((s) => s.id === server.id)),
[activedMcpServers, mcpServers]
)
const buttonEnabled = assistantMcpServers.length > 0
const handleMcpServerSelect = useCallback(
(server: MCPServer) => {
if (assistantMcpServers.some((s) => s.id === server.id)) {
@ -156,6 +152,18 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
return () => EventEmitter.off('mcp-server-select', handler)
}, [])
const updateMcpEnabled = useCallback(
(enabled: boolean) => {
setTimeout(() => {
updateAssistant({
...assistant,
mcpServers: enabled ? assistant.mcpServers || [] : []
})
}, 200)
},
[assistant, updateAssistant]
)
const menuItems = useMemo(() => {
const newList: QuickPanelListItem[] = activedMcpServers.map((server) => ({
label: server.name,
@ -171,8 +179,16 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
action: () => navigate('/settings/mcp')
})
newList.unshift({
label: t('common.close'),
description: t('settings.mcp.disable.description'),
icon: <CircleX />,
isSelected: !(assistant.mcpServers && assistant.mcpServers.length > 0),
action: () => updateMcpEnabled(false)
})
return newList
}, [activedMcpServers, t, assistantMcpServers, navigate])
}, [activedMcpServers, t, assistant.mcpServers, assistantMcpServers, navigate, updateMcpEnabled])
const openQuickPanel = useCallback(() => {
quickPanel.open({
@ -412,10 +428,9 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
}, [activedMcpServers])
const openResourcesList = useCallback(async () => {
const resources = resourcesList
quickPanel.open({
title: t('settings.mcp.title'),
list: resources,
list: resourcesList,
symbol: 'mcp-resource',
multiple: true
})
@ -442,7 +457,10 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
return (
<Tooltip placement="top" title={t('settings.mcp.title')} arrow>
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
<SquareTerminal size={18} color={buttonEnabled ? 'var(--color-primary)' : 'var(--color-icon)'} />
<SquareTerminal
size={18}
color={assistant.mcpServers && assistant.mcpServers.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)'}
/>
</ToolbarButton>
</Tooltip>
)

View File

@ -6,7 +6,7 @@ import WebSearchService from '@renderer/services/WebSearchService'
import { Assistant, WebSearchProvider } from '@renderer/types'
import { hasObjectKey } from '@renderer/utils'
import { Tooltip } from 'antd'
import { Globe, Settings } from 'lucide-react'
import { CircleX, Globe, Settings } from 'lucide-react'
import { FC, memo, useCallback, useImperativeHandle, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
@ -85,9 +85,9 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
})
items.unshift({
label: t('chat.input.web_search.no_web_search'),
label: t('common.close'),
description: t('chat.input.web_search.no_web_search.description'),
icon: <Globe />,
icon: <CircleX />,
isSelected: !assistant.enableWebSearch && !assistant.webSearchProviderId,
action: () => {
updateSelectedWebSearchProvider(undefined)