import React, { useCallback, useEffect, useState } from 'react' import { gracefulShutdown } from 'src/utils/gracefulShutdown.js' import { writeToStdout } from 'src/utils/process.js' import { Box, color, Text, useTheme, Byline, Dialog, KeyboardShortcutHint } from '@anthropic/ink' import { addMcpConfig, getAllMcpConfigs } from '../services/mcp/config.js' import type { ConfigScope, McpServerConfig, ScopedMcpServerConfig, } from '../services/mcp/types.js' import { plural } from '../utils/stringUtils.js' import { ConfigurableShortcutHint } from './ConfigurableShortcutHint.js' import { SelectMulti } from './CustomSelect/SelectMulti.js' type Props = { servers: Record scope: ConfigScope onDone(): void } export function MCPServerDesktopImportDialog({ servers, scope, onDone, }: Props): React.ReactNode { const serverNames = Object.keys(servers) const [existingServers, setExistingServers] = useState< Record >({}) useEffect(() => { void getAllMcpConfigs().then(({ servers }) => setExistingServers(servers)) }, []) const collisions = serverNames.filter( name => existingServers[name] !== undefined, ) async function onSubmit(selectedServers: string[]) { let importedCount = 0 for (const serverName of selectedServers) { const serverConfig = servers[serverName] if (serverConfig) { // If the server name already exists, find a new name with _1, _2, etc. let finalName = serverName if (existingServers[finalName] !== undefined) { let counter = 1 while (existingServers[`${serverName}_${counter}`] !== undefined) { counter++ } finalName = `${serverName}_${counter}` } await addMcpConfig(finalName, serverConfig, scope) importedCount++ } } done(importedCount) } const [theme] = useTheme() // Define done before using in useCallback const done = useCallback( (importedCount: number) => { if (importedCount > 0) { writeToStdout( `\n${color('success', theme)(`Successfully imported ${importedCount} MCP ${plural(importedCount, 'server')} to ${scope} config.`)}\n`, ) } else { writeToStdout('\nNo servers were imported.') } onDone() void gracefulShutdown() }, [theme, scope, onDone], ) // Handle ESC to cancel (import 0 servers) const handleEscCancel = useCallback(() => { done(0) }, [done]) return ( <> {collisions.length > 0 && ( Note: Some servers already exist with the same name. If selected, they will be imported with a numbered suffix. )} Please select the servers you want to import: ({ label: `${server}${collisions.includes(server) ? ' (already exists)' : ''}`, value: server, }))} defaultValue={serverNames.filter(name => !collisions.includes(name))} // Only preselect non-colliding servers onSubmit={onSubmit} onCancel={handleEscCancel} hideIndexes /> ) }