Skip to content

chore(settings): move mcp config to the MCP section and rework form - #400

Merged
mudler merged 2 commits into
mainfrom
chore/move-mcp-config
Feb 1, 2026
Merged

mudler merged 2 commits into
mainfrom
chore/move-mcp-config

Conversation

@mudler

@mudler mudler commented Feb 1, 2026

Copy link
Copy Markdown
Owner

this PR moves the MCP settings in advanced settings to the MCP, and builds a form for the MCP STDIO configuration rather than just letting the user to provide a JSON.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Copilot AI review requested due to automatic review settings February 1, 2026 17:23
@mudler
mudler merged commit c98178d into main Feb 1, 2026
5 checks passed
@mudler
mudler deleted the chore/move-mcp-config branch February 1, 2026 17:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the MCP (Model Context Protocol) configuration interface by moving MCP settings from the Advanced Settings section to a dedicated MCP section and replacing the raw JSON textarea with a structured form for STDIO server configuration.

Changes:

  • Moved mcp_stdio_servers and mcp_prepare_script fields from AdvancedSettings to MCP section in the backend metadata
  • Built a dynamic form UI for MCP STDIO servers with fields for name, command, args, and environment variables
  • Added visual separation between MCP STDIO servers and MCP HTTP servers with updated styling
  • Fixed a critical bug in AgentForm.jsx where handleInputChange was incorrectly accessing e.target.name.target
  • Enhanced Docker configuration with explicit TCP daemon settings
  • Added SELinux volume mount compatibility in Makefile

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
webui/react-ui/src/components/agent-form-sections/MCPServersSection.jsx Adds structured form for MCP STDIO servers with JSON parsing/building functions and CRUD operations for servers, args, and env vars
webui/react-ui/src/components/AgentForm.jsx Fixes critical bug in handleInputChange and passes additional props to MCPServersSection
webui/react-ui/src/App.css Adds CSS styling to visually separate MCP STDIO and HTTP server blocks
docker-compose.yaml Makes Docker daemon TCP configuration explicit with command and expose directives
core/state/config.go Moves MCP fields to MCP section and adds Name field support in JSON marshal/unmarshal
core/agent/mcp.go Adds Name field to MCPSTDIOServer struct
Makefile Adds :z flag to Docker volume mount for SELinux compatibility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +124 to +126
const val = env[oldKey];
delete env[oldKey];
env[newKey || oldKey] = val;

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updateEnvKey function has a potential issue when renaming environment variable keys. If newKey is empty or already exists, it will overwrite or create an unexpected key. Consider validating that newKey is non-empty and doesn't already exist in the env object before performing the rename operation.

Suggested change
const val = env[oldKey];
delete env[oldKey];
env[newKey || oldKey] = val;
if (!Object.prototype.hasOwnProperty.call(env, oldKey)) {
// Nothing to rename if the old key does not exist
return;
}
// Validate the new key: it must be non-empty and must not collide with an existing key
if (!newKey || newKey === oldKey || Object.prototype.hasOwnProperty.call(env, newKey)) {
// Invalid or colliding new key; do not modify env
return;
}
const val = env[oldKey];
delete env[oldKey];
env[newKey] = val;

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +108
const addEnv = (serverIndex, key = '', value = '') => {
const server = stdioList[serverIndex];
if (!server) return;
const env = { ...(server.env || {}), [key || `key_${Date.now()}`]: value };

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addEnv function generates a timestamp-based key (key_${Date.now()}) when the key parameter is empty. This could lead to key collisions if multiple environment variables are added rapidly (within the same millisecond). Consider using a more robust unique identifier generation or checking for existing keys to ensure uniqueness.

Suggested change
const addEnv = (serverIndex, key = '', value = '') => {
const server = stdioList[serverIndex];
if (!server) return;
const env = { ...(server.env || {}), [key || `key_${Date.now()}`]: value };
const generateUniqueEnvKey = (existingEnv) => {
const base = 'key_';
let suffix = 0;
let candidate;
do {
candidate = `${base}${Date.now()}_${suffix++}`;
} while (
existingEnv &&
Object.prototype.hasOwnProperty.call(existingEnv, candidate)
);
return candidate;
};
const addEnv = (serverIndex, key = '', value = '') => {
const server = stdioList[serverIndex];
if (!server) return;
const existingEnv = server.env || {};
const trimmedKey = key.trim();
const keyToUse = trimmedKey ? trimmedKey : generateUniqueEnvKey(existingEnv);
const env = { ...existingEnv, [keyToUse]: value };

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +28
let key = (item.name && item.name.trim()) ? item.name.trim() : `server${index}`;
while (usedKeys.has(key)) {
key = `${key}_${index}`;

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key collision resolution in buildStdioJson has a critical bug. When a collision is detected on line 27, the while loop on line 27 keeps appending the same _${index} suffix repeatedly, which will result in an infinite loop if there's a collision. For example, if "myserver" exists and you try to add another "myserver" at index 1, it will try "myserver_1", then "myserver_1_1", then "myserver_1_1_1" indefinitely. Instead, use a counter variable that increments each iteration to ensure uniqueness.

Suggested change
let key = (item.name && item.name.trim()) ? item.name.trim() : `server${index}`;
while (usedKeys.has(key)) {
key = `${key}_${index}`;
const baseKey = (item.name && item.name.trim()) ? item.name.trim() : `server${index}`;
let key = baseKey;
let suffix = 1;
while (usedKeys.has(key)) {
key = `${baseKey}_${suffix}`;
suffix += 1;

Copilot uses AI. Check for mistakes.

// Handle MCP configuration field value changes (FormField passes the event)
const handleMCPFieldChange = (e) => {
const { name, value, type, checked } = e.target;

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable type.

Suggested change
const { name, value, type, checked } = e.target;
const { name, value, checked } = e.target;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants