mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-09 06:15:41 -05:00
fix(frontend/mcp): Remove broken credentials widget and disable auto-connect
- Remove credentials field from MCP dynamic schema since auth is handled by the dialog's OAuth flow (the standard credentials widget doesn't support MCP as a provider and fails with 404) - Simplify FormCreator MCP handling — all form fields are tool arguments - Disable auto-connect on dialog open; pre-fill last URL instead so user can edit before connecting
This commit is contained in:
@@ -9,30 +9,22 @@ import { SpecialBlockID } from "@/lib/autogpt-server-api";
|
||||
* Build a dynamic input schema for MCP blocks.
|
||||
*
|
||||
* When a tool has been selected (tool_input_schema is populated), the block
|
||||
* should render:
|
||||
* 1. The credentials field (from the static schema)
|
||||
* 2. The selected tool's input parameters (from tool_input_schema)
|
||||
* renders only the selected tool's input parameters. Credentials are NOT
|
||||
* included because authentication is already handled by the MCP dialog's
|
||||
* OAuth flow and stored server-side.
|
||||
*
|
||||
* Static fields like server_url, selected_tool, available_tools, and
|
||||
* tool_arguments are hidden because they're pre-configured from the dialog.
|
||||
*/
|
||||
function buildMCPInputSchema(
|
||||
staticSchema: Record<string, any>,
|
||||
toolInputSchema: Record<string, any>,
|
||||
): Record<string, any> {
|
||||
const credentialsProp = staticSchema.properties?.credentials;
|
||||
const staticRequired = staticSchema.required ?? [];
|
||||
|
||||
return {
|
||||
type: "object",
|
||||
properties: {
|
||||
...(credentialsProp ? { credentials: credentialsProp } : {}),
|
||||
...(toolInputSchema.properties ?? {}),
|
||||
},
|
||||
required: [
|
||||
...staticRequired.filter((r: string) => r === "credentials"),
|
||||
...(toolInputSchema.required ?? []),
|
||||
],
|
||||
required: [...(toolInputSchema.required ?? [])],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,10 +50,7 @@ export const useCustomNode = ({
|
||||
const currentInputSchema = isAgent
|
||||
? (data.hardcodedValues.input_schema ?? {})
|
||||
: isMCPWithTool
|
||||
? buildMCPInputSchema(
|
||||
data.inputSchema,
|
||||
data.hardcodedValues.tool_input_schema,
|
||||
)
|
||||
? buildMCPInputSchema(data.hardcodedValues.tool_input_schema)
|
||||
: data.inputSchema;
|
||||
const currentOutputSchema = isAgent
|
||||
? (data.hardcodedValues.output_schema ?? {})
|
||||
|
||||
@@ -44,12 +44,10 @@ export const FormCreator: React.FC<FormCreatorProps> = React.memo(
|
||||
inputs: formData,
|
||||
};
|
||||
} else if (isMCPWithTool) {
|
||||
// Separate credentials from tool arguments
|
||||
const { credentials, ...toolArgs } = formData;
|
||||
// All form fields are tool arguments (credentials handled by dialog)
|
||||
updatedValues = {
|
||||
...getHardCodedValues(nodeId),
|
||||
...(credentials ? { credentials } : {}),
|
||||
tool_arguments: toolArgs,
|
||||
tool_arguments: formData,
|
||||
};
|
||||
} else {
|
||||
updatedValues = formData;
|
||||
@@ -64,13 +62,7 @@ export const FormCreator: React.FC<FormCreatorProps> = React.memo(
|
||||
if (isAgent) {
|
||||
initialValues = hardcodedValues.inputs ?? {};
|
||||
} else if (isMCPWithTool) {
|
||||
// Merge credentials + tool_arguments for the combined schema
|
||||
initialValues = {
|
||||
...(hardcodedValues.credentials
|
||||
? { credentials: hardcodedValues.credentials }
|
||||
: {}),
|
||||
...(hardcodedValues.tool_arguments ?? {}),
|
||||
};
|
||||
initialValues = hardcodedValues.tool_arguments ?? {};
|
||||
} else {
|
||||
initialValues = hardcodedValues;
|
||||
}
|
||||
|
||||
@@ -222,20 +222,17 @@ export const CustomNode = React.memo(
|
||||
!!data.hardcodedValues?.tool_input_schema?.properties;
|
||||
|
||||
if (isMCPWithTool) {
|
||||
const credentialsProp = data.inputSchema?.properties?.credentials;
|
||||
// Show only the tool's input parameters. Credentials are NOT included
|
||||
// because authentication is handled by the MCP dialog's OAuth flow
|
||||
// and stored server-side.
|
||||
const toolSchema = data.hardcodedValues.tool_input_schema;
|
||||
const staticRequired = data.inputSchema?.required ?? [];
|
||||
|
||||
data.inputSchema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
...(credentialsProp ? { credentials: credentialsProp } : {}),
|
||||
...(toolSchema.properties ?? {}),
|
||||
},
|
||||
required: [
|
||||
...staticRequired.filter((r: string) => r === "credentials"),
|
||||
...(toolSchema.required ?? []),
|
||||
],
|
||||
required: [...(toolSchema.required ?? [])],
|
||||
} as BlockIORootSchema;
|
||||
}
|
||||
|
||||
@@ -562,8 +559,7 @@ export const CustomNode = React.memo(
|
||||
default:
|
||||
const getInputPropKey = (key: string) => {
|
||||
if (nodeType == BlockUIType.AGENT) return `inputs.${key}`;
|
||||
if (isMCPWithTool && key !== "credentials")
|
||||
return `tool_arguments.${key}`;
|
||||
if (isMCPWithTool) return `tool_arguments.${key}`;
|
||||
return key;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,33 +66,21 @@ export function MCPToolDialog({
|
||||
const oauthHandledRef = useRef(false);
|
||||
const autoConnectAttemptedRef = useRef(false);
|
||||
|
||||
// Attempt auto-connect when dialog opens with a stored server URL
|
||||
// Pre-fill last used server URL when dialog opens (without auto-connecting)
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
autoConnectAttemptedRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const lastUrl = localStorage.getItem(STORAGE_KEY);
|
||||
if (!lastUrl || autoConnectAttemptedRef.current) return;
|
||||
if (autoConnectAttemptedRef.current) return;
|
||||
autoConnectAttemptedRef.current = true;
|
||||
|
||||
setServerUrl(lastUrl);
|
||||
setLoading(true);
|
||||
api
|
||||
.mcpDiscoverTools(lastUrl)
|
||||
.then((result) => {
|
||||
setTools(result.tools);
|
||||
setServerName(result.server_name);
|
||||
setStep("tool");
|
||||
})
|
||||
.catch(() => {
|
||||
// Stored credential expired or server changed — stay on URL step
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, [open, api]);
|
||||
const lastUrl = localStorage.getItem(STORAGE_KEY);
|
||||
if (lastUrl) {
|
||||
setServerUrl(lastUrl);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
// Clean up listeners on unmount
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user