Skip to main content

Guide To JSON RPC 2.0

Introduction

Modern distributed systems constantly need a way for one application to communicate with another application across a network. A frontend may need to ask a backend server for data, a blockchain client may need to interact with a node, or an AI application may need to invoke tools exposed by another service. While there are many communication styles available today, Remote Procedure Call, commonly called RPC, remains one of the simplest and most intuitive approaches.

JSON-RPC is one such RPC protocol, designed around a very clear philosophy: communication should be lightweight, predictable, and easy to implement. The protocol avoids unnecessary complexity and focuses only on defining how requests and responses should look. It deliberately stays transport agnostic, meaning it does not force developers to use HTTP, WebSockets, TCP, or any other specific communication layer.

In this tutorial, we will explore JSON-RPC 2.0 in depth, understand its core components, examine how requests and responses work, study error handling, notifications, batch processing, and finally understand where JSON-RPC fits in modern software systems.

Understanding the Core Idea Behind JSON-RPC

Before discussing syntax and message structures, it is important to understand the fundamental problem JSON-RPC solves. Imagine that one application wants another application to execute a function remotely.

For example:

  • A frontend application wants a backend to calculate totals
  • A wallet application wants a blockchain node to fetch account balances
  • An AI host wants an external MCP server to execute a tool
  • A monitoring dashboard wants to query metrics from another service

Instead of exchanging arbitrary messages, JSON-RPC standardizes communication into a very simple pattern:

  • A client sends a request
  • The server executes a method
  • The server sends back a response

Conceptually, it feels almost like calling a local function, except the function exists on another machine or service. This is why the term “Remote Procedure Call” exists.

What Makes JSON-RPC Lightweight

One of the major design goals of JSON-RPC is simplicity. The protocol defines only a few core concepts:

  • Request objects
  • Response objects
  • Notifications
  • Error objects
  • Batch requests

That is essentially the entire protocol. Unlike larger frameworks that include routing, resource modeling, version negotiation, or transport-level rules, JSON-RPC focuses only on message structure.

This minimalism is precisely why JSON-RPC is popular in areas such as:

  • Blockchain systems
  • Internal microservice communication
  • Developer tooling
  • AI protocols like MCP
  • Lightweight backend services

JSON-RPC Is Transport Agnostic

One extremely important characteristic of JSON-RPC is that it does not care how messages travel between systems.

The protocol can work over:

  • HTTP
  • HTTPS
  • TCP sockets
  • WebSockets
  • IPC channels
  • Message queues
  • STDIO streams

The only requirement is that the messages themselves follow JSON-RPC formatting rules. This flexibility makes JSON-RPC highly reusable across different environments.

For example:

EnvironmentPossible Transport
Web ApplicationHTTP
Real-time systemWebSocket
Local process communicationSTDIO
Blockchain nodeTCP/HTTP
AI agent protocolSTDIO/WebSocket

The Structure of a JSON-RPC Request

The heart of JSON-RPC is the request object. Whenever a client wants the server to execute something, it sends a request.

A standard JSON-RPC 2.0 request looks like this:

{
"jsonrpc": "2.0",
"method": "subtract",
"params": [42, 23],
"id": 1
}

At first glance, this may look like ordinary JSON, but every field has a very specific meaning.

Understanding Each Request Field

The jsonrpc Field

The jsonrpc field specifies the protocol version. In JSON-RPC 2.0, this field must contain:

"jsonrpc": "2.0"

This helps both client and server understand which protocol rules are being used.

The method Field

The method field contains the name of the remote procedure that should be executed. For example:

"method": "subtract"

The server interprets this as “Execute the subtract function remotely”.

Method names are case-sensitive strings. The specification also reserves method names beginning with:

rpc.

for internal protocol usage.

The params Field

The params field contains the arguments passed to the method.

JSON-RPC supports two styles of parameters:

  1. Positional parameters
  2. Named parameters

Positional Parameters

In positional parameters, values are passed as an array. Example:

"params": [42, 23]

The server interprets this based on order. So:

subtract(42, 23)

would produce:

19

Named Parameters

Named parameters use objects instead of arrays. Example:

"params": {
"minuend": 42,
"subtrahend": 23
}

This style is often easier to read because each parameter is explicitly named.

The id Field

