fix(mcp): prefer content over structured output (#34505)
This commit is contained in:
@@ -72,7 +72,7 @@ export function convertTool(mcpTool: MCPToolDef, client: Client, timeout?: numbe
|
|||||||
.filter((text) => text.trim())
|
.filter((text) => text.trim())
|
||||||
.join("\n\n") || "MCP tool returned an error",
|
.join("\n\n") || "MCP tool returned an error",
|
||||||
)
|
)
|
||||||
if (result.structuredContent === undefined || result.structuredContent === null) return result
|
if (result.content.length > 0 || result.structuredContent === undefined || result.structuredContent === null) return result
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
content: [{ type: "text" as const, text: JSON.stringify(result.structuredContent) }],
|
content: [{ type: "text" as const, text: JSON.stringify(result.structuredContent) }],
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js"
|
||||||
|
import { McpCatalog } from "@/mcp/catalog"
|
||||||
|
|
||||||
|
const options = { toolCallId: "call_mcp", abortSignal: new AbortController().signal } as any
|
||||||
|
|
||||||
|
function clientReturning(result: unknown) {
|
||||||
|
return {
|
||||||
|
callTool: async () => result,
|
||||||
|
} as unknown as Client
|
||||||
|
}
|
||||||
|
|
||||||
|
function mcpTool() {
|
||||||
|
return {
|
||||||
|
name: "screenshot",
|
||||||
|
description: "Take a screenshot",
|
||||||
|
inputSchema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {},
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
} as any
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("McpCatalog.convertTool", () => {
|
||||||
|
test("preserves content when structuredContent is also present", async () => {
|
||||||
|
const content = [{ type: "image" as const, mimeType: "image/png", data: "AAAA" }]
|
||||||
|
const structuredContent = { image: { mimeType: "image/png", data: "AAAA" } }
|
||||||
|
const converted = McpCatalog.convertTool(mcpTool(), clientReturning({ content, structuredContent }))
|
||||||
|
|
||||||
|
const output = await converted.execute?.({}, options)
|
||||||
|
|
||||||
|
expect(output).toMatchObject({ content, structuredContent })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("falls back to structuredContent only when content is absent", async () => {
|
||||||
|
const structuredContent = { results: [{ title: "one" }] }
|
||||||
|
const converted = McpCatalog.convertTool(mcpTool(), clientReturning({ content: [], structuredContent }))
|
||||||
|
|
||||||
|
const output = await converted.execute?.({}, options)
|
||||||
|
|
||||||
|
expect(output).toMatchObject({
|
||||||
|
structuredContent,
|
||||||
|
content: [{ type: "text", text: JSON.stringify(structuredContent) }],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user