diff --git a/client/src/components/DynamicJsonForm.tsx b/client/src/components/DynamicJsonForm.tsx index 96b03b3a4..685401ab9 100644 --- a/client/src/components/DynamicJsonForm.tsx +++ b/client/src/components/DynamicJsonForm.tsx @@ -113,8 +113,8 @@ const DynamicJsonForm = forwardRef( setJsonError(errorMessage); // Reset to default for clearly invalid JSON (not just incomplete typing) - const trimmed = jsonString.trim(); - if (trimmed.length > 5 && !trimmed.match(/^[\s[{]/)) { + const trimmed = jsonString?.trim(); + if (trimmed && trimmed.length > 5 && !trimmed.match(/^[\s[{]/)) { onChange(generateDefaultValue(schema)); } } @@ -155,7 +155,7 @@ const DynamicJsonForm = forwardRef( const formatJson = () => { try { - const jsonStr = rawJsonValue.trim(); + const jsonStr = rawJsonValue?.trim(); if (!jsonStr) { return; } @@ -171,7 +171,7 @@ const DynamicJsonForm = forwardRef( const validateJson = () => { if (!isJsonMode) return { isValid: true, error: null }; try { - const jsonStr = rawJsonValue.trim(); + const jsonStr = rawJsonValue?.trim(); if (!jsonStr) return { isValid: true, error: null }; const parsed = JSON.parse(jsonStr); // Clear any pending debounced update and immediately update parent diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index b8c163a2f..26f988e9b 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -194,16 +194,18 @@ const ToolsTab = ({ ...params, [key]: checked ? null - : prop.default !== null - ? prop.default - : prop.type === "boolean" - ? false - : prop.type === "string" - ? "" - : prop.type === "number" || - prop.type === "integer" - ? undefined - : undefined, + : prop.type === "array" + ? undefined + : prop.default !== null + ? prop.default + : prop.type === "boolean" + ? false + : prop.type === "string" + ? "" + : prop.type === "number" || + prop.type === "integer" + ? undefined + : undefined, }) } /> diff --git a/client/src/utils/jsonUtils.ts b/client/src/utils/jsonUtils.ts index f83789668..334dafc24 100644 --- a/client/src/utils/jsonUtils.ts +++ b/client/src/utils/jsonUtils.ts @@ -85,8 +85,9 @@ export function tryParseJson(str: string): { success: boolean; data: JsonValue; } { - const trimmed = str.trim(); + const trimmed = str?.trim(); if ( + trimmed && !(trimmed.startsWith("{") && trimmed.endsWith("}")) && !(trimmed.startsWith("[") && trimmed.endsWith("]")) ) { diff --git a/client/src/utils/schemaUtils.ts b/client/src/utils/schemaUtils.ts index 5beb25e2f..365870216 100644 --- a/client/src/utils/schemaUtils.ts +++ b/client/src/utils/schemaUtils.ts @@ -235,6 +235,16 @@ export function normalizeUnionType(schema: JsonSchemaType): JsonSchemaType { return { ...schema, type: "integer", anyOf: undefined, nullable: true }; } + // Handle anyOf with exactly array and null (FastMCP pattern) + if ( + schema.anyOf && + schema.anyOf.length === 2 && + schema.anyOf.some((t) => (t as JsonSchemaType).type === "array") && + schema.anyOf.some((t) => (t as JsonSchemaType).type === "null") + ) { + return { ...schema, type: "array", anyOf: undefined, nullable: true }; + } + // Handle array type with exactly string and null if ( Array.isArray(schema.type) &&