The id field is extremely important because it connects requests with responses. Example:

"id": 1

When the server replies, it includes the same ID so the client knows which request the response belongs to. This becomes especially useful when multiple requests are happening simultaneously. The ID may be:

  • A number
  • A string
  • Null in certain cases

However, JSON-RPC 2.0 notifications intentionally omit the ID entirely.

Understanding JSON-RPC Responses

When the server successfully executes a method, it returns a response object. Example:

{
"jsonrpc": "2.0",
"result": 19,
"id": 1
}

The response contains three important parts:

  • Protocol version
  • Result
  • Request ID

The result Field

The result field contains the actual output of the method execution. Example:

"result": 19

The important rule here is: "A successful response contains result, not error". The two fields are mutually exclusive.

Error Responses in JSON-RPC

Not every request succeeds. Sometimes:

  • The JSON is malformed
  • The method does not exist
  • Parameters are invalid
  • Internal execution fails

In such cases, the server returns an error object instead of a result. Example:

{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1
}

Structure of the Error Object

The error object contains:

FieldPurpose
codeNumeric error identifier
messageHuman-readable error
dataOptional additional details

The data field is optional but extremely useful for debugging. Example:

"data": "Missing required parameter: subtrahend"

Standard JSON-RPC Error Codes

JSON-RPC defines several built-in error codes.

Error CodeMeaning
-32700Parse error
-32600Invalid Request
-32601Method not found
-32602Invalid params
-32603Internal error
-32000 to -32099Server-defined errors

Understanding Each Error Type

Parse Error (-32700)

This happens when invalid JSON is received. Example:

{
"jsonrpc": "2.0",
"method":

Since the JSON itself is incomplete, the server cannot even parse the request.

Invalid Request (-32600)

This means the JSON may be syntactically valid, but it does not follow JSON-RPC structure rules. Example:

{
"method": 1
}

The method must be a string, so this request is invalid.

Method Not Found (-32601)

This occurs when the requested procedure does not exist on the server. Example:

"method": "foobar"

If the server has no such method, it returns this error.

Invalid Params (-32602)

This occurs when parameters are missing or incorrectly formatted.

For example, if the subtract method requires two values but receives only one, the server returns an invalid parameter error.

Internal Error (-32603)

This indicates that something failed inside the server during execution.

The request itself may be valid, but the server encountered an unexpected problem.

Notifications in JSON-RPC

One elegant feature of JSON-RPC is notifications. A notification is a request where the client does not expect a response.

Example:

{
"jsonrpc": "2.0",
"method": "update",
"params": [1,2,3]
}

Notice something important:

There is no id field.

Without an ID, the server has no mechanism for correlating a response, so it simply executes the request silently.

When Notifications Are Useful

Notifications are useful for fire-and-forget operations such as:

Logging events Sending telemetry Updating analytics Broadcasting non-critical information

Because no response is expected, notifications reduce overhead and improve efficiency. However, they also introduce risk because the client receives no confirmation that execution succeeded.

Batch Requests in JSON-RPC

JSON-RPC 2.0 also supports batch processing. Instead of sending multiple requests separately, the client can send them together inside an array.

Example:

[
{
"jsonrpc": "2.0",
"method": "subtract",
"params": [42, 23],
"id": 1
},
{
"jsonrpc": "2.0",
"method": "foobar",
"id": 2
}
]

The server processes each request independently and returns an array of responses.

Why Batch Requests Matter

Batching can significantly improve performance in distributed systems because:

  • Fewer network round trips occur
  • Multiple operations execute together
  • Communication overhead decreases

This becomes especially valuable in high-latency systems or blockchain communication layers.

When JSON-RPC Is a Better Fit

JSON-RPC works especially well when:

  • Operations resemble function calls
  • High efficiency matters
  • Strict request-response control is needed
  • The API is internally consumed
  • Real-time communication is important

This is why blockchain ecosystems heavily rely on JSON-RPC APIs.

Limitations of JSON-RPC

Despite its elegance, JSON-RPC intentionally leaves several concerns outside the specification. It does not define:

  • Authentication
  • Authorization
  • Service discovery
  • API documentation standards
  • Version negotiation
  • Transport security

These responsibilities must be implemented separately. This simplicity is both a strength and a limitation.