Overview
The Model Context Protocol (MCP) is JSON-RPC 2.0 between a client inside a host application (Claude Code, Claude Desktop, an IDE) and a server that exposes tools, resources, and prompts. The spec lives at modelcontextprotocol.io; the current revision is 2026-07-28 and the previous one is 2025-11-25. The 2026-07-28 revision made the protocol stateless, which changes how servers hold state, scale, and talk back to the client.
Treat every request as self-contained
There is no initialize handshake and no protocol-level session. Each request carries io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities in _meta (both required); clients should add clientInfo, and servers should return serverInfo in each result’s _meta. Every result has a resultType of "complete" or "input_required".
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": { "name": "search_issues", "arguments": { "q": "is:open label:bug" },
"_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {} } } }A request missing a required field gets -32602. An unsupported version returns UnsupportedProtocolVersionError with the versions the server supports. A needed but undeclared client capability returns MissingRequiredClientCapabilityError (-32021). Servers must not rely on earlier requests on the same connection; state that spans calls travels as an explicit handle the model passes as a tool argument. server/discover returns a server’s versions, capabilities, and identity; servers must implement it and clients may call it first.
Pick the primitive by who controls it
- Tools are model-controlled actions with a JSON Schema input. Use them for anything that writes or has side effects. See mcp-tool-design.
- Resources are application-driven, URI-addressed, read-only data. See mcp-resources.
- Prompts are user-invoked templates that clients may surface as slash commands. Use one when the operation is filling in a template, a tool when it calls an API.
tools/list, resources/list, and prompts/list must not vary per connection; they may vary by the authorization on the request. List and read results carry ttlMs and cacheScope ("public" or "private") so clients can cache them, and servers should return tools in a deterministic order, which also helps LLM prompt-cache hits.
Use multi round-trip requests when the server needs input
Servers no longer send requests to the client. To ask for a user answer, a server replies to tools/call, resources/read, or prompts/get with an InputRequiredResult (resultType: "input_required") holding inputRequests and an optional opaque requestState. The client gathers the input and retries the original request under a new id with inputResponses and the same requestState. See mcp-elicitation.
Do not build on deprecated or removed features
- Deprecated, still working for at least twelve months: Roots, Sampling, and Logging; the HTTP+SSE transport; Dynamic Client Registration (use Client ID Metadata Documents).
- Removed: the
initializehandshake,Mcp-Session-Id, the standalone GET stream, SSE resumption withLast-Event-ID,ping,logging/setLevel. - Moved out of core: tasks are now the official extension
io.modelcontextprotocol/tasks.
Declare only the capabilities you implement: tools (with listChanged), resources (listChanged, subscribe), prompts. Clients that must reach servers on 2025-11-25 or earlier probe with a modern request first and fall back to initialize only when the failure is not a recognized modern error. See mcp-transports.