First Principles · 14 min mission

MCP Protocol Deep Dive: The Standard Behind Every Server

Read the Model Context Protocol itself — architecture, primitives, transports, and auth — so every tool's MCP screen becomes a thin skin over machinery you understand.

mcpprotocolfoundationsarchitectureoauthtransportssdkFact-checked 2026-08-22
On this page

The Model Context Protocol (MCP) is an open JSON-RPC 2.0 standard for connecting AI applications to external tools and data. The final 2026-07-28 revision changes the protocol's center of gravity: the core is stateless, every request declares its protocol context, and a server never initiates a JSON-RPC request.

This guide explains the modern wire model first, then marks the legacy session model explicitly. That boundary matters because many clients and servers still support 2025-era peers during migration.

RoleWhat it ownsSecurity boundary
HostThe AI application that creates clients, presents consent, coordinates the model, and aggregates approved contextKeeps the full conversation and cross-server context; each server receives only what the host sends
ClientThe MCP-speaking component inside the hostAdds protocol version, client capabilities, and optional client identity to every request
ServerA focused local process or remote service that exposes tools, resources, and promptsReturns capabilities and identity as data, but self-reported identity is never a trust signal
The three roles remain, but a modern exchange is request-scoped rather than a connection-scoped session.

Modern core vs. legacy session protocol

2026-07-28

Stateless core. No mandatory initialize request, initialized notification, or Mcp-Session-Id. Each request carries version and client capabilities in metadata. Servers only answer requests or emit allowed notifications.

2025-11-25 and earlier

Connection-scoped session. The client initializes once, capabilities are negotiated for the session, and servers may initiate requests such as sampling or elicitation. Kept for compatibility, not as the modern design target.

The stable server surface

The server-facing features remain tools, resources, and prompts. Their control model still tells you who chooses the capability: the model selects tools, the application reads resources, and a person selects prompts. The modern revision adds cache semantics and deterministic-list guidance without changing those basic roles.

FeatureKey methodsControl modelResult rule
Toolstools/list, tools/callModel-controlled actionA business failure is a readable tool result; malformed protocol input is a JSON-RPC error
Resourcesresources/list, resources/templates/list, resources/readApplication-controlled contextText or base64 data addressed by URI; resource-not-found now uses Invalid Params (-32602)
Promptsprompts/list, prompts/getUser-controlled templateReturns messages for explicit selection, often through a menu or slash command
Core server features in 2026-07-28.

Discovery and per-request negotiation

A 2026-era server must implement server/discover. It reports supported versions, server capabilities, optional instructions, and self-reported server identity. Calling it is optional for clients: a client may send a normal method immediately and handle an UnsupportedProtocolVersion error instead.

On stdio, server/discover is also the clean compatibility probe because there is no HTTP status code to classify the peer. A dual-era client sends discovery first; if the response shows a legacy peer, it falls back to the older initialize flow.

A modern discovery exchange
… scroll to run this session
Protocol context travels in each request. Every successful result includes resultType; identity is informational, not authenticated.
Metadata keyStatusPurpose
io.modelcontextprotocol/protocolVersionRequiredSelects the protocol revision for this request
io.modelcontextprotocol/clientCapabilitiesRequiredDeclares the client features available during this request
io.modelcontextprotocol/clientInfoRecommendedNames the client for display and diagnostics
io.modelcontextprotocol/logLevelOptionalOpts this request into protocol log notifications at the requested level
Required and recommended metadata on a modern request.

Results and multi-round-trip input

Every result now has a required resultType. Ordinary work returns complete. Work that needs more input returns input_required with one or more inputRequests. The client obtains the requested user input, model output, or roots data, then retries the original method with inputResponses.

This multi-round-trip pattern replaces server-initiated JSON-RPC requests. A server no longer sends sampling/createMessage, elicitation/create, or roots/list as a request to the client. The original method remains the unit of work across each retry.

One multi-round-trip operation

  1. Client calls the original method

    The request carries the current protocol version and the client capabilities needed for any additional input.

  2. Server returns input_required

    The result contains inputRequests describing what is missing. The server may include requestState; the client must echo that value byte-for-byte on the retry.

  3. Client resolves the inputs

    The host asks the person, calls its model, or supplies an allowed path according to the declared request type and its own policy.

  4. Client retries the original method

    The client uses a fresh JSON-RPC request ID and includes only this round's inputResponses. The server either requests another round or returns a complete result.

