In depth
JSON-RPC 2.0 is a 2010-era open standard for remote procedure calls encoded as JSON. Every MCP message is a JSON-RPC object. The protocol is spec-simple: a message is either a request (`method` + `params` + `id`), a response (`result` or `error` + matching `id`), or a notification (`method` + `params`, no `id`, no response expected).
MCP chose JSON-RPC because it's lightweight, debuggable (human-readable JSON), and widely implemented. Every MCP SDK includes a JSON-RPC codec. Debugging an MCP issue often means tailing the JSON-RPC frames and inspecting the method/params.
JSON-RPC supports batching (multiple messages in one array) and bidirectional calls (server → client, not just client → server). MCP uses bidirectional calls for sampling (server asks client for LLM completion) and roots (server asks client for allowed locations).
The format is transport-agnostic: JSON-RPC messages can ride stdio newlines, SSE events, or HTTP POST bodies. MCP uses whichever transport makes sense for the deployment.