MCPServerMultiselectDialog.tsx
1 import React from 'react' 2 import { Box, Text, useInput } from 'ink' 3 import { getTheme } from '../utils/theme.js' 4 import { MultiSelect } from '@inkjs/ui' 5 import { 6 saveCurrentProjectConfig, 7 getCurrentProjectConfig, 8 } from '../utils/config.js' 9 import { partition } from 'lodash-es' 10 import { MCPServerDialogCopy } from './MCPServerDialogCopy.js' 11 import { useExitOnCtrlCD } from '../hooks/useExitOnCtrlCD.js' 12 13 type Props = { 14 serverNames: string[] 15 onDone(): void 16 } 17 18 export function MCPServerMultiselectDialog({ 19 serverNames, 20 onDone, 21 }: Props): React.ReactNode { 22 const theme = getTheme() 23 function onSubmit(selectedServers: string[]) { 24 const config = getCurrentProjectConfig() 25 26 // Initialize arrays if they don't exist 27 if (!config.approvedMcprcServers) { 28 config.approvedMcprcServers = [] 29 } 30 if (!config.rejectedMcprcServers) { 31 config.rejectedMcprcServers = [] 32 } 33 34 // Use partition to separate approved and rejected servers 35 const [approvedServers, rejectedServers] = partition(serverNames, server => 36 selectedServers.includes(server), 37 ) 38 39 // Add new servers directly to the respective lists 40 config.approvedMcprcServers.push(...approvedServers) 41 config.rejectedMcprcServers.push(...rejectedServers) 42 43 saveCurrentProjectConfig(config) 44 onDone() 45 } 46 47 const exitState = useExitOnCtrlCD(() => process.exit()) 48 49 useInput((_input, key) => { 50 if (key.escape) { 51 // On escape, treat all servers as rejected 52 const config = getCurrentProjectConfig() 53 if (!config.rejectedMcprcServers) { 54 config.rejectedMcprcServers = [] 55 } 56 57 for (const server of serverNames) { 58 if (!config.rejectedMcprcServers.includes(server)) { 59 config.rejectedMcprcServers.push(server) 60 } 61 } 62 63 saveCurrentProjectConfig(config) 64 onDone() 65 return 66 } 67 }) 68 69 return ( 70 <> 71 <Box 72 flexDirection="column" 73 gap={1} 74 padding={1} 75 borderStyle="round" 76 borderColor={theme.warning} 77 > 78 <Text bold color={theme.warning}> 79 New MCP Servers Detected 80 </Text> 81 <Text> 82 This project contains a .mcprc file with {serverNames.length} MCP 83 servers that require your approval. 84 </Text> 85 <MCPServerDialogCopy /> 86 87 <Text>Please select the servers you want to enable:</Text> 88 89 <MultiSelect 90 options={serverNames.map(server => ({ 91 label: server, 92 value: server, 93 }))} 94 defaultValue={serverNames} 95 onSubmit={onSubmit} 96 /> 97 </Box> 98 <Box marginLeft={3}> 99 <Text dimColor> 100 {exitState.pending ? ( 101 <>Press {exitState.keyName} again to exit</> 102 ) : ( 103 <>Space to select · Enter to confirm · Esc to reject all</> 104 )} 105 </Text> 106 </Box> 107 </> 108 ) 109 }