Back to Blog

MCP Error Codes

Emmanuel Oyibo
GuideMCPErrorsDebuggingTroubleshootingAPIError Codes

If you've worked with APIs before, you know that error codes can feel like cryptic messages from another dimension. The Model Context Protocol (MCP) uses a well-structured error code system that, once understood, makes debugging significantly easier. Let's explore these error codes and what they tell you about your MCP integrations.

Error Code Structure in MCP

MCP builds on JSON-RPC 2.0 for its error representation. When something goes wrong, you receive an error object structured like this:

{
  jsonrpc: "2.0",
  id: string | number | null,
  error: {
    code: number,       
    message: string,
    data?: unknown
  }
}

The code field contains the numeric identifier that categorizes the error type. Think of it as the error's fingerprint, and a specific number means a specific problem. The message field gives you a human-readable explanation, while the data field offers additional context to help diagnose and fix the issue.

Standard JSON-RPC Error Codes

MCP inherits several standard error codes from JSON-RPC 2.0, using the reserved range from -32768 to -32000:

Code Name What it Really Means
-32700 Parse Error Your JSON syntax is broken
-32600 Invalid Request Your message structure violates the protocol
-32601 Method Not Found The operation you requested doesn't exist
-32602 Invalid Params Your parameters failed validation
-32603 Internal Error The server encountered an implementation issue
-32000 to -32099 Server Error Implementation-specific errors

Parse Error (-32700)

A parse error occurs when the JSON syntax in your message is invalid. The server can't even begin to process your request because the message structure is broken. You might have an unterminated string, unbalanced brackets, or invalid Unicode sequences.

The server response looks like:

{
  "jsonrpc": "2.0",
  "error": {"code": -32700, "message": "Parse error"},
  "id": null
}

The id field is null because the server couldn't determine which request is yours from the broken JSON. During development, these errors often appear when manually crafting requests or when your JSON serialization has issues.

Invalid Request (-32600)

An invalid request indicates that your JSON was syntactically valid, but the structure violates the protocol requirements. Perhaps you omitted the required jsonrpc field or used the wrong data type for one of the standard fields.

The response might look like:

{
  "jsonrpc": "2.0",
  "error": {"code": -32600, "message": "Invalid Request: missing method field"},
  "id": null
}

The protocol validates structural integrity before processing content, so these errors happen early in the request lifecycle.

Method Not Found (-32601)

This error appears when you attempt to call a method the server doesn't support. You might be trying to use features from a different MCP version, or the server might not implement optional capabilities you expect.

The server responds with:

{
  "jsonrpc": "2.0",
  "error": {"code": -32601, "message": "Method 'tools/update' not found"},
  "id": "abc123"
}

These errors often stem from capability mismatches or method name typos. The error includes your original request ID so you can correlate it with the failed request.

Invalid Parameters (-32602)

Parameter validation failures produce invalid parameter errors. Your method exists, but the arguments you provided don't meet the requirements. Maybe you passed a number where a string was expected, or omitted a required field:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params: uri must be a string",
    "data": {"path": "uri", "expected": "string", "received": "number"}
  },
  "id": 42
}

The error's data field often contains validation details to help you correct your request. This is the most common error during active development as you refine your tool arguments and resource references.

Internal Error (-32603)

An internal error indicates that something went wrong inside the server. Your request was valid, but the server encountered problems during execution. For example:

{
  "jsonrpc": "2.0",
  "error": {"code": -32603, "message": "Internal error: database connection failed"},
  "id": "xyz789"
}

These errors can be particularly frustrating because they stem from issues beyond your control. For example, server dependencies might be down, reached some resource limits, or triggered certain implementation bugs.

Server Errors (-32000 to -32099)

The range from -32000 to -32099 allows for implementation-specific errors:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32050,
    "message": "Rate limit exceeded",
    "data": {"retryAfter": 60}
  },
  "id": "abc123"
}

Server implementers choose these codes to provide clearer information about what went wrong. You'll commonly see -32002 for "Resource not found" and various other codes for authentication, rate limiting, and server-specific conditions.

Custom Application Error Codes

While MCP defines several standard error codes in the reserved range (-32768 to -32000), implementers can also define their own custom error codes outside this range for application-specific errors.

According to the JSON-RPC 2.0 specification that MCP builds upon, any error code outside the reserved range can be used for custom application-defined errors. While there's no official handbook for these custom codes, many implementations follow a convention of organizing codes by category (e.g., -31xxx for authentication, -30xxx for resource access).

When implementing your own MCP server, you can define error codes like this:

// Example of custom error codes for an MCP server
const ErrorCodes = {
  // Authentication errors (-31xxx range)
  AUTH_REQUIRED: -31001,
  INVALID_TOKEN: -31002,

  // Resource access errors (-30xxx range)
  RESOURCE_LOCKED: -30001,
  QUOTA_EXCEEDED: -30002
};

MCP-Specific Error Patterns

Beyond standard error codes, MCP defines specialized error patterns for its core features. Understanding these patterns helps you handle errors more intelligently.

Initialization Errors

When first connecting to an MCP server, you exchange protocol versions and capabilities. Version incompatibilities generate specific errors:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Unsupported protocol version",
    "data": {"supported": ["2025-03-26"], "requested": "2024-11-05"}
  }
}

Initialization errors prevent any further communication until resolved. You'll need to adjust your client to use a compatible protocol version or find a server that supports your requirements.

Resource Errors

The resource system uses dedicated error codes for URI-related failures:

{
  "jsonrpc": "2.0",
  "id": 5,
  "error": {
    "code": -32002,
    "message": "Resource not found",
    "data": {"uri": "file:///nonexistent.txt"}
  }
}

Code -32002 specifically indicates that the requested resource doesn't exist or can't be accessed. This happens when working with file systems, databases, or external APIs where the requested data isn't available.

Tool Error Pattern

Here's where MCP gets interesting—tool execution failures don't use standard error objects. Instead, failed tool calls return a successful response with an isError flag:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {"type": "text", "text": "Failed to fetch weather data: API key invalid"}
    ],
    "isError": true
  }
}

This design separates protocol errors from application errors. The request was processed correctly at the protocol level, but the tool itself encountered issues. You need to check both standard errors and this flag to handle all failure scenarios.

Error Handling in Practice

In real MCP applications, error handling involves several layers. The TypeScript SDK exposes errors as objects with code, message, and data fields:

try {
  const result = await client.request(
    { method: "resources/read", params: { uri: "file:///sample.txt" } },
    ReadResourceResultSchema
  );
} catch (error) {
  console.error(`Error ${error.code}: ${error.message}`);
  // Error -32002: Resource not found
}

The Python SDK uses exceptions:

try:
    result = await session.send_request(
        {"method": "resources/read", "params": {"uri": "file:///sample.txt"}},
        ReadResourceResult
    )
except McpError as e:
    print(f"Error {e.code}: {e.message}")
    # Error -32002: Resource not found

When working with MCP tools, error handling must account for both protocol errors and tool execution errors. This is a subtlety that trips up many MCP newcomers.

During development, you'll see these error codes in various contexts—in the MCP Inspector when testing servers, in client SDK exceptions when writing code, and in server logs when debugging. Recognizing common patterns saves considerable troubleshooting time.

Conclusion

MCP's error codes might seem intimidating at first, but they provide precise information about what went wrong and how to fix it. From parse errors to resource not found situations, the error system gives you specific diagnostics to troubleshoot problems efficiently.

The next time you encounter an MCP error, look at the code first—it immediately narrows down the problem category. Then check the message for specific details and the data field for additional context. With practice, you'll recognize common patterns and resolve issues more quickly.