Attach to ui

Signed-off-by: mudler <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-04-22 23:21:55 +02:00
committed by mudler
parent 4b727116cd
commit e9cd6a1073
3 changed files with 164 additions and 10 deletions

View File

@@ -67,11 +67,12 @@ type AgentConfig struct {
} }
type AgentConfigMeta struct { type AgentConfigMeta struct {
Fields []config.Field Fields []config.Field
Connectors []config.FieldGroup Connectors []config.FieldGroup
Actions []config.FieldGroup Actions []config.FieldGroup
DynamicPrompts []config.FieldGroup DynamicPrompts []config.FieldGroup
MCPServers []config.Field MCPServers []config.Field
MCPSTDIOServers []config.Field
} }
func NewAgentConfigMeta( func NewAgentConfigMeta(
@@ -288,6 +289,28 @@ func NewAgentConfigMeta(
Required: true, Required: true,
}, },
}, },
MCPSTDIOServers: []config.Field{
{
Name: "cmd",
Label: "Command",
Type: config.FieldTypeText,
Required: true,
},
{
Name: "args",
Label: "Arguments",
Type: config.FieldTypeText,
Required: true,
HelpText: "Comma-separated list of arguments",
},
{
Name: "env",
Label: "Environment Variables",
Type: config.FieldTypeText,
Required: true,
HelpText: "Comma-separated list of environment variables in KEY=VALUE format",
},
},
DynamicPrompts: dynamicPromptsConfig, DynamicPrompts: dynamicPromptsConfig,
Connectors: connectorsConfig, Connectors: connectorsConfig,
Actions: actionsConfig, Actions: actionsConfig,

View File

