Protocol

MCP architecture

MCP is a JSON-RPC 2.0 protocol with three actors (Host, Client, Server), three transport options (stdio, SSE, HTTP), and a capability-negotiation handshake that runs at session start. The structural analog is the Language Server Protocol (LSP) applied to AI clients and capability servers.

The three actors

Every MCP session involves three roles. They sit at different layers and a single process can play more than one of them at once.

Host

The LLM application the user runs (Claude Desktop, Claude Code, Cursor, Windsurf, ChatGPT, Continue, Cline, Zed). The host owns the model context and the user-facing surface.

Client

The connector inside the host that speaks MCP. One client instance per connected server. The client manages the JSON-RPC session and the capability negotiation.

Server

The external process that exposes Resources, Tools, or Prompts. Servers run locally as child processes or remotely behind HTTP. The server publishes capabilities; the client invokes them.

The wire format

MCP runs on JSON-RPC 2.0. Every protocol interaction takes one of three message shapes, and either actor can originate any of them.

  • Requests. A method string, a params object or array, and a unique id. The receiver must reply with a response that carries the matching id.
  • Responses. The matching id plus either a result object on success or an error object. Errors use standardized JSON-RPC codes (-32601 Method Not Found, -32700 Parse Error, -32600 Invalid Request) plus MCP-specific application errors.
  • Notifications. A method and params with no id. One-way; the receiver sends no reply. MCP uses these for state-change events like notifications/tools/list_changed and notifications/resources/updated.

JSON-RPC is transport-independent and ships no authentication or authorization primitives. Security and access control are the transport's job (HTTP headers and OAuth 2.1 for remote servers, OS user permissions for local stdio servers).

The initialize handshake

Every session begins with capability negotiation. The client opens the connection and sends an initialize request carrying the protocol version it speaks and the client-side capabilities it advertises: roots (filesystem boundaries the server may read), sampling (servers can request the host LLM to perform a completion), and elicitation (servers can request the client to prompt the user for more input).

The server responds with its own capability set: which of Resources, Tools, and Prompts it exposes, plus any negotiated parameters (logging level, experimental flags). The client acknowledges with a notifications/initialized notification, and the session enters the discovery phase.

Both sides only invoke methods the other side advertised. A server that did not declare the Tools capability never receives a tools/list request; a client that did not declare sampling never receives a sampling/createMessage call from the server.

Transport variants

JSON-RPC is transport-independent. MCP defines three transports and picks per deployment topology.

stdio

The client spawns the server as a child process and exchanges newline-delimited JSON over stdin and stdout. The default for local servers. Process lifecycle is the connection lifecycle.

SSE

Server-Sent Events over HTTP for server-to-client streaming (responses, notifications, progress). Client-to-server requests are sent as out-of-band HTTP POSTs to a separate endpoint negotiated at connection time.

HTTP

Stateless client-to-server JSON-RPC over HTTP POST. Suits remote servers behind a load balancer. Notifications and streaming responses require the SSE variant or the newer streamable-HTTP profile.

Session lifecycle

A session passes through four phases. The transitions are deterministic; the client drives them.

  1. Handshake. initialize request, capability exchange, notifications/initialized acknowledgment.
  2. Discovery. The client calls tools/list, resources/list, and prompts/list against whatever the server advertised. The server returns schemas the client uses to format invocations.
  3. Invocation. The client calls tools/call, resources/read, prompts/get as the user (or the model on the user's behalf) directs. Either side can emit list_changed notifications when their advertised capabilities shift.
  4. Shutdown. The client sends a shutdown request followed by an exit notification. The server closes the transport and releases resources.

Cross-actor utilities run alongside the main flow: configuration, progress tracking via notifications/progress, request cancellation via notifications/cancelled, structured error reporting, and logging via notifications/message.

The _meta extension mechanism

JSON-RPC requests and responses reserve a _meta property for out-of-band metadata. The protocol formalizes it with namespace prefixes so extensions ride alongside the core schema without breaking it. The MCP Apps pattern uses _meta.ui.resourceUri on a tool definition to point the client at a UI resource. When the client invokes the tool and sees the metadata, it fetches the resource (typically text/html;profile=mcp-app) via resources/read and renders it in a sandboxed iframe alongside the tool's text response.

Related on MCPowered