Model Context Protocol Specification: What the MCP Spec Defines

The Model Context Protocol specification defines MCP's JSON-RPC 2.0 messages, transports, versioning and auth. See what each revision changed and how.

Bifrost Team10 min read

A dated MCP spec document with JSON-RPC messages flowing between a host and two MCP servers

The Model Context Protocol specification is the official, dated document that defines how MCP hosts, clients and servers communicate: the JSON-RPC 2.0 message formats, the stdio and Streamable HTTP transports, protocol version negotiation, an OAuth 2.1 authorization profile, and the tools, resources and prompts a server can expose. A TypeScript schema in the project repository is the source of truth for every message.

The latest revision of the Model Context Protocol specification, 2026-07-28, made the protocol stateless by removing the initialize handshake and protocol sessions, so much of what tutorials and AI answers say about the MCP spec now describes the legacy era. The MCP overview explains the protocol itself; this page covers what the specification requires. Bifrost, the open-source AI gateway, sits between MCP clients and servers that implement different revisions.

What does the MCP specification define?

The MCP specification defines the wire protocol between MCP clients and MCP servers: the message types, how each request declares its protocol version, the transports that carry messages, an authorization profile for HTTP, and the optional features each side can offer. It does not define SDK interfaces, model behavior, or how a host presents tools to users.

The 2026-07-28 specification splits the protocol into components. Three are mandatory for every implementation; the rest are adopted as needed:

ComponentWhat it coversRequirement
Base protocolJSON-RPC messages, _meta fields, error codesMUST
VersioningPer-request version, server/discover, extensionsMUST
Message patternsRequest and response, multi round-trip, subscribe and notifyMUST
Transportsstdio, Streamable HTTP, or customOne per connection
AuthorizationOAuth 2.1 profile for HTTPSHOULD on HTTP
Server featuresTools, resources, promptsOptional
Client featuresElicitation (roots and sampling deprecated)Optional
UtilitiesProgress, cancellation, completionOptional

Requirement words such as MUST and MAY carry their BCP 14 meanings (RFC 2119 and RFC 8174) only in capitals. The security principles, such as user consent before any tool call, are stated but cannot be enforced by the protocol; hosts must enforce them.

Hosts, clients and servers in the MCP specification

The MCP specification describes a client-host-server architecture. The host is the AI application, such as Claude Desktop, Claude Code or Cursor, and it creates one MCP client per server. Each client keeps a one-to-one link with a single MCP server, and no server sees the full conversation.

Servers offer three features, and the specification assigns each a different controller:

  • Tools are model-controlled functions, such as create_issue.
  • Resources are application-controlled data addressed by URI.
  • Prompts are user-controlled templates, such as a slash command.

Clients offer one active feature, elicitation, which lets a server ask the user for missing input. Revision 2026-07-28 deprecated roots, sampling and logging, and servers no longer send requests to clients: a server that needs input returns a result with resultType: "input_required", and the client retries the original request with the answers.

How the MCP specification uses JSON-RPC 2.0 messages

Every MCP message is a UTF-8 encoded JSON-RPC 2.0 object of one of three types: a request with an id and a method, a response that returns either result or error under the same id, or a notification with no id that receives no reply. MCP tightens JSON-RPC in two places: request IDs must not be null, and every result carries a resultType.

An MCP client sends a tools/call request carrying its protocol version in _meta; the server either returns a complete result, asks for input, or rejects the version with error -32022
Under the 2026-07-28 revision, every request is self-contained, so the server decides on each request whether it can serve that protocol version.

Because there is no handshake, each request carries its protocol version and client capabilities in reserved _meta keys, which every server must read:

json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "search_issues",
    "arguments": {"query": "label:bug status:open"},
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {"elicitation": {}},
      "io.modelcontextprotocol/clientInfo": {"name": "example-host", "version": "1.4.0"}
    }
  }
}

