@@ -223,6 +223,44 @@ describe('DiscoveredMCPTool', () => {
223223 } ,
224224 ) ;
225225
226+ it ( 'should return a structured error if MCP tool reports a top-level isError (spec compliant)' , async ( ) => {
227+ const tool = new DiscoveredMCPTool (
228+ mockCallableToolInstance ,
229+ serverName ,
230+ serverToolName ,
231+ baseDescription ,
232+ inputSchema ,
233+ ) ;
234+ const params = { param : 'isErrorTopLevelCase' } ;
235+ const functionCall = {
236+ name : serverToolName ,
237+ args : params ,
238+ } ;
239+
240+ // Spec compliant error response: { isError: true } at the top level of content (or response object in this mapping)
241+ const errorResponse = { isError : true } ;
242+ const mockMcpToolResponseParts : Part [ ] = [
243+ {
244+ functionResponse : {
245+ name : serverToolName ,
246+ response : errorResponse ,
247+ } ,
248+ } ,
249+ ] ;
250+ mockCallTool . mockResolvedValue ( mockMcpToolResponseParts ) ;
251+ const expectedErrorMessage = `MCP tool '${ serverToolName } ' reported tool error for function call: ${ safeJsonStringify (
252+ functionCall ,
253+ ) } with response: ${ safeJsonStringify ( mockMcpToolResponseParts ) } `;
254+ const invocation = tool . build ( params ) ;
255+ const result = await invocation . execute ( new AbortController ( ) . signal ) ;
256+
257+ expect ( result . error ?. type ) . toBe ( ToolErrorType . MCP_TOOL_ERROR ) ;
258+ expect ( result . llmContent ) . toBe ( expectedErrorMessage ) ;
259+ expect ( result . returnDisplay ) . toContain (
260+ `Error: MCP tool '${ serverToolName } ' reported an error.` ,
261+ ) ;
262+ } ) ;
263+
226264 it . each ( [
227265 { isErrorValue : false , description : 'false (bool)' } ,
228266 { isErrorValue : 'false' , description : '"false" (str)' } ,
0 commit comments