Protocol Overview
Understand JSON-RPC 2.0, the foundation of MCP communication.
What You'll Build
In this lesson, you'll build a reusable jsonrpc.py module from scratch.
By the end, you'll have working code that can:
- Create valid JSON-RPC requests, responses, and notifications
- Handle errors with proper error codes
- Route incoming messages to handler functions
Each step builds on the previous one, and your code will be runnable after every step.
What is JSON-RPC?
JSON-RPC is a lightweight remote procedure call (RPC) protocol that uses JSON for data encoding. MCP uses JSON-RPC 2.0 for all communication between clients and servers.
JSON-RPC is simple, transport-agnostic, and well-established. It works equally well over HTTP, WebSockets, or stdin/stdout — perfect for MCP's dual transport model.
Message Types
JSON-RPC 2.0 has three message types:
| Type | Has ID? | Expects Response? |
|---|---|---|
| Request | Yes | Yes |
| Response | Yes (matching) | No |
| Notification | No | No |
Request Structure
Every request must have these fields:
{
"jsonrpc": "2.0", // Required: Must be exactly "2.0"
"id": 1, // Required: Unique identifier (string or int)
"method": "tools/list", // Required: Method name to call
"params": {} // Optional: Parameters for the method
}
Response Structure
Responses match requests by ID:
// Success response
{
"jsonrpc": "2.0",
"id": 1, // Must match the request ID
"result": { // The method's return value
"tools": []
}
}
// Error response
{
"jsonrpc": "2.0",
"id": 1,
"error": { // Error object (instead of result)
"code": -32601,
"message": "Method not found"
}
}
The ID Field
The id field connects requests to responses:
- Client generates a unique ID for each request
- Server includes the same ID in the response
- Client matches responses to pending requests by ID
- ID can be a string or integer (not null)
Client Server
| |
|--- Request (id: 1) --------------->|
|--- Request (id: 2) --------------->|
| |
|<-------------- Response (id: 2) ---| (responses can arrive
|<-------------- Response (id: 1) ---| out of order)
MCP typically uses incrementing integers for IDs (1, 2, 3, ...). The ID must be unique within a session but doesn't need to be globally unique.