mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-25 19:30:17 +08:00
refactor: simplify MCP service integration and cleanup logic
- Replaced singleton pattern with direct instantiation of McpService for cleaner code. - Updated IPC handlers to use the new mcpService instance directly. - Removed unnecessary logging in Inputbar and MCPToolsButton components to streamline functionality. - Cleaned up error handling in McpSettings to improve user experience.
This commit is contained in:
parent
894c20dd05
commit
3298b3f403
@ -115,7 +115,7 @@ if (!app.requestSingleInstanceLock()) {
|
||||
app.on('will-quit', async () => {
|
||||
// event.preventDefault()
|
||||
try {
|
||||
await mcpService().cleanup()
|
||||
await mcpService.cleanup()
|
||||
} catch (error) {
|
||||
Logger.error('Error cleaning up MCP service:', error)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import FileService from './services/FileService'
|
||||
import FileStorage from './services/FileStorage'
|
||||
import { GeminiService } from './services/GeminiService'
|
||||
import KnowledgeService from './services/KnowledgeService'
|
||||
import { getMcpInstance } from './services/MCPService'
|
||||
import mcpService from './services/MCPService'
|
||||
import NotificationService from './services/NotificationService'
|
||||
import * as NutstoreService from './services/NutstoreService'
|
||||
import ObsidianVaultService from './services/ObsidianVaultService'
|
||||
@ -320,19 +320,17 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
)
|
||||
|
||||
// Register MCP handlers
|
||||
ipcMain.handle(IpcChannel.Mcp_RemoveServer, (event, server) => getMcpInstance().removeServer(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_RestartServer, (event, server) => getMcpInstance().restartServer(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_StopServer, (event, server) => getMcpInstance().stopServer(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_ListTools, (event, server) => getMcpInstance().listTools(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_CallTool, (event, params) => getMcpInstance().callTool(event, params))
|
||||
ipcMain.handle(IpcChannel.Mcp_ListPrompts, (event, server) => getMcpInstance().listPrompts(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_GetPrompt, (event, params) => getMcpInstance().getPrompt(event, params))
|
||||
ipcMain.handle(IpcChannel.Mcp_ListResources, (event, server) => getMcpInstance().listResources(event, server))
|
||||
ipcMain.handle(IpcChannel.Mcp_GetResource, (event, params) => getMcpInstance().getResource(event, params))
|
||||
ipcMain.handle(IpcChannel.Mcp_GetInstallInfo, () => getMcpInstance().getInstallInfo())
|
||||
ipcMain.handle(IpcChannel.Mcp_CheckConnectivity, (event, params) =>
|
||||
getMcpInstance().checkMcpConnectivity(event, params)
|
||||
)
|
||||
ipcMain.handle(IpcChannel.Mcp_RemoveServer, mcpService.removeServer)
|
||||
ipcMain.handle(IpcChannel.Mcp_RestartServer, mcpService.restartServer)
|
||||
ipcMain.handle(IpcChannel.Mcp_StopServer, mcpService.stopServer)
|
||||
ipcMain.handle(IpcChannel.Mcp_ListTools, mcpService.listTools)
|
||||
ipcMain.handle(IpcChannel.Mcp_CallTool, mcpService.callTool)
|
||||
ipcMain.handle(IpcChannel.Mcp_ListPrompts, mcpService.listPrompts)
|
||||
ipcMain.handle(IpcChannel.Mcp_GetPrompt, mcpService.getPrompt)
|
||||
ipcMain.handle(IpcChannel.Mcp_ListResources, mcpService.listResources)
|
||||
ipcMain.handle(IpcChannel.Mcp_GetResource, mcpService.getResource)
|
||||
ipcMain.handle(IpcChannel.Mcp_GetInstallInfo, mcpService.getInstallInfo)
|
||||
ipcMain.handle(IpcChannel.Mcp_CheckConnectivity, mcpService.checkMcpConnectivity)
|
||||
|
||||
ipcMain.handle(IpcChannel.App_IsBinaryExist, (_, name: string) => isBinaryExists(name))
|
||||
ipcMain.handle(IpcChannel.App_GetBinaryPath, (_, name: string) => getBinaryPath(name))
|
||||
|
||||
@ -69,18 +69,10 @@ function withCache<T extends unknown[], R>(
|
||||
}
|
||||
|
||||
class McpService {
|
||||
private static instance: McpService | null = null
|
||||
private clients: Map<string, Client> = new Map()
|
||||
private pendingClients: Map<string, Promise<Client>> = new Map()
|
||||
|
||||
public static getInstance(): McpService {
|
||||
if (!McpService.instance) {
|
||||
McpService.instance = new McpService()
|
||||
}
|
||||
return McpService.instance
|
||||
}
|
||||
|
||||
private constructor() {
|
||||
constructor() {
|
||||
this.initClient = this.initClient.bind(this)
|
||||
this.listTools = this.listTools.bind(this)
|
||||
this.callTool = this.callTool.bind(this)
|
||||
@ -661,13 +653,4 @@ class McpService {
|
||||
})
|
||||
}
|
||||
|
||||
let mcpInstance: ReturnType<typeof McpService.getInstance> | null = null
|
||||
|
||||
export const getMcpInstance = () => {
|
||||
if (!mcpInstance) {
|
||||
mcpInstance = McpService.getInstance()
|
||||
}
|
||||
return mcpInstance
|
||||
}
|
||||
|
||||
export default McpService.getInstance
|
||||
export default new McpService()
|
||||
|
||||
@ -226,10 +226,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
const { message, blocks } = getUserMessage(baseUserMessage)
|
||||
|
||||
currentMessageId.current = message.id
|
||||
Logger.log('[DEBUG] Created message and blocks:', message, blocks)
|
||||
Logger.log('[DEBUG] Dispatching _sendMessage')
|
||||
dispatch(_sendMessage(message, blocks, assistant, topic.id))
|
||||
Logger.log('[DEBUG] _sendMessage dispatched')
|
||||
|
||||
// Clear input
|
||||
setText('')
|
||||
|
||||
@ -3,7 +3,6 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { EventEmitter } from '@renderer/services/EventService'
|
||||
import { Assistant, MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
||||
import { delay, runAsyncFunction } from '@renderer/utils'
|
||||
import { Form, Input, Tooltip } from 'antd'
|
||||
import { Plus, SquareTerminal } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||
@ -110,11 +109,6 @@ const extractPromptContent = (response: any): string | null => {
|
||||
return null
|
||||
}
|
||||
|
||||
// Add static variable before component definition
|
||||
let isFirstResourcesListCall = true
|
||||
let isFirstPromptListCall = true
|
||||
const initMcpDelay = 3
|
||||
|
||||
const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, ToolbarButton, ...props }) => {
|
||||
const { activedMcpServers } = useMCPServers()
|
||||
const { t } = useTranslation()
|
||||
@ -314,11 +308,6 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
const promptList = useMemo(async () => {
|
||||
const prompts: MCPPrompt[] = []
|
||||
|
||||
if (isFirstPromptListCall) {
|
||||
await delay(initMcpDelay)
|
||||
isFirstPromptListCall = false
|
||||
}
|
||||
|
||||
for (const server of activedMcpServers) {
|
||||
const serverPrompts = await window.api.mcp.listPrompts(server)
|
||||
prompts.push(...serverPrompts)
|
||||
@ -392,40 +381,33 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, Toolbar
|
||||
const [resourcesList, setResourcesList] = useState<QuickPanelListItem[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
runAsyncFunction(async () => {
|
||||
let isMounted = true
|
||||
let isMounted = true
|
||||
|
||||
const fetchResources = async () => {
|
||||
const resources: MCPResource[] = []
|
||||
const fetchResources = async () => {
|
||||
const resources: MCPResource[] = []
|
||||
|
||||
for (const server of activedMcpServers) {
|
||||
const serverResources = await window.api.mcp.listResources(server)
|
||||
resources.push(...serverResources)
|
||||
}
|
||||
|
||||
if (isMounted) {
|
||||
setResourcesList(
|
||||
resources.map((resource) => ({
|
||||
label: resource.name,
|
||||
description: resource.description,
|
||||
icon: <SquareTerminal />,
|
||||
action: () => handleResourceSelect(resource)
|
||||
}))
|
||||
)
|
||||
}
|
||||
for (const server of activedMcpServers) {
|
||||
const serverResources = await window.api.mcp.listResources(server)
|
||||
resources.push(...serverResources)
|
||||
}
|
||||
|
||||
// Avoid mcp following the software startup, affecting the startup speed
|
||||
if (isFirstResourcesListCall) {
|
||||
await delay(initMcpDelay)
|
||||
isFirstResourcesListCall = false
|
||||
fetchResources()
|
||||
if (isMounted) {
|
||||
setResourcesList(
|
||||
resources.map((resource) => ({
|
||||
label: resource.name,
|
||||
description: resource.description,
|
||||
icon: <SquareTerminal />,
|
||||
action: () => handleResourceSelect(resource)
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
isMounted = false
|
||||
}
|
||||
})
|
||||
fetchResources()
|
||||
|
||||
return () => {
|
||||
isMounted = false
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [activedMcpServers])
|
||||
|
||||
|
||||
@ -168,10 +168,6 @@ const McpSettings: React.FC = () => {
|
||||
setTools(localTools)
|
||||
} catch (error) {
|
||||
setLoadingServer(server.id)
|
||||
window.message.error({
|
||||
content: t('settings.mcp.tools.loadError') + ' ' + formatError(error),
|
||||
key: 'mcp-tools-error'
|
||||
})
|
||||
} finally {
|
||||
setLoadingServer(null)
|
||||
}
|
||||
@ -185,10 +181,6 @@ const McpSettings: React.FC = () => {
|
||||
const localPrompts = await window.api.mcp.listPrompts(server)
|
||||
setPrompts(localPrompts)
|
||||
} catch (error) {
|
||||
window.message.error({
|
||||
content: t('settings.mcp.prompts.loadError') + ' ' + formatError(error),
|
||||
key: 'mcp-prompts-error'
|
||||
})
|
||||
setPrompts([])
|
||||
} finally {
|
||||
setLoadingServer(null)
|
||||
@ -203,10 +195,6 @@ const McpSettings: React.FC = () => {
|
||||
const localResources = await window.api.mcp.listResources(server)
|
||||
setResources(localResources)
|
||||
} catch (error) {
|
||||
window.message.error({
|
||||
content: t('settings.mcp.resources.loadError') + ' ' + formatError(error),
|
||||
key: 'mcp-resources-error'
|
||||
})
|
||||
setResources([])
|
||||
} finally {
|
||||
setLoadingServer(null)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user