import cls from 'classnames'; import React, { useCallback } from 'react'; import { Badge, Button, Icon, Popover, PopoverTriggerType } from '@opensumi/ide-components'; import { useInjectable } from '@opensumi/ide-core-browser'; import { MCPConfigServiceToken, localize } from '@opensumi/ide-core-common'; import { BUILTIN_MCP_SERVER_NAME } from '../../../../common'; import { MCPServerDescription } from '../../../../common/mcp-server-manager'; import { MCPServer } from '../../../../common/types'; import { MCPConfigService } from '../mcp-config.service'; import styles from './mcp-config.module.less'; import { MCPServerForm, MCPServerFormData } from './mcp-server-form'; export const MCPConfigView: React.FC = () => { const mcpConfigService = useInjectable(MCPConfigServiceToken); const [servers, setServers] = React.useState([]); const [formVisible, setFormVisible] = React.useState(false); const [editingServer, setEditingServer] = React.useState(); const [loadingServer, setLoadingServer] = React.useState(); const [isReady, setIsReady] = React.useState(mcpConfigService.isInitialized); const loadServers = useCallback(async () => { const allServers = await mcpConfigService.getServers(); setServers(allServers); }, [mcpConfigService]); React.useEffect(() => { loadServers(); const disposer = mcpConfigService.onMCPServersChange((isReady) => { if (isReady) { setIsReady(true); } loadServers(); }); return () => { disposer.dispose(); }; }, [loadServers]); const handleServerControl = useCallback( async (serverName: string, start: boolean) => { try { setLoadingServer(serverName); await mcpConfigService.controlServer(serverName, start); await loadServers(); setLoadingServer(undefined); } catch (error) { setLoadingServer(undefined); } }, [mcpConfigService, loadServers], ); const handleAddServer = useCallback(() => { setEditingServer(undefined); setFormVisible(true); }, []); const handleEditServer = useCallback( async (server: MCPServer) => { const serverConfig = await mcpConfigService.getServerConfigByName(server.name); if (serverConfig) { setEditingServer(serverConfig); setFormVisible(true); } }, [mcpConfigService], ); const handleDeleteServer = useCallback( async (serverName: string) => { await mcpConfigService.deleteServer(serverName); await loadServers(); }, [mcpConfigService, loadServers], ); const handleSaveServer = useCallback( async (prev: MCPServerDescription | undefined, data: MCPServerFormData) => { setFormVisible(false); await mcpConfigService.saveServer(prev, data); if (prev?.enabled) { setLoadingServer(data.name); await mcpConfigService.controlServer(data.name, true); setLoadingServer(undefined); } await loadServers(); }, [mcpConfigService, loadServers], ); const handleSyncServer = useCallback( async (server: MCPServer) => { setLoadingServer(server.name); await mcpConfigService.syncServer(server.name); await loadServers(); setLoadingServer(undefined); }, [mcpConfigService, loadServers], ); return (

MCP Servers

{localize('ai.native.mcp.manage.connections')}

{servers.map((server) => (

{server.name}

{server.name !== BUILTIN_MCP_SERVER_NAME && (
{server.type && (
Type: {mcpConfigService.getReadableServerType(server.type)}
)}
{server.tools && server.tools.length > 0 && (
Tools: {server.tools.map((tool, index) => ( {tool.name} ))}
)} {server.command && (
Command: {server.command}
)} {server.url && (
Server Link: {server.url}
)}
))}
handleSaveServer(editingServer, data)} onCancel={() => setFormVisible(false)} />
); };