Lesson 3 - Step 3 of 5

Responses & Errors

Add response creation and error handling to your JSON-RPC module.

Edit: jsonrpc.py

Now let's add the ability to create responses. A JSON-RPC response can be either a success (with a result) or an error (with an error object).

Step 1: Add the Error Codes

Add this code after your imports, before the create_request function:

python jsonrpc.py - Add after imports
from enum import IntEnum


class JsonRpcErrorCode(IntEnum):
    """Standard JSON-RPC 2.0 error codes."""

    PARSE_ERROR = -32700       # Invalid JSON
    INVALID_REQUEST = -32600   # Not a valid Request object
    METHOD_NOT_FOUND = -32601  # Method does not exist
    INVALID_PARAMS = -32602    # Invalid method parameters
    INTERNAL_ERROR = -32603    # Internal JSON-RPC error


# Human-readable messages for each error code
ERROR_MESSAGES: dict[JsonRpcErrorCode, str] = {
    JsonRpcErrorCode.PARSE_ERROR: "Parse error",
    JsonRpcErrorCode.INVALID_REQUEST: "Invalid request",
    JsonRpcErrorCode.METHOD_NOT_FOUND: "Method not found",
    JsonRpcErrorCode.INVALID_PARAMS: "Invalid params",
    JsonRpcErrorCode.INTERNAL_ERROR: "Internal error",
}

Step 2: Add Response Functions

Add these functions after your create_request function:

python jsonrpc.py - Add after create_request
def create_success_response(request_id: int | str, result: Any) -> dict:
    """
    Create a JSON-RPC success response.

    Args:
        request_id: The ID from the original request
        result: The result data to return

    Returns:
        A properly formatted JSON-RPC success response
    """
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "result": result
    }


def create_error_response(
    request_id: int | str | None,
    code: JsonRpcErrorCode,
    message: str | None = None,
    data: Any = None
) -> dict:
    """
    Create a JSON-RPC error response.

    Args:
        request_id: The ID from the original request (None if parse error)
        code: The error code
        message: Custom error message (uses default if not provided)
        data: Optional additional error data

    Returns:
        A properly formatted JSON-RPC error response
    """
    error: dict[str, Any] = {
        "code": int(code),
        "message": message or ERROR_MESSAGES.get(code, "Unknown error")
    }

    if data is not None:
        error["data"] = data

    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "error": error
    }

Step 3: Update the Test Block

Replace your if __name__ == "__main__": block with this:

python jsonrpc.py - Replace the test block
# =============================================================================
# Try it out
# =============================================================================

if __name__ == "__main__":
    # Create a request
    req = create_request("tools/list", request_id=1)
    print("Request:")
    print(json.dumps(req, indent=2))
    print()

    # Create a success response
    success = create_success_response(
        request_id=1,
        result={"tools": [{"name": "calculator"}]}
    )
    print("Success Response:")
    print(json.dumps(success, indent=2))
    print()

    # Create an error response
    error = create_error_response(
        request_id=1,
        code=JsonRpcErrorCode.METHOD_NOT_FOUND,
        data={"method": "unknown/method"}
    )
    print("Error Response:")
    print(json.dumps(error, indent=2))

Try It

bash
python jsonrpc.py

Expected Output

text
Request:
{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "id": 1
}

Success Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "calculator"
      }
    ]
  }
}

Error Response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "Method not found",
    "data": {
      "method": "unknown/method"
    }
  }
}

Understanding Error Codes

JSON-RPC 2.0 defines these standard error codes. Memorize these — you'll see them often when debugging MCP:

Code Name When to Use
-32700 Parse error Invalid JSON received
-32600 Invalid Request Missing required fields
-32601 Method not found Unknown method name
-32602 Invalid params Wrong or missing parameters
-32603 Internal error Server-side error
Never Both!

A JSON-RPC response must have either result OR error, never both. Including both will confuse clients.

Your File So Far

Your jsonrpc.py should now have:

  • Imports: json, typing.Any, enum.IntEnum
  • JsonRpcErrorCode enum with 5 error codes
  • ERROR_MESSAGES dict
  • create_request() function
  • create_success_response() function
  • create_error_response() function
  • Test block that demonstrates all three

What's Next

Requests expect responses, but JSON-RPC also supports notifications — one-way messages that don't expect a reply. In the next step, you'll add notification support and message type detection.