From 0d9ceae1e38291035605613ab41a8f5e693d6fcd Mon Sep 17 00:00:00 2001 From: Gautam0507 <110854761+Gautam0507@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:30:18 +0530 Subject: [PATCH] ui: read structuredContent from MCP tool result when content is empty (#26691) --- tools/ui/src/lib/services/mcp.service.ts | 18 +++++++++++++++--- tools/ui/tests/unit/mcp-service.test.ts | 19 ++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/tools/ui/src/lib/services/mcp.service.ts b/tools/ui/src/lib/services/mcp.service.ts index 43f905c33..65e9e59d6 100644 --- a/tools/ui/src/lib/services/mcp.service.ts +++ b/tools/ui/src/lib/services/mcp.service.ts @@ -18,7 +18,8 @@ import { DEFAULT_CLIENT_VERSION, DEFAULT_IMAGE_MIME_TYPE, DEFAULT_MCP_CONFIG, - HEADERS + HEADERS, + NEWLINE } from '$lib/constants'; import { MCPConnectionPhase, @@ -70,6 +71,7 @@ interface ToolResultContentItem { interface ToolCallResult { content?: ToolResultContentItem[]; + structuredContent?: Record; isError?: boolean; _meta?: Record; } @@ -1012,10 +1014,20 @@ export class MCPService { if (!Array.isArray(content)) return ''; - return content + const formatted = content .map((item) => this.formatSingleContent(item)) .filter(Boolean) - .join('\n'); + .join(NEWLINE); + + if (formatted !== '') { + return formatted; + } + + if (result.structuredContent && typeof result.structuredContent === 'object') { + return JSON.stringify(result.structuredContent); + } + + return ''; } private static formatSingleContent(content: ToolResultContentItem): string { diff --git a/tools/ui/tests/unit/mcp-service.test.ts b/tools/ui/tests/unit/mcp-service.test.ts index 358881b47..97879f234 100644 --- a/tools/ui/tests/unit/mcp-service.test.ts +++ b/tools/ui/tests/unit/mcp-service.test.ts @@ -2,7 +2,7 @@ import { Client } from '@modelcontextprotocol/sdk/client'; import { CORS_PROXY } from '$lib/constants'; import { MCPConnectionPhase, MCPTransportType } from '$lib/enums'; import { MCPService } from '$lib/services/mcp.service'; -import type { MCPConnectionLog, MCPServerConfig } from '$lib/types'; +import type { MCPConnection, MCPConnectionLog, MCPServerConfig } from '$lib/types'; import { afterEach, describe, expect, it, vi } from 'vitest'; type DiagnosticFetchFactory = ( @@ -329,4 +329,21 @@ describe('MCPService', () => { ) ).toHaveLength(0); }); + + it('falls back to structuredContent when content array is empty', async () => { + const connection = { + client: { + callTool: vi.fn().mockResolvedValue({ + content: [], + structuredContent: { accounts: [{ id: 1 }], total: 1 } + }) + }, + requestTimeoutMs: 9000, + serverName: 'test-server' + } as unknown as MCPConnection; + const result = await MCPService.callTool(connection, { arguments: {}, name: 'tool' }); + + expect(result.isError).toBe(false); + expect(result.content).toBe('{"accounts":[{"id":1}],"total":1}'); + }); });