Skip to content

1. Structured Error Responses for MCP Tools

This module, is mainly about this distinction:

Use JSON-RPC protocol errors when the MCP protocol call itself is invalid. Use isError: true tool results when the tool was invoked correctly but the operation failed.

1.1 Transient Errors

A transient error means the request itself is valid, but some temporary system condition prevented the tool from completing.

Examples:

Timeout
Service unavailable
Database overloaded
Rate limit
Temporary network failure
Upstream API not responding

Agent behavior:

Retry, usually with backoff. 
Do not ask the user to fix input. 
Do not immediately escalate unless retries fail.

Example response:

{  
    "isError": true,  
    "errorCategory": "transient",  
    "isRetryable": true,  
    "description": "The order database timed out after 5 seconds. The request is valid and may succeed if retried after a short delay."
}

Heuristic:

If the system is temporarily unavailable but the user’s request is valid, classify it as transient.


1.2 Validation Errors

A validation error means the tool received invalid or malformed input.

Examples:

Invalid date format
Missing required field
Wrong ID format
Amount is negative
Enum value is not allowed
Date range has start_date after end_date

Agent behavior:

Fix the input and retry.
Do not blindly retry the same call.
Ask the user only if the correct value cannot be inferred.

Example:

{  
    "isError": true,  
    "errorCategory": "validation",  
    "isRetryable": true,  
    "description": "Order ID must be in format #NNNNN, such as #12345. Received 'order-abc'. Reformat the order ID and retry."
}

Heuristic:

isRetryable: true here means to retry after correction, not “retry the exact same request.”


1.3 Business Errors

A business error means the request is technically valid, but it violates a business rule, policy, or domain constraint.

Examples:

Refund exceeds automatic limit
Order cannot be cancelled after shipment
Customer is outside the return window
Discount is not allowed for this plan
Account cannot be deleted while invoices are unpaid

Agent behavior:

Do not retry.
Explain the rule in customer-friendly language.
Use an alternative workflow, such as escalation or manager approval.

Example:

{  
    "isError": true,  
    "errorCategory": "business",  
    "isRetryable": false,  
    "description": "The requested refund of $750 exceeds the $500 automatic refund limit. Retrying will not succeed. Escalate to a manager for approval."
}

Heuristic:

If the same request will fail every time because of policy, it is business, not transient.


1.4 Permission Errors

A permission error means the tool cannot complete because the caller lacks the required access.

Examples:

Insufficient role
Missing OAuth scope
Service account lacks access
User cannot view financial records
Credential expired or invalid

Agent behavior:

Do not retry with the same credentials.
Ask for elevated access, use an approved alternate credential path, or escalate.
Do not reveal sensitive data.

Example:

{  
    "isError": true,  
    "errorCategory": "permission",  
    "isRetryable": false,  
    "description": "The current user does not have permission to access financial records. Request elevated access or escalate to a user with financial-system permissions."
}


2. Use the Canonical Error Fields

The official document specifically calls out these fields:

{
  "isError": true,
  "errorCategory": "transient | validation | business | permission",
  "isRetryable": true,
  "description": "Human-readable explanation and recovery guidance"
}

You can and should still add richer metadata, but do not miss those three.

2.1 Subagent Local Recovery

The official statement makes this a skill-level requirement. Add this directly to your guide:

Subagents should handle transient failures locally when possible. 
Only unrecoverable errors should be propagated to the coordinator. 
When propagating, include partial results and what was attempted.

Example:

{  
    "isError": true,  
    "errorCategory": "transient",  
    "isRetryable": false,  
    "description": "Research subagent retried two sources continued timing out.",  
    "partialResults": [    
        {      
            "source": "knowledge_base",      
            "status": "success",      
            "resultCount": 4    
        },    
        {      
            "source": "support_tickets",      
            "status": "success",      
            "resultCount": 2    
        }  
    ],  
    "attempted": [    
        "Searched knowledge_base once: succeeded",    
        "Searched support_tickets once: succeeded",    
        "Searched web_search three times: timed out each time"  
    ]
}

The coordinator can then decide:

Proceed with partial results.Ask the user whether partial results are acceptable.
Try an alternate tool.Escalate.Report that some sources could not be checked.

Bad pattern:

{  
    "isError": false,  
    "content": [    
        {      
            "type": "text",      
            "text": "No results found."    
        }  
    ]
}

When the subagent failed to search some sources. That hides failure and creates false confidence.


3. MCP Envelope for Structured Errors

MCP tool results can include structuredContent, and if a tool returns structured content, the spec says it should also return serialized JSON in a text content block for backward compatibility.

