From 16ca373c55e9f91808c2a622086294e5ae5fc351 Mon Sep 17 00:00:00 2001 From: LiuVaayne <10231735+vaayne@users.noreply.github.com> Date: Sat, 12 Jul 2025 15:35:59 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20MCP=20server=20versio?= =?UTF-8?q?n=20display=20with=20badges=20(#8097)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/shared/IpcChannel.ts | 1 + src/main/ipc.ts | 1 + src/main/services/MCPService.ts | 26 +++++++++++ src/preload/index.ts | 3 +- .../settings/MCPSettings/McpServersList.tsx | 45 ++++++++++++++++++- .../settings/MCPSettings/McpSettings.tsx | 39 +++++++++++++++- 6 files changed, 110 insertions(+), 5 deletions(-) diff --git a/packages/shared/IpcChannel.ts b/packages/shared/IpcChannel.ts index b970a6507a..94d7f8819a 100644 --- a/packages/shared/IpcChannel.ts +++ b/packages/shared/IpcChannel.ts @@ -76,6 +76,7 @@ export enum IpcChannel { Mcp_CheckConnectivity = 'mcp:check-connectivity', Mcp_SetProgress = 'mcp:set-progress', Mcp_AbortTool = 'mcp:abort-tool', + Mcp_GetServerVersion = 'mcp:get-server-version', // Python Python_Execute = 'python:execute', diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 7ccbc54ba4..4731056370 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -503,6 +503,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { ipcMain.handle(IpcChannel.Mcp_GetInstallInfo, mcpService.getInstallInfo) ipcMain.handle(IpcChannel.Mcp_CheckConnectivity, mcpService.checkMcpConnectivity) ipcMain.handle(IpcChannel.Mcp_AbortTool, mcpService.abortTool) + ipcMain.handle(IpcChannel.Mcp_GetServerVersion, mcpService.getServerVersion) ipcMain.handle(IpcChannel.Mcp_SetProgress, (_, progress: number) => { mainWindow.webContents.send('mcp-progress', progress) }) diff --git a/src/main/services/MCPService.ts b/src/main/services/MCPService.ts index 9893c81474..0e9100d086 100644 --- a/src/main/services/MCPService.ts +++ b/src/main/services/MCPService.ts @@ -88,6 +88,7 @@ class McpService { this.stopServer = this.stopServer.bind(this) this.abortTool = this.abortTool.bind(this) this.cleanup = this.cleanup.bind(this) + this.getServerVersion = this.getServerVersion.bind(this) } private getServerKey(server: MCPServer): string { @@ -692,6 +693,31 @@ class McpService { return false } } + + /** + * Get the server version information + */ + public async getServerVersion(_: Electron.IpcMainInvokeEvent, server: MCPServer): Promise { + try { + Logger.info(`[MCP] Getting server version for: ${server.name}`) + const client = await this.initClient(server) + + // Try to get server information which may include version + const serverInfo = client.getServerVersion() + Logger.info(`[MCP] Server info for ${server.name}:`, serverInfo) + + if (serverInfo && serverInfo.version) { + Logger.info(`[MCP] Server version for ${server.name}: ${serverInfo.version}`) + return serverInfo.version + } + + Logger.warn(`[MCP] No version information available for server: ${server.name}`) + return null + } catch (error: any) { + Logger.error(`[MCP] Failed to get server version for ${server.name}:`, error?.message) + return null + } + } } export default new McpService() diff --git a/src/preload/index.ts b/src/preload/index.ts index ca88949e70..9e62eb639f 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -241,7 +241,8 @@ const api = { getInstallInfo: () => ipcRenderer.invoke(IpcChannel.Mcp_GetInstallInfo), checkMcpConnectivity: (server: any) => ipcRenderer.invoke(IpcChannel.Mcp_CheckConnectivity, server), abortTool: (callId: string) => ipcRenderer.invoke(IpcChannel.Mcp_AbortTool, callId), - setProgress: (progress: number) => ipcRenderer.invoke(IpcChannel.Mcp_SetProgress, progress) + setProgress: (progress: number) => ipcRenderer.invoke(IpcChannel.Mcp_SetProgress, progress), + getServerVersion: (server: MCPServer) => ipcRenderer.invoke(IpcChannel.Mcp_GetServerVersion, server) }, python: { execute: (script: string, context?: Record, timeout?: number) => diff --git a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx index 1957beefcf..b8efffd2c6 100644 --- a/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx +++ b/src/renderer/src/pages/settings/MCPSettings/McpServersList.tsx @@ -5,9 +5,9 @@ import Scrollbar from '@renderer/components/Scrollbar' import { useMCPServers } from '@renderer/hooks/useMCPServers' import { MCPServer } from '@renderer/types' import { formatMcpError } from '@renderer/utils/error' -import { Button, Dropdown, Empty, Switch, Tag } from 'antd' +import { Badge, Button, Dropdown, Empty, Switch, Tag } from 'antd' import { MonitorCheck, Plus, RefreshCw, Settings2, SquareArrowOutUpRight } from 'lucide-react' -import { FC, useCallback, useState } from 'react' +import { FC, useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useNavigate } from 'react-router' import styled from 'styled-components' @@ -25,6 +25,27 @@ const McpServersList: FC = () => { const navigate = useNavigate() const [isAddModalVisible, setIsAddModalVisible] = useState(false) const [loadingServerIds, setLoadingServerIds] = useState>(new Set()) + const [serverVersions, setServerVersions] = useState>({}) + + const fetchServerVersion = useCallback(async (server: MCPServer) => { + if (!server.isActive) return + + try { + const version = await window.api.mcp.getServerVersion(server) + setServerVersions((prev) => ({ ...prev, [server.id]: version })) + } catch (error) { + setServerVersions((prev) => ({ ...prev, [server.id]: null })) + } + }, []) + + // Fetch versions for all active servers + useEffect(() => { + mcpServers.forEach((server) => { + if (server.isActive) { + fetchServerVersion(server) + } + }) + }, [mcpServers, fetchServerVersion]) const onAddMcpServer = useCallback(async () => { const newServer = { @@ -64,8 +85,12 @@ const McpServersList: FC = () => { try { if (active) { await window.api.mcp.listTools(server) + // Fetch version when server is activated + fetchServerVersion({ ...server, isActive: active }) } else { await window.api.mcp.stopServer(server) + // Clear version when server is deactivated + setServerVersions((prev) => ({ ...prev, [server.id]: null })) } updateMCPServer({ ...server, isActive: active }) } catch (error: any) { @@ -126,6 +151,7 @@ const McpServersList: FC = () => { {server.logoUrl && } {server.name} + {serverVersions[server.id] && } {server.providerUrl && (