ui: read structuredContent from MCP tool result when content is empty (#26691)
This commit is contained in:
@@ -18,7 +18,8 @@ import {
|
|||||||
DEFAULT_CLIENT_VERSION,
|
DEFAULT_CLIENT_VERSION,
|
||||||
DEFAULT_IMAGE_MIME_TYPE,
|
DEFAULT_IMAGE_MIME_TYPE,
|
||||||
DEFAULT_MCP_CONFIG,
|
DEFAULT_MCP_CONFIG,
|
||||||
HEADERS
|
HEADERS,
|
||||||
|
NEWLINE
|
||||||
} from '$lib/constants';
|
} from '$lib/constants';
|
||||||
import {
|
import {
|
||||||
MCPConnectionPhase,
|
MCPConnectionPhase,
|
||||||
@@ -70,6 +71,7 @@ interface ToolResultContentItem {
|
|||||||
|
|
||||||
interface ToolCallResult {
|
interface ToolCallResult {
|
||||||
content?: ToolResultContentItem[];
|
content?: ToolResultContentItem[];
|
||||||
|
structuredContent?: Record<string, unknown>;
|
||||||
isError?: boolean;
|
isError?: boolean;
|
||||||
_meta?: Record<string, unknown>;
|
_meta?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
@@ -1012,10 +1014,20 @@ export class MCPService {
|
|||||||
|
|
||||||
if (!Array.isArray(content)) return '';
|
if (!Array.isArray(content)) return '';
|
||||||
|
|
||||||
return content
|
const formatted = content
|
||||||
.map((item) => this.formatSingleContent(item))
|
.map((item) => this.formatSingleContent(item))
|
||||||
.filter(Boolean)
|
.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 {
|
private static formatSingleContent(content: ToolResultContentItem): string {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Client } from '@modelcontextprotocol/sdk/client';
|
|||||||
import { CORS_PROXY } from '$lib/constants';
|
import { CORS_PROXY } from '$lib/constants';
|
||||||
import { MCPConnectionPhase, MCPTransportType } from '$lib/enums';
|
import { MCPConnectionPhase, MCPTransportType } from '$lib/enums';
|
||||||
import { MCPService } from '$lib/services/mcp.service';
|
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';
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
type DiagnosticFetchFactory = (
|
type DiagnosticFetchFactory = (
|
||||||
@@ -329,4 +329,21 @@ describe('MCPService', () => {
|
|||||||
)
|
)
|
||||||
).toHaveLength(0);
|
).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}');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user