A request missing a required _meta field is malformed and returns -32602 (Invalid params). The specification partitions the JSON-RPC server-error range: -32000 to -32019 is legacy and implementation-defined, and -32020 to -32099 is reserved for codes the specification defines:

CodeNameReturned when
-32602Invalid paramsMissing _meta field, or resource not found (replaced -32002)
-32020HeaderMismatchAn HTTP header disagrees with the body
-32021MissingRequiredClientCapabilityThe client did not declare a needed capability
-32022UnsupportedProtocolVersionVersion not supported; data.supported lists alternatives

A failed tool is not a protocol error: the server returns a normal result with isError: true, so the model can read the message and try again.

MCP transports in the specification

The MCP specification defines two standard transports and allows custom ones. stdio carries newline-delimited JSON-RPC over the standard input and output of a subprocess the client launches. Streamable HTTP sends each message as an HTTP POST to one MCP endpoint, with replies as a JSON object or a request-scoped server-sent events stream. Message semantics are identical on both.

TransportHow messages moveAuthenticationStatus
stdioOne JSON-RPC message per line, no embedded newlines; stderr for logsCredentials come from the environment, not the HTTP auth profileActive
Streamable HTTPOne POST per message with MCP-Protocol-Version, Mcp-Method and Mcp-Name headers; Origin validatedOAuth 2.1 profile with protected resource metadata (RFC 9728)Active
HTTP+SSEA separate GET stream for server-to-client messagesVariesDeprecated since 2025-03-26
CustomAny bidirectional channel; byte streams should reuse stdio framingTransport's own best practicesAllowed

The HTTP headers mirror body fields so load balancers and gateways can route without parsing JSON; a header that disagrees with the body returns 400 Bad Request. MCP endpoint covers the single URL a Streamable HTTP server serves.

MCP spec versions and what each revision changed

MCP spec versions are date strings in YYYY-MM-DD form that mark the last backwards-incompatible change; compatible additions ship without a new version. Each revision is labeled Draft, Current or Final. The current revision is 2026-07-28, one of five shipped since November 2024.

RevisionStatusHeadline changes
2024-11-05FinalFirst public release: JSON-RPC base protocol, stdio and HTTP+SSE, tools, resources, prompts, sampling and roots
2025-03-26FinalOAuth 2.1 authorization framework; Streamable HTTP replaces HTTP+SSE; JSON-RPC batching; tool annotations
2025-06-18FinalBatching removed; structured tool output; elicitation; servers as OAuth resource servers; MCP-Protocol-Version header
2025-11-25FinalExperimental tasks; URL-mode elicitation; Client ID Metadata Documents; JSON Schema 2020-12 by default
2026-07-28CurrentStateless, no initialize or sessions; server/discover; multi round-trip requests; tasks moved to an extension; roots, sampling and logging deprecated

The 2026-07-28 revision lists every breaking change, and the MCP overview summarizes them for server builders. A deprecated feature stays in the specification for at least twelve months before removal.

How MCP version negotiation and compatibility work

Under the 2026-07-28 MCP specification there is no negotiation handshake. Every request names its protocol version in _meta, and on HTTP also in the MCP-Protocol-Version header. A server that does not support that version returns UnsupportedProtocolVersionError (code -32022) listing the versions it supports, and the client retries with one of them.

Servers must implement server/discover, which returns supported versions, capabilities and identity in one call; clients may call it first or send requests directly. Versioning names three eras: modern (2026-07-28 and later), legacy (2025-11-25 and earlier, with the initialize handshake) and dual-era (both). The outcomes that matter in practice:

ClientServerOutcome
ModernModernWorks; a version mismatch returns -32022 and the client retries
ModernLegacyFails; a server/discover probe makes the failure deterministic on stdio
Dual-eraModernWorks; the client stays modern
Dual-eraLegacyWorks; the client falls back to initialize
LegacyModernFails; HTTP returns 400 Bad Request, with no fall-forward
LegacyDual-eraWorks under the negotiated legacy revision

Where the Model Context Protocol specification lives and how it changes

