Error Response Format

Our MCP implementation uses JSON-RPC 2.0 error format for all error conditions. Every error response contains structured information for programmatic handling.

Standard Error Structure

{
  "jsonrpc": "2.0",
  "id": "request-123",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "details": "Missing required parameter 'name'",
      "parameter": "name",
      "received": {}
    }
  }
}

Error Components

FieldTypeDescription
codeintegerStandard JSON-RPC error code
messagestringHuman-readable error description
dataobjectAdditional error context (optional)

Standard Error Codes

JSON-RPC Protocol Errors

CodeNameMeaningCommon Causes
-32700Parse errorInvalid JSONMalformed request body
-32600Invalid RequestInvalid JSON-RPCMissing required fields
-32601Method not foundUnknown methodTypo in method name
-32602Invalid paramsBad parametersWrong parameter types
-32603Internal errorServer errorUnexpected server failure

MCP-Specific Error Codes

CodeNameMeaningRecovery Strategy
-32000AuthenticationAuth failureRefresh token, reinitialize
-32001Resource not foundMissing resourceVerify resource exists
-32002Tool not foundUnknown toolCheck available tools

Detailed Error Examples

Authentication Errors

Expired Token:

{
  "jsonrpc": "2.0",
  "id": "tools-list-123",
  "error": {
    "code": -32000,
    "message": "Authentication failed",
    "data": {
      "error": "Token expired",
      "expires_at": "2024-01-15T10:30:00Z",
      "refresh_required": true
    }
  }
}

Invalid Session:

{
  "jsonrpc": "2.0",
  "id": "resource-read-456",
  "error": {
    "code": -32000,
    "message": "Authentication failed",
    "data": {
      "error": "Invalid session ID",
      "session_id": "invalid_session_123",
      "reinitialize_required": true
    }
  }
}

Parameter Validation Errors

Missing Required Parameter:

{
  "jsonrpc": "2.0",
  "id": "tool-call-789",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "parameter": "name",
      "error": "Missing required parameter",
      "expected": "string",
      "received": null
    }
  }
}

Invalid Parameter Type:

{
  "jsonrpc": "2.0",
  "id": "resource-read-101",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "parameter": "uri",
      "error": "Invalid parameter type",
      "expected": "string",
      "received": "number",
      "value": 123
    }
  }
}

Resource and Tool Errors

Tool Not Found:

{
  "jsonrpc": "2.0",
  "id": "tool-call-404",
  "error": {
    "code": -32002,
    "message": "Tool not found",
    "data": {
      "tool_name": "nonexistent_tool",
      "available_tools": ["get_contacts", "create_deal", "update_person"],
      "suggestion": "Check available tools with tools/list method"
    }
  }
}

Resource Not Found:

{
  "jsonrpc": "2.0",
  "id": "resource-read-404",
  "error": {
    "code": -32001,
    "message": "Resource not found",
    "data": {
      "uri": "pipedrive://invalid/resource",
      "error": "Resource does not exist or access denied",
      "available_resources": [
        "pipedrive://deals/schema",
        "pipedrive://contacts/list"
      ]
    }
  }
}

Rate Limiting Errors

Rate Limit Exceeded:

{
  "jsonrpc": "2.0",
  "id": "ping-rate-limited",
  "error": {
    "code": -32000,
    "message": "Request rate limit exceeded",
    "data": {
      "type": "rate_limit_exceeded",
      "retry_after": 60,
      "limit": 10,
      "remaining": 0,
      "reset_time": 1642248660
    }
  }
}

Error Recovery Strategies

Authentication Recovery

  1. Token Refresh: Use refresh token to obtain new access token
  2. Re-authentication: Redirect user through OAuth flow
  3. Session Reinitialize: Call initialize method with new token

Example Recovery Flow:

async function handleAuthError(error) {
  if (error.code === -32000) {
    if (error.data?.refresh_required) {
      // Attempt token refresh
      const newToken = await refreshAccessToken();
      return retryWithNewToken(newToken);
    }

    if (error.data?.reinitialize_required) {
      // Reinitialize session
      await initializeMCPSession();
      return retryOriginalRequest();
    }
  }

  throw error; // Unrecoverable auth error
}

Rate Limiting Recovery

Exponential Backoff:

async function handleRateLimit(error) {
  if (error.code === -32000 && error.data?.type === "rate_limit_exceeded") {
    const retryAfter = error.data.retry_after || 60;

    // Wait for retry period
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));

    // Retry original request
    return retryOriginalRequest();
  }

  throw error;
}

Resource/Tool Recovery

Fallback to Available Options:

async function handleResourceError(error) {
  if (error.code === -32001 || error.code === -32002) {
    const available =
      error.data?.available_tools || error.data?.available_resources;

    if (available && available.length > 0) {
      // Suggest alternative or prompt user to select
      return suggestAlternatives(available);
    }
  }

  throw error;
}

Error Prevention

Input Validation

Client-Side Validation:

function validateToolCall(toolName, arguments) {
  if (!toolName || typeof toolName !== "string") {
    throw new Error("Tool name must be a non-empty string");
  }

  if (arguments && typeof arguments !== "object") {
    throw new Error("Tool arguments must be an object");
  }

  return true;
}

Session Management

Session Health Checks:

class MCPSession {
  async ensureValidSession() {
    try {
      await this.ping();
    } catch (error) {
      if (error.code === -32000) {
        // Session invalid, reinitialize
        await this.initialize();
      } else {
        throw error;
      }
    }
  }
}

Request ID Management

Unique ID Generation:

class RequestIDManager {
  constructor() {
    this.usedIds = new Set();
  }

  generateUniqueId() {
    let id;
    do {
      id = `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    } while (this.usedIds.has(id));

    this.usedIds.add(id);
    return id;
  }

  markCompleted(id) {
    this.usedIds.delete(id);
  }
}

Error Monitoring

Error Logging

Structured Error Logging:

function logMCPError(error, context) {
  const logEntry = {
    timestamp: new Date().toISOString(),
    error_code: error.code,
    error_message: error.message,
    error_data: error.data,
    request_id: context.requestId,
    method: context.method,
    session_id: context.sessionId,
    user_id: context.userId,
  };

  console.error("MCP Error:", JSON.stringify(logEntry));

  // Send to monitoring service
  sendToMonitoring(logEntry);
}

Error Metrics

Track these error metrics for monitoring:

  • Error Rate: Percentage of requests resulting in errors
  • Error Types: Distribution of error codes
  • Recovery Success: Rate of successful error recovery
  • Session Health: Session initialization and failure rates

Best Practices

Error Handling Principles

  1. Graceful Degradation: Provide fallback functionality when possible
  2. User-Friendly Messages: Convert technical errors to user-readable messages
  3. Retry Logic: Implement appropriate retry strategies with backoff
  4. State Recovery: Maintain application state consistency during errors

Implementation Guidelines

  1. Always Check Error Codes: Don’t rely only on HTTP status codes
  2. Use Error Data: Leverage additional context in error data field
  3. Implement Timeouts: Set reasonable timeouts for all requests
  4. Log Context: Include request context in error logs

Testing Error Scenarios

Test these error conditions:

  • Network failures and timeouts
  • Authentication token expiration
  • Rate limit exceeded scenarios
  • Invalid parameter combinations
  • Resource/tool availability changes

This comprehensive error handling approach ensures robust, reliable integration with our MCP server implementation.