File size: 5,445 Bytes
379a97e
7dec804
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

const TOOLS = [
  { value: 'list_files', label: 'List Files', description: 'Lists files and directories in a given path.', params: [{ name: 'path', type: 'text', label: 'Directory Path' }] },
  { value: 'read_file', label: 'Read File', description: 'Reads the content of a specific file.', params: [{ name: 'path', type: 'text', label: 'File Path' }] },
  { value: 'create_file', label: 'Create File', description: 'Creates a new file with optional content.', params: [{ name: 'path', type: 'text', label: 'New File Path' }, { name: 'content', type: 'textarea', label: 'Initial Content (optional)' }] },
  { value: 'write_file', label: 'Write to File', description: 'Writes content to a file, creating a backup first.', params: [{ name: 'path', type: 'text', label: 'File Path' }, { name: 'content', type: 'textarea', label: 'New Content' }] },
  { value: 'delete_file', label: 'Delete File', description: 'Deletes a specific file.', params: [{ name: 'path', type: 'text', label: 'File to Delete' }] },
  { value: 'identify_log_errors', label: 'Identify Log Errors', description: 'Scans a log file for common error messages.', params: [{ name: 'log_file_path', type: 'text', label: 'Log File Path' }] },
];

function App() {
  const [selectedTool, setSelectedTool] = React.useState(TOOLS[0].value);
  const [parameters, setParameters] = React.useState({ path: 'C:\\temp' });
  const [isLoading, setIsLoading] = React.useState(false);
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState('');

  const currentTool = React.useMemo(() => TOOLS.find(t => t.value === selectedTool), [selectedTool]);

  const handleToolChange = (e) => {
    const newToolName = e.target.value;
    setSelectedTool(newToolName);
    setParameters({});
    setResponse(null);
    setError('');
  };

  const handleParamChange = (name, value) => {
    setParameters(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsLoading(true);
    setResponse(null);
    setError('');

    const invocation_id = `mcp-ui-${Date.now()}`;
    const endpoint = `http://127.0.0.1:8000/mcp/invoke/${selectedTool}`;

    try {
      const res = await fetch(endpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          tool_name: selectedTool,
          invocation_id,
          parameters,
        }),
      });

      const data = await res.json();
      if (!res.ok || data.result?.status === 'error') {
        throw new Error(data.result?.message || `Server responded with status: ${res.status}`);
      }
      setResponse(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An unknown error occurred.');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="container">
      <header>
        <h1>MCP Toolkit Control Panel</h1>
        <p>A client to interact with the Maintenance & Control Program toolkit server.</p>
      </header>
      
      <main>
        <div className="card form-card">
          <h2>Select a Tool</h2>
          <form onSubmit={handleSubmit}>
            <div className="form-group">
              <label htmlFor="tool-select">Tool</label>
              <select id="tool-select" value={selectedTool} onChange={handleToolChange}>
                {TOOLS.map(tool => (
                  <option key={tool.value} value={tool.value}>{tool.label}</option>
                ))}
              </select>
              <p>{currentTool.description}</p>
            </div>
            
            {currentTool.params.map(param => (
              <div className="form-group" key={param.name}>
                <label htmlFor={param.name}>{param.label}</label>
                {param.type === 'textarea' ? (
                  <textarea
                    id={param.name}
                    value={parameters[param.name] || ''}
                    onChange={(e) => handleParamChange(param.name, e.target.value)}
                    required
                  />
                ) : (
                  <input
                    id={param.name}
                    type="text"
                    value={parameters[param.name] || ''}
                    onChange={(e) => handleParamChange(param.name, e.target.value)}
                    required
                  />
                )}
              </div>
            ))}

            <button type="submit" disabled={isLoading}>
              {isLoading ? 'Running...' : `Run: ${currentTool.label}`}
            </button>
          </form>
        </div>

        {isLoading && (
          <div className="card status-card">
            <div className="loader">
                <span></span>
                <span></span>
                <span></span>
            </div>
            <p>Communicating with MCP Server...</p>
          </div>
        )}

        {error && (
          <div className="card result-card error">
            <h2>Error</h2>
            <pre>{error}</pre>
          </div>
        )}

        {response && (
          <div className="card result-card success">
            <h2>Result for Invocation: {response.invocation_id}</h2>
            <pre>{JSON.stringify(response.result, null, 2)}</pre>
          </div>
        )}
      </main>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);