The Model Context Protocol specification is versioned by date and generated from a TypeScript schema (schema.ts) in the project's GitHub repository, with a JSON Schema generated from it for tooling. Changes go through Specification Enhancement Proposals (SEPs), and MCP is a Linux Foundation project.

  • Change process. A SEP is a design document for a protocol or process change, reviewed as a pull request; the changelog cites a SEP for each change.
  • Governance. Lead Maintainers, Core Maintainers and Maintainers form the MCP Steering Group, and seats belong to individuals, not companies. Specifications are licensed under Apache 2.0.
  • Adjacent projects. The MCP Registry (in preview) publishes server.json metadata for public servers, and the MCP Inspector tests servers across protocol eras. Neither is part of the specification.

MCP: the protocol, the plumbing and the gateway follows a request on the wire and through a gateway.

The MCP specification with Bifrost

Bifrost, the open-source AI gateway built by Maxim AI, implements the Model Context Protocol specification on both sides of a connection, which is how it runs as an MCP gateway. As an MCP client, Bifrost connects to MCP servers over STDIO, HTTP or SSE, or generates a server from an OpenAPI document (beta). As an MCP server, Bifrost exposes every connected tool at one /mcp endpoint: POST carries JSON-RPC calls such as tools/list and tools/call, and GET opens an SSE stream.

MCP hosts connect to the Bifrost /mcp endpoint, which applies auth and per-key tool filtering, then calls upstream MCP servers over STDIO, HTTP or SSE
Clients speak to one endpoint, while Bifrost handles each upstream server's transport, credentials and connection health.

The /mcp endpoint follows the handshake-based revisions: clients open with initialize, and the documented probe uses protocol version 2025-06-18. Toward upstream servers, Bifrost runs health checks that combine a ping (when the server supports one) with tools/list, each attempt bounded at 5 seconds, and reconnects automatically when a session expires, an SSE stream drops or a STDIO process exits.

Credentials follow the specification's split by transport. STDIO servers inherit their environment, and HTTP and SSE servers use one of Bifrost's six authentication types, including per-user OAuth and token exchange. Tool filtering makes tools/list return only the tools a virtual key allows and checks every tools/call against the same list.

For large tool sets, Code Mode cut input tokens by 92.8% across 508 tools on 16 servers at the same pass rate.

The same gateway routes LLM traffic to 25+ providers and 10,000+ models with 11 microseconds of overhead at 5,000 RPS. To connect your first MCP server, start with the gateway quickstart.

Run MCP clients and servers through one gateway

Connect servers over STDIO, HTTP or SSE, filter tools per virtual key, and log every call.

FAQ

What is Model Context Protocol in simple terms?

In simple terms, the Model Context Protocol is a shared language that lets an AI assistant ask another program what it can do, then ask it to do one of those things. That program, an MCP server, wraps something like GitHub or a database, and any MCP app, such as Claude Desktop or Cursor, can use it without custom code.

What is the MCP server architecture and how does it work?

An MCP host, such as Claude Desktop, creates one MCP client for each MCP server it uses. The client sends JSON-RPC 2.0 requests over stdio or Streamable HTTP; the server lists its tools, resources and prompts, runs calls against the system it wraps, and returns results. Under the 2026-07-28 revision, no session is kept between requests.

What is the latest MCP specification version?

The latest MCP specification version is 2026-07-28, labeled Current; 2025-11-25 is now Final. The biggest change is statelessness: the initialize handshake and the Mcp-Session-Id header are gone, every request carries its protocol version in _meta, and servers must implement server/discover. Dual-era servers can still serve 2025-11-25 clients.

Where is the MCP specification on GitHub?

The Model Context Protocol specification lives in the modelcontextprotocol organization on GitHub, with one TypeScript schema file per revision and a generated JSON Schema beside it. Changes are proposed as Specification Enhancement Proposals (SEPs).

[ Keep reading ]

More on MCP Gateway

View all →