Skip to content

McpToolResponse.isError is dropped before MCP tool result reaches the client #444

Description

McpToolResponse accepts isError: true, but the Node.js worker conversion path appears to drop that field before the result is sent to the Azure Functions MCP extension. As a result, MCP clients receive a
successful tools/call result instead of a tool-error result.

Environment

  • @azure/functions: 4.16.0
  • Azure Functions MCP extension: observed with extension bundle preview using MCP extension 1.5.0
  • Runtime: Node.js Azure Functions app using app.mcpTool(...)

Reproduction

Return an MCP tool response with isError: true:

return new McpToolResponse({
  content: [
    new McpTextContent("Invalid file")
  ],
  isError: true,
});

The public type supports this:

export interface McpToolResponseInit {
  content: McpContentBlock[];
  structuredContent?: unknown;
  isError?: boolean;
}

But toMcpToolResult() serializes only type, content, and optional structuredContent:

const out: McpToolResult = { type, content: contentStr };

if (response.structuredContent !== undefined && response.structuredContent !== null) {
  out.structuredContent =
    typeof response.structuredContent === "string"
      ? response.structuredContent
      : JSON.stringify(response.structuredContent);
}

return out;

Actual Behavior

A handler-level error response reaches the MCP client like this:

{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Invalid file"
      }
    ]
  },
  "id": 5,
  "jsonrpc": "2.0"
}

There is no isError field.

Expected Behavior

The client-visible MCP result should include:

{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Invalid file"
      }
    ],
    "isError": true
  },
  "id": 5,
  "jsonrpc": "2.0"
}

Per the MCP schema, missing isError defaults to false, so clients currently treat handler-level tool errors as successful tool results.

Spec reference: https://modelcontextprotocol.io/specification/2025-06-18/schema#tools-call

Notes

I'm unsure if this would best be solved in the node library, or in the extension handler same way _meta is (in preview builds)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions