Menu

AI

JSON-RPC in MCP: Requests, Responses and Notifications

How MCP uses JSON-RPC 2.0 in the 2026-07-28 spec: request IDs, the new resultType field, error codes, notifications, and what changed from older versions.

By: Irina ShvayaOctober 28, 2026

JSON-RPC in MCP: Requests, Responses and Notifications

This page is part of our MCP specification reference, a plain-English guide to the Model Context Protocol spec (version 2026-07-28), within The MCP Guide. Building a server? See MCP development.

Status in the 2026-07-28 spec: core

Every MCP message is a JSON-RPC 2.0 message. JSON-RPC is a small, decades-old convention for one program to call a function in another by sending a JSON object. MCP uses three kinds: requests, responses (a result or an error) and notifications.

MCP adds a few rules on top of plain JSON-RPC. IDs can never be null. Every result now carries a resultType. And since the 2026-07-28 spec, only the client starts requests.

This page explains each message type in plain English, with examples from the MCP base protocol page, current as of October 2026.

Key Takeaways

  • MCP messages "MUST follow the JSON-RPC 2.0 specification," with a few MCP-specific additions.
  • Requests carry a string or integer ID that is never null and never reused while a request is still open.
  • Every successful result must include resultType: complete or input_required.
  • Notifications are one-way messages with no ID, and the receiver must not reply.
  • In 2026-07-28, servers must not start requests; they ask for input through multi round-trip requests instead.
  • MCP reserves error codes -32020 to -32099 for codes defined by the spec.

What JSON-RPC is, and why MCP uses it

JSON-RPC 2.0 defines a request object with a method name and params, and a response object with either a result or an error. It does not care how bytes travel, so the same messages work over a local pipe or over HTTP.

That is why MCP picked it. The MCP overview says the protocol "uses JSON-RPC 2.0 messages" between hosts, clients and servers. The transport (stdio or Streamable HTTP) only decides how those messages are delivered.

Requests

A request asks the other side to do something. In 2026-07-28, "Requests are sent from the client to the server, to initiate an operation." The rules are:

  • A request MUST include a string or integer id.
  • "Unlike base JSON-RPC, the ID MUST NOT be null."
  • The ID MUST NOT match any other request the sender has sent and not yet had answered.

Every request also carries metadata in params._meta. The protocol version and client capabilities are required on every request; client name and version are recommended. Here is a tool call adapted from the extensions overview:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "New York" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }
    }
  }
}

A request missing a required _meta field is malformed. The spec says the server MUST reject it with error -32602 (Invalid params), and with 400 Bad Request on HTTP.

Responses: results

A result response answers a request that worked. It MUST carry the same id as the request and a result object. New in 2026-07-28, the result MUST include a resultType:

  • "complete": the request finished and the result holds the final content.
  • "input_required": the server needs more information first. This drives multi round-trip requests.

For older servers that do not send it, "clients MUST treat an absent resultType as complete." Any value the client does not recognize "MUST be considered invalid." Extensions may add their own values once both sides advertise them.

Here is an illustrative tool result (our example, following the shapes in the spec):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "content": [{ "type": "text", "text": "Sunny, 72°F" }]
  }
}

Responses: errors

An error response carries an error object with an integer code and a message, plus optional data. It uses the request's ID, unless the ID could not be read because the request was malformed.

MCP uses the standard JSON-RPC codes (-32700 and -32600 to -32603) for general failures. It also splits the JSON-RPC server-error range:

Range or codeMeaning in 2026-07-28
-32000 to -32019Legacy range. No new codes may be allocated here.
-32020 to -32099Reserved for codes defined by the MCP spec
-32020HeaderMismatch
-32021MissingRequiredClientCapability
-32022UnsupportedProtocolVersion
-32002Old "resource not found" code; now replaced by -32602

Your own application errors should sit outside the JSON-RPC reserved range of -32768 to -32000. Note that a tool failing at its job (for example, "city not found") is usually reported inside a normal tool result, not as a protocol error. Our guide to MCP tool errors covers that difference.

Notifications

A notification is a one-way message. It "MUST NOT include an ID," and "the receiver MUST NOT send a response." This example, from the cancellation page, is a client telling a stdio server to stop work on request 123:

{
  "jsonrpc": "2.0",
  "method": "notifications/cancelled",
  "params": {
    "requestId": "123",
    "reason": "User requested cancellation"
  }
}

In 2026-07-28, servers send notifications in two places only. Some are tied to a request in flight, such as progress updates. Others flow on a subscriptions/listen stream the client opened, such as "the tool list changed." The message patterns page is explicit: "Servers MUST NOT initiate JSON-RPC requests, and clients do not send JSON-RPC responses."

What changed across spec versions

  • 2025-03-26 added support for JSON-RPC batching, per its changelog.
  • 2025-06-18 removed batching again, according to the 2025-06-18 changelog. Send one message at a time.
  • 2025-11-25 and earlier let requests flow "from the client to the server or vice versa," per the 2025-11-25 base protocol page. Servers could send sampling/createMessage or elicitation/create requests to clients.
  • 2026-07-28 made the client the only side that starts requests, added the required resultType field and set the error-code allocation policy. The 2026-07-28 changelog also moved three codes: HeaderMismatch from -32001 to -32020, MissingRequiredClientCapability from -32003 to -32021 and UnsupportedProtocolVersion from -32004 to -32022.

For the full picture of the 2026 release, see what changed in the July 2026 MCP specification.

Common mistakes

  • Reusing an ID on a retry. In a multi round-trip request, "the JSON-RPC id MUST be different between the initial request and the retry."
  • Sending null IDs. Plain JSON-RPC allows it; MCP does not.
  • Leaving out resultType. New servers must send it on every result.
  • Replying to a notification. Notifications never get a response.
  • Inventing codes in the MCP range. Implementations "MUST NOT emit any code" from -32020 to -32099 that the spec does not define.
  • Still emitting -32002 for missing resources. Use -32602, but keep accepting -32002 from older servers.
  • Treating clientInfo as identity. It is self-reported and not verified, so never use it for security decisions.

Next step

JSON-RPC tells you the shape of each message. The next question is who sends them. Read MCP hosts, clients and servers, or return to the MCP specification hub.

Frequently asked questions

Does MCP use JSON-RPC 2.0?

Yes. All messages between MCP clients and servers must follow JSON-RPC 2.0. MCP adds its own rules, such as non-null IDs, the _meta field and the required resultType on results.

Can an MCP server send requests to the client?

Not in the 2026-07-28 spec. Servers must not initiate JSON-RPC requests. When a server needs something from the client, it returns an input_required result and the client retries the original request with the answers.

Does MCP support JSON-RPC batching?

No. Batching was added in 2025-03-26 and removed in 2025-06-18. Each message is sent on its own.

What is resultType in MCP?

It is a required field on every result in 2026-07-28. complete means the result is final. input_required means the server needs more input before it can finish.

What error code means "unsupported protocol version"?

In 2026-07-28 it is -32022. The error's data lists the versions the server supports, so the client can retry with one of them.

You Might Also like to Read

Get a FREE Website Audit

Enter your website and get a 20–30 page SEO, GEO, AEO & CRO audit within 24 hours. Completely free.

Don't have a site yet? Get in touch →

Ready to speak with a marketing expert?
Give us a call! (916) 866-7893

Websites Launched
1407
Websites Launched
Marketing Experts
29
Marketing Experts
Hours of Dedicated Work
204533
Hours of Dedicated Work
Irina S.Benjamin G.Jeanette M.David G.