diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/mcp-server-form-modal/mcp-server-form-modal.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/mcp-server-form-modal/mcp-server-form-modal.tsx index 9c93dd8fa01..fe6d59e0967 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/mcp-server-form-modal/mcp-server-form-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/mcp-server-form-modal/mcp-server-form-modal.tsx @@ -157,7 +157,7 @@ function FormattedInput({ onChange={onChange} onScroll={handleScroll} onInput={handleScroll} - inputClassName='text-transparent caret-[var(--text-primary)]' + inputClassName='font-medium font-sans text-transparent caret-[var(--text-primary)]' />
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx index 5fa807b3f73..3994248ef6d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mcp-dynamic-args/mcp-dynamic-args.tsx @@ -15,6 +15,33 @@ import { formatParameterLabel } from '@/tools/params' const logger = createLogger('McpDynamicArgs') +/** + * The dropdown UI renders each enum member as a string label/value, so it can only + * represent JSON Schema enums whose members are primitives — a non-primitive member + * (object/array) would collapse to "[object Object]" and lose its identity. Callers + * route a non-primitive enum to the JSON editor (`long-input`) instead. + */ +function isPrimitiveEnum( + enumValues: unknown +): enumValues is Array { + return ( + Array.isArray(enumValues) && + enumValues.every((value) => value === null || typeof value !== 'object') + ) +} + +/** + * True when the schema's actual value must be a JSON object/array (a plain + * object/array type, or a non-primitive enum member) rather than a string. + */ +function requiresJsonValue(paramSchema: any): boolean { + return ( + paramSchema.type === 'object' || + paramSchema.type === 'array' || + (Array.isArray(paramSchema.enum) && !isPrimitiveEnum(paramSchema.enum)) + ) +} + interface McpDynamicArgsProps { blockId: string subBlockId: string @@ -116,7 +143,9 @@ export function McpDynamicArgs({ ) const getInputType = (paramSchema: any) => { - if (paramSchema.enum) return 'dropdown' + if (Array.isArray(paramSchema.enum)) { + return isPrimitiveEnum(paramSchema.enum) ? 'dropdown' : 'long-input' + } if (paramSchema.type === 'boolean') return 'switch' if (paramSchema.type === 'number' || paramSchema.type === 'integer') { if (paramSchema.minimum !== undefined && paramSchema.maximum !== undefined) { @@ -241,6 +270,8 @@ export function McpDynamicArgs({ case 'long-input': { const config = createParamConfig(paramName, paramSchema, 'long-input') + const displayValue = + typeof value === 'string' || value == null ? value || '' : JSON.stringify(value) return ( updateParameter(paramName, newValue)} + value={displayValue} + onChange={(newValue) => { + if (!requiresJsonValue(paramSchema)) { + updateParameter(paramName, newValue) + return + } + try { + updateParameter(paramName, JSON.parse(newValue)) + } catch { + updateParameter(paramName, newValue) + } + }} isPreview={isPreview} disabled={disabled} workflowSearchValuePath={[paramName]} diff --git a/apps/sim/lib/api/contracts/mcp.ts b/apps/sim/lib/api/contracts/mcp.ts index dfcddac85ad..1c0159e9ec2 100644 --- a/apps/sim/lib/api/contracts/mcp.ts +++ b/apps/sim/lib/api/contracts/mcp.ts @@ -50,10 +50,12 @@ export const mcpToolSchemaPropertySchema: z.ZodType = z.l .object({ type: z.union([z.string(), z.array(z.string())]).optional(), description: z.string().optional(), - items: mcpToolSchemaPropertySchema.optional(), + items: z + .union([mcpToolSchemaPropertySchema, z.array(mcpToolSchemaPropertySchema)]) + .optional(), properties: z.record(z.string(), mcpToolSchemaPropertySchema).optional(), required: z.array(z.string()).optional(), - enum: z.array(z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(), + enum: z.array(z.unknown()).optional(), default: z.unknown().optional(), }) .passthrough() diff --git a/apps/sim/lib/mcp/types.ts b/apps/sim/lib/mcp/types.ts index be506fd5b07..575e86ea2f8 100644 --- a/apps/sim/lib/mcp/types.ts +++ b/apps/sim/lib/mcp/types.ts @@ -68,10 +68,10 @@ export interface McpSecurityPolicy { export interface McpToolSchemaProperty { type?: string | string[] description?: string - items?: McpToolSchemaProperty + items?: McpToolSchemaProperty | McpToolSchemaProperty[] properties?: Record required?: string[] - enum?: Array + enum?: unknown[] default?: unknown [key: string]: unknown }