Development Choices

MCP Initialization Lifecycle

Author
Joseph TrasattiMember of technical staff
Published
Section
MCP
Length
5 min read3 sources cited

MCP initialization is a three-message boundary: the client sends `initialize` first, the server returns a supported protocol version plus its capabilities and implementation details, and the client sends `notifications/initialized`. If the client cannot use the server-selected version, it must disconnect; normal requests start only after the final notification.

MCP initialization lifecycle

The MCP initialization lifecycle is the exchange that turns a transport connection into an operating protocol session. The client opens with initialize, the server returns the version and features it will use, and the client confirms readiness with notifications/initialized before normal requests begin.

initialize is the first protocol operation

MCP startup from connection through initialization messages to normal operation
Capabilities are fixed before ordinary protocol requests begin.

The client sends initialize before any other protocol operation. The MCP lifecycle specification dated 25 November 2025 defines initialization as the first interaction between client and server because neither side can safely use optional protocol features until they have exchanged versions, capabilities and implementation information.

initialize is a JSON-RPC request rather than a notification. It therefore carries an id, and the server returns that same id in its response. Its method is exactly initialize. The required parameters are:

The MCP schema for the 25 November 2025 protocol version expresses that request shape directly: protocolVersion, capabilities and clientInfo are required members of params. The request can also carry _meta; that does not replace any of the three required members.

A minimal structural example is:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": {
      "name": "ExampleClient",
      "version": "1.0.0"
    }
  }
}

The client is not yet in normal operation after sending this message. While it waits for the server’s response, it should not send requests other than pings. In particular, it should not begin listing tools, reading resources or invoking features merely because it advertised the corresponding client capabilities.

The response fixes the session contract

The server answers initialize with an InitializeResult. That result carries four relevant parts:

The two capability objects have different directions. Client capabilities describe operations the server may ask the client to perform or facilities the client provides, such as roots, sampling or elicitation. Server capabilities describe facilities the client may use, such as prompts, resources, tools or logging. A capability can also declare a narrower sub-capability, including support for list-change notifications or resource subscriptions.

This exchange is permission by declaration, not discovery by trial. During normal operation, both parties must use only capabilities that were successfully negotiated. A server capability such as tools establishes that the feature is available; the actual tool inventory is obtained through the relevant operation after initialization. If that inventory needs to be narrowed for a particular client, treat restricting the tools an MCP server exposes as a separate access and configuration decision.

Implementation information serves a different purpose from capabilities. It identifies the software at each end; it does not grant a feature. Conversely, a capability declaration is not a product name or version check. Keeping those fields separate lets logs report which implementations connected while protocol code decides which optional messages are valid.

The server selects a supported protocol version

The client proposes a version in initialize, normally its latest supported version. If the server supports that exact version, it returns the same value. If it does not, the server returns another version that it supports, normally its own latest supported version.

The value in the server’s result is therefore the proposed session version, not a passive report of the server’s build. The client must compare it with the versions it can implement. If the client cannot use the server-selected version, it must disconnect. It must not continue with the version it originally requested, silently reinterpret messages, or proceed with a partial handshake.

That rule gives version negotiation a definite outcome: one version accepted by both parties, or no protocol session. When investigating that boundary, protocol version mismatch negotiation and diagnostics covers the version-specific checks that follow from it.

For HTTP connections, the negotiated version also leaves the JSON-RPC body: every subsequent HTTP request to the MCP server must include MCP-Protocol-Version with the selected version. That header belongs to the later transport requests, not to the initial initialize parameters. Its interaction with connection-level state is covered under MCP session management over Streamable HTTP.

initialized opens normal operation

Receiving a successful InitializeResult does not by itself open normal operation. The client first validates the returned version and records the server’s capabilities and implementation information. If it accepts the result, it sends:

{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

This message is a JSON-RPC notification: it has a method but no id, and the receiver does not send a response. That follows the JSON-RPC 2.0 specification, updated 4 January 2013, which distinguishes a request from a notification by the notification’s missing id and forbids a server response to a notification.

The absence of a response is important to the boundary. notifications/initialized is not another negotiation round and does not let the server revise its result. It tells the server that the client has finished processing initialization and is ready to use the agreed protocol contract.

Before receiving this notification, the server should not send ordinary requests. The lifecycle specification permits pings and logging messages as the exceptions. Tool calls, resource operations, prompt operations and other negotiated feature traffic belong after the notification.

Normal requests therefore begin only after the client sends notifications/initialized. From that point, both sides must respect the selected protocol version and use only the capabilities exchanged during initialization. The transport may already have been connected for the entire exchange, but connection and protocol readiness are separate states.

What to check next

Once normal operation has begun, request IDs again correlate requests with responses, while notifications continue without responses. Timeouts and cancellation apply to in-flight operational requests, but the client must not cancel its initialize request. The handling rules for later work are covered in cancelling in-flight MCP requests; initialization itself remains the fixed gate that must complete before that work starts.

Sources

  1. MCP lifecycle specification dated 25 November 2025modelcontextprotocol.io
  2. MCP schema for the 25 November 2025 protocol versionmodelcontextprotocol.io
  3. JSON-RPC 2.0 specification, updated 4 January 2013jsonrpc.org

See also