What it does
The `initialize` request is always the first message sent by the client in an MCP session. The client transmits its proposed `protocolVersion` string (e.g. `"2024-11-05"`), a `ClientCapabilities` object advertising which optional features it supports (such as `roots`, `sampling`, or `experimental` namespaces), and a `clientInfo` block containing a human-readable `name` and `version`. No other requests or notifications may be sent by either party until the full handshake completes. The server responds synchronously with an `InitializeResult` that contains the server's chosen `protocolVersion` (it must select a version it can honor — typically the client's proposed version or an older one it also supports), a `ServerCapabilities` object, and a `serverInfo` block. After the client receives this result it must send a `notifications/initialized` notification to signal readiness; only after that notification arrives can the server begin processing further requests. If the client proposes a `protocolVersion` the server cannot support, the server should return a JSON-RPC error with code `-32602` (Invalid params) and a message describing the version mismatch, after which the transport should be closed. Both sides must treat any non-`initialize` message received before the handshake completes as a protocol error. Capability fields declared here gate all subsequent feature negotiation — a capability absent from `InitializeResult` must not be relied upon by the client for the lifetime of that session.
When to use
Once, at the start of each session.
When NOT to use
Never mid-session — that's a protocol violation.
Notes
Version negotiation is strict
The server must echo back a `protocolVersion` it actually implements. If it cannot support any version the client proposed, it returns error code `-32602` and closes the connection. Clients should not attempt to continue the session after receiving a version-mismatch error — the transport must be torn down and re-established with a compatible version.
Capabilities gate all subsequent features
Every optional MCP feature (tools, resources, prompts, sampling, roots, logging) is gated by the `ServerCapabilities` returned here. If a capability key is absent or `false`, the client must not send the corresponding requests for the lifetime of that session. Attempting to call, for example, `tools/list` when `capabilities.tools` was not advertised is a protocol violation and will produce an `MethodNotFound` (-32601) error on well-behaved servers.
notifications/initialized must precede all other traffic
The client is responsible for sending `notifications/initialized` immediately after processing `InitializeResult`. Servers that receive any request other than `initialize` before this notification should return a `-32600` (Invalid Request) error. In practice, some SDKs handle this automatically, but if you are writing a raw client you must sequence this notification explicitly before queuing any tool or resource calls.
No retry on initialize — reconnect instead
Unlike idempotent data-fetching calls, `initialize` must not be retried on the same transport connection after a failure. A transport error or version-mismatch error requires closing the connection entirely and opening a new one. Re-sending `initialize` on an already-initialized connection is a protocol violation and most servers will reject it with `-32600`.
clientInfo is advisory, not authenticated
The `name` and `version` fields in `clientInfo` are purely informational — servers should not use them for access control decisions. If your server needs to enforce client identity, implement that at the transport layer (e.g., mutual TLS or an auth token in the HTTP headers) before the MCP handshake begins. The `initialize` method itself provides no authentication mechanism.
Request parameters
| Name | Type | Purpose |
|---|---|---|
| protocolVersion | string | e.g. '2025-11-25'. |
| capabilities | ClientCapabilities | Optional features the client supports. |
| clientInfo | Implementation | Client identity. |
Response fields
| Name | Type | Purpose |
|---|---|---|
| protocolVersion | string | Negotiated version. |
| capabilities | ServerCapabilities | Server features. |
| serverInfo | Implementation | Server identity. |
| instructions | string? | Server hints for the LLM. |
Examples
Initialize handshake
Request:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": { "protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": { "name": "client", "version": "1.0.0" } } }
Response:
{ "jsonrpc": "2.0", "id": 1, "result": { ... } }
Common mistakes
❌ Sending tools/list before initialize
✅ Wait for the result and send notifications/initialized first.