@@ -157,6 +157,40 @@ const AgentForm = ({
}); });
}; };
// Handle adding an MCP STDIO server
const handleAddMCPSTDIOServer = () => {
setFormData({
...formData,
mcp_stdio_servers: [
...(formData.mcp_stdio_servers || []),
{ cmd: '', args: [], env: [] }
]
});
};
// Handle removing an MCP STDIO server
const handleRemoveMCPSTDIOServer = (index) => {
const updatedSTDIOServers = [...formData.mcp_stdio_servers];
updatedSTDIOServers.splice(index, 1);
setFormData({
...formData,
mcp_stdio_servers: updatedSTDIOServers
});
};
// Handle MCP STDIO server change
const handleMCPSTDIOServerChange = (index, field, value) => {
const updatedSTDIOServers = [...formData.mcp_stdio_servers];
updatedSTDIOServers[index] = {
...updatedSTDIOServers[index],
[field]: value
};
setFormData({
...formData,
mcp_stdio_servers: updatedSTDIOServers
});
};
if (loading) { if (loading) {
return <div className="loading">Loading...</div>; return <div className="loading">Loading...</div>;
} }
@@ -260,7 +294,15 @@ const AgentForm = ({
</div> </div>
<div style={{ display: activeSection === 'mcp-section' ? 'block' : 'none' }}> <div style={{ display: activeSection === 'mcp-section' ? 'block' : 'none' }}>
<MCPServersSection formData={formData} handleAddMCPServer={handleAddMCPServer} handleRemoveMCPServer={handleRemoveMCPServer} handleMCPServerChange={handleMCPServerChange} /> <MCPServersSection
formData={formData}
handleAddMCPServer={handleAddMCPServer}
handleRemoveMCPServer={handleRemoveMCPServer}
handleMCPServerChange={handleMCPServerChange}
handleAddMCPSTDIOServer={handleAddMCPSTDIOServer}
handleRemoveMCPSTDIOServer={handleRemoveMCPSTDIOServer}
handleMCPSTDIOServerChange={handleMCPSTDIOServerChange}
/>
</div> </div>
<div style={{ display: activeSection === 'memory-section' ? 'block' : 'none' }}> <div style={{ display: activeSection === 'memory-section' ? 'block' : 'none' }}>
@@ -311,7 +353,15 @@ const AgentForm = ({
</div> </div>
<div style={{ display: activeSection === 'mcp-section' ? 'block' : 'none' }}> <div style={{ display: activeSection === 'mcp-section' ? 'block' : 'none' }}>
<MCPServersSection formData={formData} handleAddMCPServer={handleAddMCPServer} handleRemoveMCPServer={handleRemoveMCPServer} handleMCPServerChange={handleMCPServerChange} /> <MCPServersSection
formData={formData}
handleAddMCPServer={handleAddMCPServer}
handleRemoveMCPServer={handleRemoveMCPServer}
handleMCPServerChange={handleMCPServerChange}
handleAddMCPSTDIOServer={handleAddMCPSTDIOServer}
handleRemoveMCPSTDIOServer={handleRemoveMCPSTDIOServer}
handleMCPSTDIOServerChange={handleMCPSTDIOServerChange}
/>
</div> </div>
<div style={{ display: activeSection === 'memory-section' ? 'block' : 'none' }}> <div style={{ display: activeSection === 'memory-section' ? 'block' : 'none' }}>

View File

@@ -8,7 +8,10 @@ const MCPServersSection = ({
formData, formData,
handleAddMCPServer, handleAddMCPServer,
handleRemoveMCPServer, handleRemoveMCPServer,
handleMCPServerChange handleMCPServerChange,
handleAddMCPSTDIOServer,
handleRemoveMCPSTDIOServer,
handleMCPSTDIOServerChange
}) => { }) => {
// Define field definitions for each MCP server // Define field definitions for each MCP server
const getServerFields = () => [ const getServerFields = () => [
@@ -27,14 +30,55 @@ const MCPServersSection = ({
}, },
]; ];
// Define field definitions for each MCP STDIO server
const getSTDIOServerFields = () => [
{
name: 'cmd',
label: 'Command',
type: 'text',
defaultValue: '',
required: true,
},
{
name: 'args',
label: 'Arguments',
type: 'text',
defaultValue: '',
required: true,
helpText: 'Comma-separated list of arguments',
},
{
name: 'env',
label: 'Environment Variables',
type: 'text',
defaultValue: '',
required: true,
helpText: 'Comma-separated list of environment variables in KEY=VALUE format',
},
];
// Handle field value changes for a specific server // Handle field value changes for a specific server
const handleFieldChange = (index, e) => { const handleFieldChange = (index, e, isStdio = false) => {
const { name, value, type, checked } = e.target; const { name, value, type, checked } = e.target;
// Convert value to number if it's a number input // Convert value to number if it's a number input
const processedValue = type === 'number' ? Number(value) : value; const processedValue = type === 'number' ? Number(value) : value;
handleMCPServerChange(index, name, type === 'checkbox' ? checked : processedValue); // Handle comma-separated values for args and env
if (name === 'args' || name === 'env') {
const values = value.split(',').map(v => v.trim()).filter(v => v);
if (isStdio) {
handleMCPSTDIOServerChange(index, name, values);
} else {
handleMCPServerChange(index, name, values);
}
} else {
if (isStdio) {
handleMCPSTDIOServerChange(index, name, type === 'checkbox' ? checked : processedValue);
} else {
handleMCPServerChange(index, name, type === 'checkbox' ? checked : processedValue);
}
}
}; };
return ( return (
@@ -75,6 +119,43 @@ const MCPServersSection = ({
<i className="fas fa-plus"></i> Add MCP Server <i className="fas fa-plus"></i> Add MCP Server
</button> </button>
</div> </div>
<h3 className="section-title mt-4">MCP STDIO Servers</h3>
<p className="section-description">
Configure MCP STDIO servers for this agent.
</p>
<div className="mcp-stdio-servers-container">
{formData.mcp_stdio_servers && formData.mcp_stdio_servers.map((server, index) => (
<div key={index} className="mcp-stdio-server-item mb-4">
<div className="mcp-stdio-server-header">
<h4>MCP STDIO Server #{index + 1}</h4>
<button
type="button"
className="action-btn delete-btn"
onClick={() => handleRemoveMCPSTDIOServer(index)}
>
<i className="fas fa-times"></i>
</button>
</div>
<FormFieldDefinition
fields={getSTDIOServerFields()}
values={server}
onChange={(e) => handleFieldChange(index, e, true)}
idPrefix={`mcp_stdio_server_${index}_`}
/>
</div>
))}
<button
type="button"
className="action-btn"
onClick={handleAddMCPSTDIOServer}
>
<i className="fas fa-plus"></i> Add MCP STDIO Server
</button>
</div>
</div> </div>
); );
}; };