Open
Description
Describe the bug
When a tool with outputSchema is called, the server sdk checks the result to see if the structuredContent is correct. If not, throw an Error. This blocks tools from reporting error, as the tool can set the isError
property to true
to indicates any error. However the structuredContent checking is prioritized and always runs first.
To Reproduce
Steps to reproduce the behavior:
- create a MCP server
// server.mjs
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer(
{
name: "Basic Server",
version: "1.0.0",
},
{ capabilities: { tools: {} } }
);
server.registerTool(
"toolThatFails",
{
description: "A tool that fails",
outputSchema: {
test: z.string(),
},
},
async () => {
return {
content: [
{
type: "text",
text: "It is a message that reports error and should be sent to client",
},
],
isError: true,
};
}
);
const transport = new StdioServerTransport();
server.connect(transport);
- create an MCP client and call the tool
// client.mjs
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const client = new Client({
name: "Basic Client",
version: "1.0.0",
});
const transport = new StdioClientTransport({
command: "node",
args: ["server.mjs"],
});
await client.connect(transport);
console.log(await client.listTools());
console.log(
await client.callTool({
name: "toolThatFails",
})
);
Expected behavior
MCP client should receive the origin error that is reported by the MCP server.
Plus
I do not think it is a by design behavior, as the code in the client sdk side checks the isError
property first.