Getting Started2026-07-202 min read

How MCP Servers Work: The Complete Technical Breakdown

MCP's lifecycle has three real, distinct phases — initialization/capability negotiation, normal operation, and shutdown — and understanding the handshake specifically explains a lot of otherwise-confusing client behavior.

Technical discussionCode sharing section

MCP uses JSON-RPC 2.0 as its message format, but the interesting part of "how it works" isn't the wire format — it's the three-phase lifecycle every connection goes through, and the capability negotiation that happens before a single tool is ever called.

Phase 1: Initialization and Capability Negotiation

A connection starts with the client sending an initialize request, including the protocol version it supports and a list of its own capabilities. The server responds with its own supported protocol version and capabilities — tools, resources, prompts, and whether it supports things like resource subscriptions. If the client and server can't agree on a compatible protocol version, initialization fails right here, before either side has learned anything about the other's actual tools.

Once the server's response arrives, the client sends a notifications/initialized notification confirming it's ready — only after that does the connection move into normal operation.

Phase 2: Normal Operation

  1. Client calls tools/list (or resources/list, prompts/list) to discover what's actually available
  2. Client calls tools/call with a specific tool name and arguments matching that tool's declared schema
  3. Server executes the tool and returns a result — or an error, at either the JSON-RPC protocol level or the tool-execution level via isError: true
  4. If the server supports it, it can send notifications/tools/list_changed if the available tool set changes mid-session — a plugin being loaded, for instance

Phase 3: Shutdown

Either side can end the session — closing the transport connection (stdio process exit, HTTP connection close) is generally sufficient; there's no elaborate goodbye handshake required by the spec.

Transport Is a Separate Concern From This Lifecycle

This entire lifecycle — initialize, operate, shut down — happens identically regardless of whether the underlying transport is stdio (local process) or Streamable HTTP (remote server). The transport just carries the JSON-RPC messages; it doesn't change what messages get sent or in what order.

A Real Production Example

Real production servers built by companies like Zerodha (Kite MCP) and Stripe follow exactly this lifecycle — capability negotiation up front determines what tools a given client sees, which is also how Zerodha's hosted instance can expose a smaller, safer tool set than its self-hosted full version: the server simply advertises different tool lists during the same initialization phase depending on which deployment mode it's running in.

Join the Discussion

Code Snippets (0)

No code snippets shared yet. Be the first to contribute!