import { useState } from 'react' import { useTranslation } from 'react-i18next' import { Server, EnvVar, ServerFormData } from '@/types' interface ServerFormProps { onSubmit: (payload: any) => void onCancel: () => void initialData?: Server | null modalTitle: string formError?: string | null } const ServerForm = ({ onSubmit, onCancel, initialData = null, modalTitle, formError = null }: ServerFormProps) => { const { t } = useTranslation() // Determine the initial server type from the initialData const getInitialServerType = () => { if (!initialData || !initialData.config) return 'stdio'; if (initialData.config.type) { return initialData.config.type; // Use explicit type if available } else if (initialData.config.url) { return 'sse'; // Fallback to SSE if URL exists } else { return 'stdio'; // Default to stdio } }; const [serverType, setServerType] = useState<'stdio' | 'sse' | 'streamable-http'>(getInitialServerType()); const [formData, setFormData] = useState({ name: (initialData && initialData.name) || '', url: (initialData && initialData.config && initialData.config.url) || '', command: (initialData && initialData.config && initialData.config.command) || '', arguments: initialData && initialData.config && initialData.config.args ? Array.isArray(initialData.config.args) ? initialData.config.args.join(' ') : String(initialData.config.args) : '', args: (initialData && initialData.config && initialData.config.args) || [], type: getInitialServerType(), // Initialize the type field env: [], headers: [] }) const [envVars, setEnvVars] = useState( initialData && initialData.config && initialData.config.env ? Object.entries(initialData.config.env).map(([key, value]) => ({ key, value })) : [], ) const [headerVars, setHeaderVars] = useState( initialData && initialData.config && initialData.config.headers ? Object.entries(initialData.config.headers).map(([key, value]) => ({ key, value })) : [], ) const [error, setError] = useState(null) const isEdit = !!initialData const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target setFormData({ ...formData, [name]: value }) } // Transform space-separated arguments string into array const handleArgsChange = (value: string) => { let args = value.split(' ').filter((arg) => arg.trim() !== '') setFormData({ ...formData, arguments: value, args }) } const updateServerType = (type: 'stdio' | 'sse' | 'streamable-http') => { setServerType(type); setFormData(prev => ({ ...prev, type })); } const handleEnvVarChange = (index: number, field: 'key' | 'value', value: string) => { const newEnvVars = [...envVars] newEnvVars[index][field] = value setEnvVars(newEnvVars) } const addEnvVar = () => { setEnvVars([...envVars, { key: '', value: '' }]) } const removeEnvVar = (index: number) => { const newEnvVars = [...envVars] newEnvVars.splice(index, 1) setEnvVars(newEnvVars) } const handleHeaderVarChange = (index: number, field: 'key' | 'value', value: string) => { const newHeaderVars = [...headerVars] newHeaderVars[index][field] = value setHeaderVars(newHeaderVars) } const addHeaderVar = () => { setHeaderVars([...headerVars, { key: '', value: '' }]) } const removeHeaderVar = (index: number) => { const newHeaderVars = [...headerVars] newHeaderVars.splice(index, 1) setHeaderVars(newHeaderVars) } // Submit handler for server configuration const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setError(null) try { const env: Record = {} envVars.forEach(({ key, value }) => { if (key.trim()) { env[key.trim()] = value } }) const headers: Record = {} headerVars.forEach(({ key, value }) => { if (key.trim()) { headers[key.trim()] = value } }) const payload = { name: formData.name, config: { type: serverType, // Always include the type ...(serverType === 'sse' || serverType === 'streamable-http' ? { url: formData.url, ...(Object.keys(headers).length > 0 ? { headers } : {}) } : { command: formData.command, args: formData.args, env: Object.keys(env).length > 0 ? env : undefined, } ) } } onSubmit(payload) } catch (err) { setError(`Error: ${err instanceof Error ? err.message : String(err)}`) } } return (

{modalTitle}

{(error || formError) && (
{formError || error}
)}
updateServerType('stdio')} className="mr-1" />
updateServerType('sse')} className="mr-1" />
updateServerType('streamable-http')} className="mr-1" />
{serverType === 'sse' || serverType === 'streamable-http' ? ( <>
{headerVars.map((headerVar, index) => (
handleHeaderVarChange(index, 'key', e.target.value)} className="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-1/2" placeholder="Authorization" /> : handleHeaderVarChange(index, 'value', e.target.value)} className="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-1/2" placeholder="Bearer token..." />
))}
) : ( <>
handleArgsChange(e.target.value)} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" placeholder="e.g.: -y time-mcp" required={serverType === 'stdio'} />
{envVars.map((envVar, index) => (
handleEnvVarChange(index, 'key', e.target.value)} className="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-1/2" placeholder={t('server.key')} /> : handleEnvVarChange(index, 'value', e.target.value)} className="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-1/2" placeholder={t('server.value')} />
))}
)}
) } export default ServerForm