MCP messages are JSON-RPC 2.0 messages, UTF-8 JSON objects that carry "jsonrpc": "2.0". The transport only decides how they are framed and delivered.
There are three shapes. A request has an id, a method, and optional params, and expects exactly one reply. A response repeats that id with either result or error, never both. A notification has a method but no id, so nothing is sent back.
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_weather","arguments":{"city":"Oslo"}}}
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"12C, clear"}]}}
An id is a string or an integer, never null, and a sender never reuses one still awaiting its reply. An error holds an integer code, a message, and optional data. Batching was allowed early on, then removed in the 2025-06-18 revision.
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.
Why there's no diagram: “”
The interactive diagram is below the answer - jump to diagram ↓ · Below it, the related concept . Jump to it ↓
The diagram below the answer is the concept . Jump to it ↓