diff --git a/src/core/FormatConverter.js b/src/core/FormatConverter.js index 89599d7f..50a706bb 100644 --- a/src/core/FormatConverter.js +++ b/src/core/FormatConverter.js @@ -174,6 +174,56 @@ class FormatConverter { try { responseContent = typeof message.content === "string" ? JSON.parse(message.content) : message.content; + + // Handle array format (common in MCP, e.g., [{ type: "text", text: "..." }]) + // Gemini requires 'response' to be an object (Struct), not an array. + if (Array.isArray(responseContent)) { + // 1. Process ALL items (text, image, etc.) + const processedItems = responseContent.map(item => { + if (item.type === "text" && typeof item.text === "string") { + try { + const parsed = JSON.parse(item.text); + // Robustness Check: Only unwrap if it's a bare object (not null, not array, not primitive) + // This prevents "123" or "true" or "[]" from becoming inconsistent types in the list + if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) { + return parsed; + } + // If it's a primitive or array, keep it wrapped as text to avoid structure confusion + return { content: item.text, type: "text" }; + } catch { + return { content: item.text, type: "text" }; // Wrap raw text + } + } + return item; // Keep other types (e.g. image) as is + }); + + if (processedItems.length > 0) { + // 2. Determine structure + if ( + processedItems.length === 1 && + typeof processedItems[0] === "object" && + !Array.isArray(processedItems[0]) && + processedItems[0] !== null + ) { + // Single object: use it directly as the root response (Best for standard MCP) + responseContent = processedItems[0]; + } else { + // Multiple/Mixed items configuration + responseContent = { result: JSON.stringify(processedItems) }; + this.logger.info( + `[Adapter] Multiple tool response items found (${processedItems.length}). Wrapping in JSON string to preserve all data.` + ); + } + } else { + // Empty array or unforeseen structure + // To keep behavior consistent with the multiple-items case, stringify the array + // (e.g. returns { result: "[]" }) + responseContent = { result: JSON.stringify(responseContent) }; + this.logger.info( + `[Adapter] Empty/Unforeseen tool response structure. Wrapping in JSON string: ${JSON.stringify(responseContent)}` + ); + } + } } catch (e) { // If content is not valid JSON, wrap it responseContent = { result: message.content };