skip to content

JSON-RPC 2.0

A transport-independent envelope: a request carries a method, params and an id, a notification omits the id, and errors use reserved codes. It is the wire under MCP, LSP and Ethereum node APIs.

part ofAPI stylesoverview, primer and where to startread it →
on this pageshow

questions

6

What members make up a JSON-RPC 2.0 request and its response, and how does the client match one to the other?

level: juniorimportance: must knowfreq 34%

answer

  1. a version marker in every message
  2. positional or named arguments
  3. success and failure are exclusive
  4. a client-chosen correlation value

basics

~20 s

A JSON-RPC 2.0 request carries jsonrpc "2.0", a method, optional params (an Array or an Object) and an id. The response echoes that id and carries exactly one of result or error, so the client correlates by id.

solid answer

~40 s

A request is one JSON Object with four members: `jsonrpc`, which MUST be exactly `"2.0"`; `method`, a String naming the procedure (names beginning `rpc.` are reserved for extensions); `params`, which MAY be omitted and otherwise MUST be an Array (by position) or an Object (by name, matched case-sensitively); and `id`, a String, Number or Null chosen by the client. The server MUST answer with a Response carrying `jsonrpc`, the same `id`, and exactly one of `result` on success or `error` on failure — never both. The client matches responses to requests by `id` alone, which is why the specification discourages `null` ids and fractional numbers: `null` is what the server writes when it could not read the id, and a fraction may not survive the round trip exactly.

go deeper

for a junior

Recall the four request members, the three response members, and that a response has result or error but never both. Be able to write a request and its success reply from memory.

for a middle

Explain the params rules — Array by position, Object by name with exact case, Primitives not allowed — and why the id discouragements exist. Show that correlation rests on id alone.

for a senior

Read a captured exchange and name what is malformed, and explain why a client must keep an in-flight table keyed by id rather than trusting arrival order on any transport.

for a principal

Argue what a team should standardise on top of the bare objects — id format, named versus positional params, reserved method prefixes — so that every service in an estate reads the same.

## What JSON-RPC 2.0 is **JSON-RPC 2.0** is a stateless, lightweight remote procedure call protocol. Its specification defines a handful of JSON data structures and the rules for processing them, and nothing about the wire underneath. A **Client** is whatever originates Request objects and handles Response objects; a **Server** originates Responses and handles Requests. The core is two objects — the **Request** and the **Response** — and the `id` that ties one to the other. Several protocols, among them the Language Server Protocol, the Model Context Protocol and Ethereum node APIs, carry exactly these objects, so reading them by hand is a skill that transfers. Two conventions run through the text: member names are **case-sensitive**, and "Structured" means an Object or an Array, while "Primitive" means a String, Number, Boolean or Null. ## The Request object | Member | Required? | Rule | |---|---|---| | `jsonrpc` | yes | A String that MUST be exactly `"2.0"` | | `method` | yes | A String naming the method to invoke | | `params` | no | If present, MUST be Structured: an Array or an Object | | `id` | for a call | A String, Number or Null chosen by the Client | What each rule means in practice: - **By position**, `params` is an Array whose values arrive in the order the Server expects. - **By name**, `params` is an Object whose member names MUST match the expected parameter names exactly, including case; a missing expected name MAY produce an error. - **`params` may be omitted** for a method that takes nothing, but it may not be a bare String, Number, Boolean or Null — those are Primitives. - **Method names beginning with `rpc.`** (the word rpc followed by a period) are reserved for rpc-internal methods and system extensions and MUST NOT be used for anything else. - **`id`** SHOULD normally not be Null, and a Number id SHOULD NOT have a fractional part. - **Leaving `id` out** turns the Request into a notification, which gets no reply at all. ## The Response object Outside a batch, every call — every valid Request that carries an `id` — MUST be answered with one Response, a single JSON Object (inside a batch the specification softens this to SHOULD): 1. `jsonrpc`, again exactly `"2.0"`. 2. `id`, REQUIRED, the same value the Request carried. 3. Either `result` or `error`, and never both. `result` is REQUIRED on success and MUST NOT exist on error; `error` is REQUIRED on error, MUST NOT exist otherwise, and is an Object with an integer `code`, a short `message` and an optional `data`. The value of `result` is whatever the method returns; the specification constrains it no further. ## Correlation by id The `id` is the only thing linking a Response to its Request. The Server MUST reply with the same value, and the specification says the member "is used to correlate the context between the two objects". It promises nothing about the order in which separate requests are answered, and inside a batch it explicitly allows Responses in any order. So a Client keeps a table of the requests it has in flight, keyed by `id`, and settles each entry when a Response with that `id` arrives. The specification does not demand that ids be unique, but correlation only works if a Client never has two requests in flight under the same one. The two discouragements on `id` follow from that job: - **Null** is the value the Server itself writes when it could not determine a Request's `id` — after a parse error or an invalid Request. A Client that sends `"id": null` cannot tell its own answer from such a failure. JSON-RPC 1.0 also used a null id to mark notifications, a second source of confusion. - **Fractions** are discouraged because many decimal fractions have no exact binary representation, so an echoed value might not compare equal to the one sent. ## A worked exchange A call by position, and its answer: ```json {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1} {"jsonrpc": "2.0", "result": 19, "id": 1} ``` The same call by name, with a String id; the order of the named members does not matter: ```json {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": "q-7"} {"jsonrpc": "2.0", "result": 19, "id": "q-7"} ``` A call to a method the Server does not have still echoes the `id`, but carries `error` instead of `result`: ```json {"jsonrpc": "2.0", "method": "subtrakt", "params": [42, 23], "id": "q-8"} {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "q-8"} ``` ## Reading a message cold Handed an unfamiliar message, ask four questions in order: 1. Is `jsonrpc` present and exactly `"2.0"`? 2. Is there a `method` (a Request) or a `result` / `error` (a Response)? 3. For a Request, is there an `id` (a call, which will be answered) or not (a notification, which will not)? 4. For a Response, is exactly one of `result` and `error` present, and does its `id` match a request still in flight? Those four checks catch most malformed traffic before any method-specific logic runs, and they are the same whichever protocol happens to be carrying the objects.

  • Can a JSON-RPC 2.0 method be called with positional params by one client and named params by another?
    The specification defines both structures — an Array by position, an Object by name — but which one a given method accepts is the server's decision. By name, member names must match the expected parameter names exactly, including case, and a missing name MAY produce an error; by position, values must arrive in the server's expected order. A server may accept both for one method if it chooses.
  • Why does the JSON-RPC 2.0 specification say a request id SHOULD NOT be null or fractional?
    Null is the value the server writes into a Response when it could not determine the request's id, as after a parse error or an invalid Request, so a request that uses null cannot be told apart from those failures; JSON-RPC 1.0 also used null for notifications. Fractions are discouraged because many decimal fractions are not exactly representable in binary, so the echoed value might not compare equal.
  • In JSON-RPC 2.0, may an application name one of its own methods rpc.status?
    No. Method names that begin with rpc followed by a period are reserved for rpc-internal methods and system extensions, each defined in a related specification, and MUST NOT be used for anything else. All such extensions are OPTIONAL, so a client also cannot assume that any rpc.-prefixed method exists on a given server.

