재하의 개발 블로그
Article 4 min read

MCP Deep Dive Part 2 — JSON-RPC 2.0 and Serialization

mcp json-rpc protocol serialization

What is JSON-RPC 2.0

JSON-RPC is "a remote procedure call (RPC) protocol packaged in JSON". It's an agreement that allows you to call functions in other processes or servers as if they were local.

"2.0" refers to the version, a spec finalized in 2010. All messages must include the "jsonrpc": "2.0" field.

Three Message Types

JSON-RPC 2.0 has only three types of messages.

1. Request — A request expecting a response

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "jira_search",
  "params": {
    "jql": "project = BIO AND status = 'In Progress'"
  }
}

The id field is key. Even when sending multiple requests simultaneously, responses don't get mixed up—they're matched by id.

2. Response — Response to a Request

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "issues": [{ "key": "BIO-42", "summary": "OpenSearch 동의어 사전 최적화" }]
  }
}

The id must match the Request. When an error occurs, an error field comes instead of result.

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32600,
    "message": "Invalid Request"
  }
}

3. Notification — One-way transmission without response

{
  "jsonrpc": "2.0",
  "method": "progress",
  "params": {
    "value": 42,
    "message": "Jira API 호출 중..."
  }
}

No id field. Used when the server pushes progress updates to the client.

Standard Error Codes JSON-RPC 2.0 has predefined error codes.

-32700 is Parse error, -32600 is Invalid Request, -32601 is Method not found, -32602 is Invalid params. MCP adds its own error codes on top of these.

Why JSON-RPC Was Chosen

There are other protocols, but there are reasons JSON-RPC was chosen.

ProtocolAdvantagesWhy Unsuitable for MCP
gRPCPerformance, type safetyRequires .proto schema + build pipeline → High barrier for server implementation
RESTUniversal adoptionVerbs (GET/POST/PUT) are resource-centric → Unnatural for "function call" concept
JSON-RPCSimplicityJust define method + params → Language/runtime agnostic implementation

JSON-RPC enables implementing MCP Servers in any language—Python, TypeScript, Kotlin—with a low barrier to entry. It's a trade-off Anthropic chose because they prioritized ecosystem expansion.

What is Serialization

Serialization is the process of converting program objects in memory into a transmittable byte stream (text). The opposite is deserialization.

Here's what actually happens in MCP:

Step 1 — LLM generates tool_use block

When the LLM (Claude) determines during response generation that a Jira search is needed, it creates a structured object in memory.

ToolUseBlock {
  id: "toolu_abc123",
  name: "jira_search",
  input: { jql: "project = BIO AND status = 'In Progress'" }
}

This object is still a data structure in Python/TypeScript memory. It can't be sent to another process yet.

Step 2 — JSON serialization (performed by Host)

The Host converts this object into JSON text. This is serialization.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "jira_search",
  "params": {
    "jql": "project = BIO AND status = 'In Progress'"
  }
}

Now it's text that can be transmitted over network (or stdio).

Step 3 — Transmission

If stdio, it's sent via standard input; if SSE/HTTP, it's sent in the HTTP body as text.

Step 4 — Deserialization (performed by MCP Server)

The MCP Server (e.g., Atlassian server, written in Python) restores the received JSON text into an object in its own language.

# Inside Python MCP Server
request = {
    "method": "jira_search",
    "params": {"jql": "project = BIO AND status = 'In Progress'"}
}
# Actual Jira API call
issues = jira_client.search_issues(request["params"]["jql"])

Step 5 — Serialize result and return

The server serializes the result received from Jira API back into JSON and sends it to the Host, which deserializes it and passes it to the LLM as a tool_result.

The Essence of Serialization Ultimately, serialization is "translating into a common language (JSON text) for programs to exchange". Whether the LLM (Claude) is in Python or the MCP Server is in Kotlin, they can communicate without language barriers because there's a common language—JSON—in between.

Summary

JSON-RPC 2.0 is a simple remote procedure call protocol consisting of three message types: Request / Response / Notification. MCP's choice of JSON-RPC over gRPC or REST was a strategic decision to rapidly expand the ecosystem with a low barrier to entry.

Serialization is the process of converting these messages into actually transmittable form, and all MCP communication works language-agnostically through this conversion.

The next part explains which transport layers these messages actually travel over, and why we transitioned from SSE to Streamable HTTP.

MCP Deep Dive Part 3 — From SSE to Streamable HTTP — Covers SSE