import { useEffect, useMemo, useState } from 'react'; import { classNames } from '~/utils/classNames'; import type { MCPConfig } from '~/lib/services/mcpService'; import { toast } from 'react-toastify'; import { useMCPStore } from '~/lib/stores/mcp'; import McpServerList from '~/components/@settings/tabs/mcp/McpServerList'; const EXAMPLE_MCP_CONFIG: MCPConfig = { mcpServers: { everything: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-everything'], }, deepwiki: { type: 'streamable-http', url: 'https://mcp.deepwiki.com/mcp', }, 'local-sse': { type: 'sse', url: 'http://localhost:8000/sse', headers: { Authorization: 'Bearer mytoken123', }, }, }, }; export default function McpTab() { const settings = useMCPStore((state) => state.settings); const isInitialized = useMCPStore((state) => state.isInitialized); const serverTools = useMCPStore((state) => state.serverTools); const initialize = useMCPStore((state) => state.initialize); const updateSettings = useMCPStore((state) => state.updateSettings); const checkServersAvailabilities = useMCPStore((state) => state.checkServersAvailabilities); const [isSaving, setIsSaving] = useState(false); const [mcpConfigText, setMCPConfigText] = useState(''); const [maxLLMSteps, setMaxLLMSteps] = useState(1); const [error, setError] = useState(null); const [isCheckingServers, setIsCheckingServers] = useState(false); const [expandedServer, setExpandedServer] = useState(null); useEffect(() => { if (!isInitialized) { initialize().catch((err) => { setError(`Failed to initialize MCP settings: ${err instanceof Error ? err.message : String(err)}`); toast.error('Failed to load MCP configuration'); }); } }, [isInitialized]); useEffect(() => { setMCPConfigText(JSON.stringify(settings.mcpConfig, null, 2)); setMaxLLMSteps(settings.maxLLMSteps); setError(null); }, [settings]); const parsedConfig = useMemo(() => { try { setError(null); return JSON.parse(mcpConfigText) as MCPConfig; } catch (e) { setError(`Invalid JSON format: ${e instanceof Error ? e.message : String(e)}`); return null; } }, [mcpConfigText]); const handleMaxLLMCallChange = (value: string) => { setMaxLLMSteps(parseInt(value, 10)); }; const handleSave = async () => { if (!parsedConfig) { return; } setIsSaving(true); try { await updateSettings({ mcpConfig: parsedConfig, maxLLMSteps, }); toast.success('MCP configuration saved'); setError(null); } catch (e) { setError(e instanceof Error ? e.message : 'Failed to save configuration'); toast.error('Failed to save MCP configuration'); } finally { setIsSaving(false); } }; const handleLoadExample = () => { setMCPConfigText(JSON.stringify(EXAMPLE_MCP_CONFIG, null, 2)); setError(null); }; const checkServerAvailability = async () => { if (serverEntries.length === 0) { return; } setIsCheckingServers(true); setError(null); try { await checkServersAvailabilities(); } catch (e) { setError(`Failed to check server availability: ${e instanceof Error ? e.message : String(e)}`); } finally { setIsCheckingServers(false); } }; const toggleServerExpanded = (serverName: string) => { setExpandedServer(expandedServer === serverName ? null : serverName); }; const serverEntries = useMemo(() => Object.entries(serverTools), [serverTools]); return (

MCP Servers Configured

{' '}

Configuration