Tools can define an outputSchema, and when they do, structured results must conform to that schema. (Model Context Protocol)

A strong MCP-style tool execution error:

{
  "jsonrpc": "2.0",
  "id": 12,
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "{\"ok\":false,\"error\":{\"code\":\"INVALID_DATE_RANGE\",\"category\":\"validation\",\"message\":\"start_date must be before end_date.\",\"recoverable\":true,\"automatic_retry_allowed\":true,\"suggested_action\":\"Retry with start_date earlier than end_date.\",\"example_arguments\":{\"start_date\":\"2026-07-01\",\"end_date\":\"2026-07-10\"}}}"
      }
    ],
    "structuredContent": {
      "ok": false,
      "error": {
        "code": "INVALID_DATE_RANGE",
        "category": "validation",
        "message": "start_date must be before end_date.",
        "recoverable": true,
        "automatic_retry_allowed": true,
        "suggested_action": "Retry with start_date earlier than end_date.",
        "example_arguments": {
          "start_date": "2026-07-01",
          "end_date": "2026-07-10"
        }
      }
    }
  }
}

3.1Output Schema Must Also Allow Error Shape

If your tool has an outputSchema that only describes success output, then returning error-shaped structuredContent may violate that schema. Better options:

  1. Define a union-like schema that supports both success and error results.
  2. Return error details in content only.
  3. Use a consistent result envelope where both success and failure conform to the same schema.

Recommended pattern:

{
  "ok": true,
  "data": {
    "ticket_id": "SUP-1042",
    "status": "open"
  },
  "error": null
}

or:

{
  "ok": false,
  "data": null,
  "error": {
    "code": "TICKET_NOT_FOUND",
    "category": "not_found",
    "message": "No support ticket exists with ID SUP-9999.",
    "recoverable": true,
    "suggested_action": "Search tickets by customer or keyword."
  }
}


4. Bad Vs Good Examples

4.1 Bad: Protocol Error for a Normal Validation Failure

{
  "jsonrpc": "2.0",
  "id": 8,
  "error": {
    "code": -32602,
    "message": "Invalid date"
  }
}

Why this is weak:

The tool exists.
The tool handler received the call.
The date failed business/input validation.
Claude could fix it if told the expected format.
Therefore this should be an isError: true tool result.

4.2 Good

{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "{\"ok\":false,\"error\":{\"code\":\"INVALID_DATE\",\"category\":\"validation\",\"message\":\"updated_after must be an ISO date in YYYY-MM-DD format.\",\"recoverable\":true,\"automatic_retry_allowed\":true,\"suggested_action\":\"Retry using a date such as 2026-06-01.\",\"example_arguments\":{\"updated_after\":\"2026-06-01\"}}}"
      }
    ]
  }
}

5. Security and Privacy Rules

Structured errors should be helpful, but not leaky.

Do not return:

Stack traces
Database queries
Access tokens
API keys
Raw upstream request headers
Sensitive customer data
Full permission policy internals
Private infrastructure names unless necessary

Better:

{
  "ok": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "category": "internal",
    "message": "The operation failed due to an internal server error.",
    "recoverable": true,
    "automatic_retry_allowed": false,
    "suggested_action": "Do not retry repeatedly. Report the correlation ID to support.",
    "correlation_id": "err_01HX8QR2J9"
  }
}

Heuristic:

Use logs for developer diagnostics; use structured error responses for agent recovery.


6. Decision Table

Scenario Best answer
Request malformed against tools/call schema JSON-RPC protocol error
Missing required business field isError: true with validation error
Date format wrong isError: true with expected format and example
User lacks permission isError: true, no automatic retry
User has not confirmed destructive action isError: true, ask user for confirmation
Upstream API rate limited isError: true, include retry guidance
Upstream timeout isError: true, include retry guidance and correlation ID
Tool returns partial results Usually isError: false with warnings, or isError: true if task cannot be completed
Internal exception Sanitized isError: true or protocol error only if execution could not be safely represented
Output has structuredContent Ensure it conforms to outputSchema if one exists

D2.2 mental model

For this module, think like this:

MCP protocol errors help clients debug broken calls.
MCP tool execution errors help Claude recover from failed operations.

The best exam answers make errors:

Structured
Actionable
Recoverable where appropriate
Safe to expose to the model
Consistent across tools
Clear about whether to retry, ask the user, try another tool, or stop
Test yourself on this topic Interactive questions for Task 2.2 — Structured Error Responses, with instant explanations and scoring.
Start quiz →