Skip to content

Commit 9adc527

Browse files
committed
ai-plugin: Enhance MCP settings with editor dialog integration
- Replace plain textarea with professional editor dialog - Add MCPServer interface support for environment variables - Update example configuration with modern MCP server setups - Add configuration summary with server count and status display - Integrate MCPConfigEditorDialog for better user experience - Show detailed server list with enabled/disabled status - Remove complex JSON validation in favor of editor dialog approach Signed-off-by: ashu8912 <aghildiyal@microsoft.com>
1 parent ad9f561 commit 9adc527

File tree

1 file changed

+66
-175
lines changed

1 file changed

+66
-175
lines changed
Lines changed: 66 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1+
import { Icon } from '@iconify/react';
12
import { SectionBox } from '@kinvolk/headlamp-plugin/lib/components/common';
23
import {
34
Box,
45
Button,
56
FormControlLabel,
67
Switch,
7-
TextField,
88
Typography,
9-
Alert,
109
} from '@mui/material';
11-
import { Icon } from '@iconify/react';
1210
import React, { useEffect, useState } from 'react';
1311
import { pluginStore } from '../../utils';
12+
import MCPConfigEditorDialog from './MCPConfigEditorDialog';
1413

1514
// Helper function to check if running in Electron
1615
const isElectron = (): boolean => {
@@ -23,6 +22,7 @@ export interface MCPServer {
2322
name: string;
2423
command: string;
2524
args: string[];
25+
env?: Record<string, string>;
2626
enabled: boolean;
2727
}
2828

@@ -36,13 +36,6 @@ interface MCPSettingsProps {
3636
onConfigChange?: (config: MCPConfig) => void;
3737
}
3838

39-
const defaultMCPServer: MCPServer = {
40-
name: '',
41-
command: 'npx',
42-
args: [],
43-
enabled: true,
44-
};
45-
4639
export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
4740
const [mcpConfig, setMCPConfig] = useState<MCPConfig>(
4841
config || {
@@ -51,8 +44,7 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
5144
}
5245
);
5346

54-
const [jsonConfig, setJsonConfig] = useState('');
55-
const [jsonError, setJsonError] = useState('');
47+
const [editorDialogOpen, setEditorDialogOpen] = useState(false);
5648

5749
useEffect(() => {
5850
// Load MCP config from Electron if available
@@ -67,10 +59,6 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
6759
}
6860
}, []);
6961

70-
// Update JSON config when mcpConfig changes
71-
useEffect(() => {
72-
setJsonConfig(JSON.stringify(mcpConfig, null, 2));
73-
}, [mcpConfig]);
7462

7563
const loadMCPConfigFromElectron = async () => {
7664
if (!isElectron()) return;
@@ -140,25 +128,25 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
140128
name: 'inspektor-gadget',
141129
command: 'docker',
142130
args: [
143-
'run', '-i', '--rm',
144-
'--mount', 'type=bind,src=%USERPROFILE%\\.kube\\config,dst=/root/.kube/config,readonly',
145-
'--mount', 'type=bind,src=%USERPROFILE%\\.minikube,dst=/root/.minikube,readonly',
146-
'ghcr.io/inspektor-gadget/ig-mcp-server:latest',
147-
'-gadget-discoverer=artifacthub'
131+
'mcp',
132+
'gateway',
133+
'run'
148134
],
149-
enabled: false, // Disabled by default to avoid errors
135+
enabled: true,
150136
},
151137
{
152-
name: 'filesystem',
153-
command: 'npx',
138+
name: 'flux-mcp',
139+
command: 'flux-operator-mcp',
154140
args: [
155-
'-y', '@danielsuguimoto/readonly-server-filesystem',
156-
'C:\\Users\\' + (process.env.USERNAME || 'username') + '\\Desktop'
141+
'serve'
157142
],
143+
env: {
144+
'KUBECONFIG': '/Users/ashughildiyal/.kube/config'
145+
},
158146
enabled: true,
159147
}
160148
];
161-
149+
162150
newConfig.servers = defaultServers;
163151
}
164152