Transports

MCP still standardizes stdio and Streamable HTTP. The JSON-RPC semantics are the same, but framing, cancellation, and the metadata mirror differ by transport.

The two standard transports

stdio

A host launches a local subprocess. Requests arrive as newline-delimited UTF-8 JSON-RPC on stdin; responses leave on stdout. Log only to stderr. Cancellation uses notifications/cancelled, and process exit ends the connection.

Streamable HTTP

Each message is an HTTP POST to one MCP endpoint. A response is JSON or a request-scoped SSE stream. There is no protocol session ID, no GET event stream, and no SSE replay in the 2026 revision.

Removed or changedModern rule
Mcp-Session-IdRemoved. Put durable state behind explicit server-minted handles passed as normal parameters.
GET notification streamReplaced by subscriptions/listen, a long-lived POST-response stream for selected change notifications.
Last-Event-ID replayRemoved. If a response stream breaks, reconcile the operation first; retry with a new JSON-RPC request ID only when application-level idempotency or deduplication prevents duplicate side effects.
Transport-only protocol contextThe JSON body is authoritative, but routing headers are mandatory: MCP-Protocol-Version on every POST, Mcp-Method on every request, and Mcp-Name on tools/call, resources/read, and prompts/get.
Streamable HTTP changes that break copied 2025-era examples.
A modern Streamable HTTP tool call
… scroll to run this session
Routing headers mirror the authoritative body. A disagreement returns HTTP 400 with HeaderMismatch (-32020).

Subscriptions and durable tasks

Clients that want server-side change events call subscriptions/listen and opt into specific event families such as tool-list, prompt-list, resource-list, or resource-subscription changes. Request-scoped progress and log notifications remain on the response stream of the request they belong to.

Durable work is no longer an experimental core primitive. It is the official io.modelcontextprotocol/tasks extension. Its lifecycle uses tasks/get for polling, tasks/update for client input, and tasks/cancel for cancellation. There is no tasks/list method in the redesigned extension.

Area2026 statusImplementation guidance
Tools, resources, promptsCoreSafe foundation for new servers
ElicitationCore, via multi-round-trip inputUse form mode for non-secret fields and URL mode for out-of-band auth or payment
TasksOfficial extensionNegotiate io.modelcontextprotocol/tasks before returning task handles
Roots and SamplingDeprecatedUse explicit path/resource parameters and direct model-provider integration in new designs
Protocol LoggingDeprecatedUse stderr for stdio and OpenTelemetry for deployed services
Core, extension, and sunset boundaries.

Authorization for HTTP servers

Authorization remains optional and applies to HTTP transports. The MCP server is the OAuth resource server; the client is the OAuth client; the authorization server may be separate. Use Protected Resource Metadata, authorization-server discovery, PKCE, audience binding through the resource parameter, and bearer tokens only in the Authorization header.

The 2026 revision prefers Client ID Metadata Documents. Dynamic Client Registration is deprecated for backwards compatibility. Authorization servers should return an issuer identifier as defined by RFC 9207; clients must validate a present issuer before redeeming the code and must key stored client credentials by that issuer.

Migrate a 2025-era implementation deliberately

  1. Upgrade the SDK before rewriting the wire layer

    The stable TypeScript and Python v2 SDKs implement the 2026 protocol and carry compatibility support. Use their migration guides instead of recreating version negotiation by hand.

  2. Remove connection-scoped protocol state

    Delete assumptions around initialize, initialized, Mcp-Session-Id, GET event streams, and Last-Event-ID. Keep business state behind explicit handles or durable storage.

  3. Adopt discovery, metadata, and result envelopes

    Implement server/discover, ensure each request is evaluated against its protocol metadata, and return complete or input_required results.

  4. Move notifications and long-running work

    Use subscriptions/listen for change events and negotiate the tasks extension for durable operations.

  5. Retire deprecated features from new designs

    Replace roots, sampling, protocol logging, and Dynamic Client Registration while preserving only the compatibility paths your deployed clients need.

Knowledge check

A new 2026-07-28 server needs the user to approve a write while handling tools/call. What should it do?

Reach the end and this star joins your charted sky.