saying these in an interview costs you the question

  • The server assigns the response id to number its replies.
  • A JSON-RPC 2.0 response carries both result and error, with the unused one null.
  • params may be any JSON value, such as a bare string or number.
  • The jsonrpc member is optional because servers infer the version.
  • Responses always come back in the order the requests were sent.
open as a page

How does a JSON-RPC 2.0 server choose among the reserved error codes, and when must the error response's id be null?

level: middleimportance: must knowfreq 26%

basics

~20 s

JSON-RPC 2.0 reserves -32700 (parse error), -32600 (invalid request), -32601 (method not found), -32602 (invalid params) and -32603 (internal error), with -32000 to -32099 for implementation-defined server errors. The id is null when it could not be determined.

open as a page

A JSON-RPC 2.0 server receives a batch array — what must it send back, and when is the reply a single object or nothing?

level: middleimportance: should knowfreq 15%

basics

~20 s

A JSON-RPC 2.0 batch is an Array of Request objects; the server answers with an Array of Responses, one per non-notification, in any order, matched by id. Invalid JSON or an empty Array gets one error object; an all-notification batch gets nothing.

open as a page

What makes a JSON-RPC 2.0 message a notification, and why can the client never learn that one failed?

level: middleimportance: should knowfreq 22%

basics

~20 s

A JSON-RPC 2.0 notification is a Request object with no id member at all. The server MUST NOT reply to it — not on success, not on error, not inside a batch — so the client never sees errors such as invalid params.

open as a page

JSON-RPC 2.0 calls itself transport agnostic — what does that leave a protocol carrying it over HTTP or a byte stream to define?

level: seniorimportance: should knowfreq 12%

basics

~20 s

JSON-RPC 2.0 defines only objects and their processing rules. A protocol carrying it must define message framing on a stream, any HTTP mapping (method, status codes, what a notification gets), which side may send requests, and cancellation or timeouts.

open as a page

A legacy JSON-RPC 1.0 client calls a strict JSON-RPC 2.0 server and its notifications start getting replies — why, and what else differs?

level: seniorimportance: nice to knowfreq 6%

basics

~20 s

JSON-RPC 1.0 marks a notification with id null and sends no jsonrpc member, so a strict 2.0 server sees a request to answer or reject. 2.0 also adds named params, result-or-error responses, defined error codes, batches and reserved rpc. names.

open as a page