diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 3dc9cb48..09d41cdc 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -846,8 +846,7 @@ "no_packages": "No packages found", "search_error": "Search error" }, - "jsonMode": "JSON Schema", - "normalMode": "Normal mode", + "editJson": "Edit JSON", "jsonModeHint": "Edit the JSON representation of the MCP server configuration. Please ensure the format is correct before saving.", "jsonFormatError": "JSON formatting error", "jsonSaveSuccess": "JSON configuration has been saved.", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 6299318b..9d455a41 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -846,8 +846,7 @@ "no_packages": "パッケージが見つかりません", "search_error": "パッケージの検索に失敗しました" }, - "jsonMode": "JSONスキーマ", - "normalMode": "通常モード", + "editJson": "JSONを編集", "jsonModeHint": "MCPサーバー設定のJSON表現を編集します。保存する前に、フォーマットが正しいことを確認してください。", "jsonFormatError": "JSONフォーマットエラー", "jsonSaveSuccess": "JSON設定が保存されました。", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index ad60841a..14dd4c62 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -846,8 +846,7 @@ "no_packages": "Ничего не найдено", "search_error": "Ошибка поиска" }, - "jsonMode": "JSON-схема", - "normalMode": "Обычный режим", + "editJson": "Редактировать JSON", "jsonModeHint": "Редактируйте JSON-форматирование конфигурации сервера MCP. Перед сохранением убедитесь, что формат правильный.", "jsonFormatError": "Ошибка форматирования JSON", "jsonSaveSuccess": "JSON конфигурация сохранена", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index cec887e4..470057a5 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -846,8 +846,7 @@ "no_packages": "未找到包", "search_error": "搜索失败" }, - "jsonMode": "JSON模式", - "normalMode": "常规模式", + "editJson": "编辑JSON", "jsonModeHint": "编辑MCP服务器配置的JSON表示。保存前请确保格式正确。", "jsonFormatError": "JSON格式化错误", "jsonSaveSuccess": "JSON配置已保存", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 4691e984..b92546f3 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -846,8 +846,7 @@ "no_packages": "未找到包", "search_error": "搜索失敗" }, - "jsonMode": "JSON模式", - "normalMode": "常規模式", + "editJson": "編輯JSON", "jsonModeHint": "編輯MCP伺服器配置的JSON表示。保存前請確保格式正確。", "jsonFormatError": "JSON格式錯誤", "jsonSaveSuccess": "JSON配置已儲存", diff --git a/src/renderer/src/pages/settings/MCPSettings/EditMcpJsonPopup.tsx b/src/renderer/src/pages/settings/MCPSettings/EditMcpJsonPopup.tsx new file mode 100644 index 00000000..72460f53 --- /dev/null +++ b/src/renderer/src/pages/settings/MCPSettings/EditMcpJsonPopup.tsx @@ -0,0 +1,152 @@ +import { TopView } from '@renderer/components/TopView' +import { useAppDispatch, useAppSelector } from '@renderer/store' +import { setMCPServers } from '@renderer/store/mcp' +import { MCPServer } from '@renderer/types' +import { Modal, Typography } from 'antd' +import TextArea from 'antd/es/input/TextArea' +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' + +interface Props { + resolve: (data: any) => void +} + +const PopupContainer: React.FC = ({ resolve }) => { + const [open, setOpen] = useState(true) + const [jsonConfig, setJsonConfig] = useState('') + const [jsonSaving, setJsonSaving] = useState(false) + const [jsonError, setJsonError] = useState('') + const mcpServers = useAppSelector((state) => state.mcp.servers) + + const dispatch = useAppDispatch() + const { t } = useTranslation() + + const ipcRenderer = window.electron.ipcRenderer + + useEffect(() => { + try { + const mcpServersObj: Record = {} + + mcpServers.forEach((server) => { + const { name, ...serverData } = server + mcpServersObj[name] = serverData + }) + + const standardFormat = { + mcpServers: mcpServersObj + } + + const formattedJson = JSON.stringify(standardFormat, null, 2) + setJsonConfig(formattedJson) + setJsonError('') + } catch (error) { + console.error('Failed to format JSON:', error) + setJsonError(t('settings.mcp.jsonFormatError')) + } + }, [mcpServers, t]) + + const onOk = async () => { + setJsonSaving(true) + try { + if (!jsonConfig.trim()) { + dispatch(setMCPServers([])) + window.message.success(t('settings.mcp.jsonSaveSuccess')) + setJsonError('') + setJsonSaving(false) + return + } + const parsedConfig = JSON.parse(jsonConfig) + + if (!parsedConfig.mcpServers || typeof parsedConfig.mcpServers !== 'object') { + throw new Error(t('settings.mcp.invalidMcpFormat')) + } + + const serversArray: MCPServer[] = [] + for (const [name, serverConfig] of Object.entries(parsedConfig.mcpServers)) { + const server: MCPServer = { + name, + isActive: false, + ...(serverConfig as any) + } + serversArray.push(server) + } + + dispatch(setMCPServers(serversArray)) + ipcRenderer.send('mcp:servers-from-renderer', mcpServers) + + window.message.success(t('settings.mcp.jsonSaveSuccess')) + setJsonError('') + setOpen(false) + } catch (error: any) { + console.error('Failed to save JSON config:', error) + setJsonError(error.message || t('settings.mcp.jsonSaveError')) + window.message.error(t('settings.mcp.jsonSaveError')) + } finally { + setJsonSaving(false) + } + } + + const onCancel = () => { + setOpen(false) + } + + const onClose = () => { + resolve({}) + } + + EditMcpJsonPopup.hide = onCancel + + return ( + +
+ + {jsonError ? {jsonError} : ''} + +
+