@@ -167,87 +155,16 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
167155

168156

169157

170-
const handleJsonConfigChange = (value: string) => {
171-
setJsonConfig(value);
172-
setJsonError('');
173-
};
174-
175-
const validateAndApplyJsonConfig = () => {
176-
try {
177-
const parsedConfig = JSON.parse(jsonConfig) as MCPConfig;
178-
179-
// Validate the structure
180-
if (typeof parsedConfig.enabled !== 'boolean') {
181-
throw new Error('enabled field must be a boolean');
182-
}
183-
184-
if (!Array.isArray(parsedConfig.servers)) {
185-
throw new Error('servers field must be an array');
186-
}
187-
188-
// Validate each server
189-
parsedConfig.servers.forEach((server, index) => {
190-
if (typeof server.name !== 'string') {
191-
throw new Error(`Server ${index}: name must be a string`);
192-
}
193-
if (typeof server.command !== 'string') {
194-
throw new Error(`Server ${index}: command must be a string`);
195-
}
196-
if (!Array.isArray(server.args)) {
197-
throw new Error(`Server ${index}: args must be an array`);
198-
}
199-
if (typeof server.enabled !== 'boolean') {
200-
throw new Error(`Server ${index}: enabled must be a boolean`);
201-
}
202-
});
203-
204-
// Apply the config
205-
handleConfigChange(parsedConfig);
206-
setJsonError('');
207-
} catch (error) {
208-
setJsonError(error instanceof Error ? error.message : 'Invalid JSON configuration');
209-
}
210-
};
211-
212-
const resetJsonToCurrentConfig = () => {
213-
setJsonConfig(JSON.stringify(mcpConfig, null, 2));
214-
setJsonError('');
158+
const handleOpenEditorDialog = () => {
159+
setEditorDialogOpen(true);
215160
};
216161

217-
const getExampleConfig = (): MCPConfig => {
218-
return {
219-
enabled: true,
220-
servers: [
221-
{
222-
name: "inspektor-gadget",
223-
command: "docker",
224-
args: [
225-
"run", "-i", "--rm",
226-
"--mount", "type=bind,src=%USERPROFILE%\\.kube\\config,dst=/root/.kube/config,readonly",
227-
"--mount", "type=bind,src=%USERPROFILE%\\.minikube,dst=/root/.minikube,readonly",
228-
"ghcr.io/inspektor-gadget/ig-mcp-server:latest",
229-
"-gadget-discoverer=artifacthub"
230-
],
231-
enabled: false
232-
},
233-
{
234-
name: "filesystem",
235-
command: "npx",
236-
args: [
237-
"-y", "@danielsuguimoto/readonly-server-filesystem",
238-
"C:\\Users\\username\\Desktop",
239-
"C:\\Users\\username\\Documents"
240-
],
241-
enabled: true
242-
}
243-
]
244-
};
162+
const handleCloseEditorDialog = () => {
163+
setEditorDialogOpen(false);
245164
};
246165

247-
const loadExampleConfig = () => {
248-
const exampleConfig = getExampleConfig();
249-
setJsonConfig(JSON.stringify(exampleConfig, null, 2));
250-
setJsonError('');
166+
const handleSaveConfig = (newConfig: MCPConfig) => {
167+
handleConfigChange(newConfig);
251168
};
252169

253170
// Only show MCP settings in Electron
@@ -282,86 +199,60 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
282199

283200
{mcpConfig.enabled && (
284201
<>
285-
{/* JSON Configuration */}
202+
{/* Configuration Summary */}
286203
<Box sx={{ mb: 3 }}>
287204
<Typography variant="h6" sx={{ mb: 2 }}>
288-
JSON Configuration Editor
205+
Server Configuration
289206
</Typography>
290207
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
291-
Edit your MCP servers configuration as JSON. This allows you to easily add, remove,
292-
and modify multiple servers at once.
208+
You have {mcpConfig.servers.length} server(s) configured.
209+
{mcpConfig.servers.filter(s => s.enabled).length} server(s) are currently enabled.
293210
</Typography>
294-
295-
{jsonError && (
296-
<Alert severity="error" sx={{ mb: 2 }}>
297-
{jsonError}
298-
</Alert>
299-
)}
300-
301-
<TextField
302-
label="MCP Configuration JSON"
303-
value={jsonConfig}
304-
onChange={(e) => handleJsonConfigChange(e.target.value)}
305-
multiline
306-
rows={15}
307-
fullWidth
308-
variant="outlined"
309-
sx={{
310-
mb: 2,
311-
'& .MuiInputBase-input': {
312-
fontFamily: 'monospace',
313-
fontSize: '0.875rem',
314-
}
315-
}}
316-
helperText="Edit the JSON configuration above. Make sure to keep the proper structure."
317-
/>
318-
319-
<Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
320-
<Button
321-
variant="contained"
322-
onClick={validateAndApplyJsonConfig}
323-
startIcon={<Icon icon="mdi:check" />}
324-
>
325-
Apply Configuration
326-
</Button>
327-
<Button
328-
variant="outlined"
329-
onClick={resetJsonToCurrentConfig}
330-
startIcon={<Icon icon="mdi:refresh" />}
331-
>
332-
Reset to Current
333-
</Button>
334-
<Button
335-
variant="outlined"
336-
onClick={loadExampleConfig}
337-
startIcon={<Icon icon="mdi:file-document" />}
338-
>
339-
Load Example
340-
</Button>
341-
</Box>
342211

343-
{/* Schema Documentation */}
344-
<Box sx={{ p: 2, bgcolor: 'grey.50', borderRadius: 1, mb: 3 }}>
345-
<Typography variant="subtitle2" sx={{ mb: 2 }}>
346-
📝 Configuration Schema:
347-
</Typography>
348-
<Typography variant="body2" sx={{ fontFamily: 'monospace', fontSize: '0.8rem', mb: 1 }}>
349-
{JSON.stringify({
350-
"enabled": "boolean - Enable/disable MCP servers",
351-
"servers": [
352-
{
353-
"name": "string - Unique server name",
354-
"command": "string - Executable command",
355-
"args": ["array of strings - Command arguments"],
356-
"enabled": "boolean - Enable/disable this server"
357-
}
358-
]
359-
}, null, 2)}
212+
<Button
213+
variant="contained"
214+
onClick={handleOpenEditorDialog}
215+
startIcon={<Icon icon="mdi:pencil" />}
216+
>
217+
Edit Configuration
218+
</Button>
219+
</Box>
220+
221+
{/* Server List Summary */}
222+
{mcpConfig.servers.length > 0 && (
223+
<Box sx={{ mb: 3 }}>
224+
<Typography variant="subtitle2" sx={{ mb: 1 }}>
225+
Configured Servers:
360226
</Typography>
227+
<Box component="ul" sx={{ pl: 2 }}>
228+
{mcpConfig.servers.map((server, index) => (
229+
<li key={index}>
230+
<Typography variant="body2">
231+
<strong>{server.name}</strong> ({server.command}) -
232+
<span style={{ color: server.enabled ? 'green' : 'red', marginLeft: '8px' }}>
233+
{server.enabled ? 'Enabled' : 'Disabled'}
234+
</span>
235+
{server.env && (
236+
<span style={{ marginLeft: '8px', fontStyle: 'italic' }}>
237+
(with env variables)
238+
</span>
239+
)}
240+
</Typography>
241+
</li>
242+
))}
243+
</Box>
361244
</Box>
245+
)}
246+
</>
247+
)}
362248

363-
</Box>
364-
</>)}
249+
{/* Editor Dialog */}
250+
<MCPConfigEditorDialog
251+
open={editorDialogOpen}
252+
onClose={handleCloseEditorDialog}
253+
config={mcpConfig}
254+
onSave={handleSaveConfig}
255+
/>
365256
</SectionBox>
366257
);
367258
}

0 commit comments

Comments
 (0)