MCP DuckDuckGo Search Server
by spences10
Verified
import { useState, useEffect } from 'react'
import {
Box,
Typography,
Paper,
TextField,
Switch,
Button,
Grid,
FormControlLabel,
Alert,
Snackbar,
} from '@mui/material'
import { getSettings, updateSettings, Settings as APISettings } from '../api/client'
interface ServerSettings {
host: string
port: number
maxConnections: number
pingTimeout: number
debugMode: boolean
sslEnabled: boolean
}
interface MCPSettings {
protocolVersion: string
maxContextLength: number
defaultTemperature: number
maxTokens: number
}
function Settings() {
const defaultServerSettings: ServerSettings = {
host: '',
port: 8765,
maxConnections: 100,
pingTimeout: 30,
debugMode: false,
sslEnabled: false,
}
const defaultMCPSettings: MCPSettings = {
protocolVersion: '1.0.0',
maxContextLength: 4096,
defaultTemperature: 0.7,
maxTokens: 2048,
}
const [serverSettings, setServerSettings] = useState<ServerSettings>(defaultServerSettings)
const [mcpSettings, setMcpSettings] = useState<MCPSettings>(defaultMCPSettings)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [success, setSuccess] = useState<string | null>(null)
const [isDirty, setIsDirty] = useState(false)
useEffect(() => {
const loadSettings = async () => {
try {
const { data } = await getSettings()
if (data.server && data.mcp) {
setServerSettings({
host: data.server.host ?? defaultServerSettings.host,
port: data.server.port ?? defaultServerSettings.port,
maxConnections: data.server.maxConnections ?? defaultServerSettings.maxConnections,
pingTimeout: data.server.pingTimeout ?? defaultServerSettings.pingTimeout,
debugMode: data.server.debugMode ?? defaultServerSettings.debugMode,
sslEnabled: data.server.sslEnabled ?? defaultServerSettings.sslEnabled,
})
setMcpSettings({
protocolVersion: data.mcp.protocolVersion ?? defaultMCPSettings.protocolVersion,
maxContextLength: data.mcp.maxContextLength ?? defaultMCPSettings.maxContextLength,
defaultTemperature: data.mcp.defaultTemperature ?? defaultMCPSettings.defaultTemperature,
maxTokens: data.mcp.maxTokens ?? defaultMCPSettings.maxTokens,
})
}
setLoading(false)
} catch (error) {
console.error('Error loading settings:', error)
setError('Failed to load settings')
setLoading(false)
}
}
loadSettings()
}, [])
const handleServerSettingChange = (field: keyof ServerSettings) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value =
field === 'debugMode' || field === 'sslEnabled'
? event.target.checked
: field === 'port' || field === 'maxConnections' || field === 'pingTimeout'
? parseInt(event.target.value)
: event.target.value
setServerSettings((prev) => ({ ...prev, [field]: value }))
setIsDirty(true)
}
const handleMCPSettingChange = (field: keyof MCPSettings) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value =
field === 'defaultTemperature'
? parseFloat(event.target.value)
: field === 'maxContextLength' || field === 'maxTokens'
? parseInt(event.target.value)
: event.target.value
setMcpSettings((prev) => ({ ...prev, [field]: value }))
setIsDirty(true)
}
const handleSave = async () => {
try {
await updateSettings({
server: serverSettings,
mcp: mcpSettings,
})
setSuccess('Settings saved successfully')
setIsDirty(false)
} catch (error) {
console.error('Error saving settings:', error)
setError('Failed to save settings')
}
}
const handleCloseError = () => setError(null)
const handleCloseSuccess = () => setSuccess(null)
if (loading) {
return (
<Box>
<Typography variant="h4" gutterBottom>
Settings
</Typography>
<Typography variant="body1" color="text.secondary">
Loading settings...
</Typography>
</Box>
)
}
return (
<Box>
<Typography variant="h4" gutterBottom>
Settings
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
Configure your MCP server and client settings.
</Typography>
{error && (
<Alert severity="error" sx={{ mb: 3 }}>
{error}
</Alert>
)}
<Grid container spacing={3}>
<Grid item xs={12} md={6}>
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
Server Configuration
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<TextField
label="Host"
value={serverSettings.host}
onChange={handleServerSettingChange('host')}
fullWidth
/>
<TextField
label="Port"
type="number"
value={serverSettings.port}
onChange={handleServerSettingChange('port')}
fullWidth
/>
<FormControlLabel
control={
<Switch
checked={serverSettings.debugMode}
onChange={handleServerSettingChange('debugMode')}
/>
}
label="Debug Mode"
/>
<FormControlLabel
control={
<Switch
checked={serverSettings.sslEnabled}
onChange={handleServerSettingChange('sslEnabled')}
/>
}
label="SSL Enabled"
/>
<TextField
label="Max Connections"
type="number"
value={serverSettings.maxConnections}
onChange={handleServerSettingChange('maxConnections')}
fullWidth
/>
<TextField
label="Ping Timeout (seconds)"
type="number"
value={serverSettings.pingTimeout}
onChange={handleServerSettingChange('pingTimeout')}
fullWidth
/>
</Box>
</Paper>
</Grid>
<Grid item xs={12} md={6}>
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
MCP Configuration
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<TextField
label="Protocol Version"
value={mcpSettings.protocolVersion}
onChange={handleMCPSettingChange('protocolVersion')}
fullWidth
/>
<TextField
label="Max Context Length"
type="number"
value={mcpSettings.maxContextLength}
onChange={handleMCPSettingChange('maxContextLength')}
fullWidth
/>
<TextField
label="Default Temperature"
type="number"
inputProps={{ step: 0.1, min: 0, max: 1 }}
value={mcpSettings.defaultTemperature}
onChange={handleMCPSettingChange('defaultTemperature')}
fullWidth
/>
<TextField
label="Max Tokens"
type="number"
value={mcpSettings.maxTokens}
onChange={handleMCPSettingChange('maxTokens')}
fullWidth
/>
</Box>
</Paper>
</Grid>
</Grid>
<Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end' }}>
<Button
variant="contained"
onClick={handleSave}
disabled={!isDirty}
sx={{ minWidth: 150 }}
>
Save Changes
</Button>
</Box>
<Snackbar
open={!!success}
autoHideDuration={6000}
onClose={handleCloseSuccess}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
>
<Alert onClose={handleCloseSuccess} severity="success">
{success}
</Alert>
</Snackbar>
</Box>
)
}
export default Settings