# MCP's initialize handshake negotiates version and capabilities, and 2026-07-28 replaces it

> Up to MCP 2025-11-25, every connection opens with an initialize request, an initialize response and a notifications/initialized notification; revision 2026-07-28 removes the handshake and puts version and capabilities on every request.

## Answer

In MCP revisions up to **2025-11-25**, every connection starts with a three-step handshake. The client sends an `initialize` request with its `protocolVersion`, `capabilities` and `clientInfo`. The server replies with the version it will use, its own `capabilities` and `serverInfo`. The client then sends `notifications/initialized`. The latest revision, **2026-07-28**, removes this handshake. Each request now carries its version and capabilities in `_meta`, and servers must answer `server/discover`. This page describes the 2025-11-25 handshake and notes what 2026-07-28 changed.

## Details

### The three messages (2025-11-25)

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

```json
{"jsonrpc":"2.0","id":1,"result":{
  "protocolVersion":"2025-11-25",
  "capabilities":{"tools":{"listChanged":true}},
  "serverInfo":{"name":"ExampleServer","version":"1.0.0"},
  "instructions":"Optional instructions for the client"}}
```

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

`clientInfo` and `serverInfo` also accept optional fields such as `title`, `description`, `icons` and `websiteUrl`.

### Version negotiation

- The client MUST send a version it supports, and SHOULD send its latest one.
- If the server supports that version, it MUST return the same one. If not, it returns another version it supports, and SHOULD pick its latest.
- If the client cannot use the version the server returns, it SHOULD disconnect.
- Over HTTP, the client then sends `MCP-Protocol-Version: <version>` on every later request.

### Capabilities

Capabilities decide which optional features the session can use. Neither side may use a feature that was not negotiated.

| Side | Examples |
|---|---|
| Client | `roots`, `sampling`, `elicitation`, `tasks`, `experimental` |
| Server | `tools`, `resources`, `prompts`, `logging`, `completions`, `tasks`, `experimental` |

Sub-flags refine these. `listChanged` means the side sends list-change notifications. `subscribe` (resources only) allows subscribing to single items.

### What may be sent before initialization completes

- Before the server has answered `initialize`, the client SHOULD NOT send requests other than `ping`.
- Before the server receives `notifications/initialized`, it SHOULD NOT send requests other than `ping` and logging.

A common pitfall is a hand-written client that sends `tools/list` right after `initialize` to save a round trip. That breaks the first rule above. Wait for the `initialize` response, send `notifications/initialized`, and then list tools.

### What 2026-07-28 changed

| 2025-11-25 (legacy) | 2026-07-28 (modern) |
|---|---|
| `initialize` + `notifications/initialized` once per connection | No handshake. Every request carries `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` in `_meta` |
| `clientInfo` in `initialize` | `io.modelcontextprotocol/clientInfo` on each request (SHOULD) |
| `serverInfo` in `InitializeResult` | `io.modelcontextprotocol/serverInfo` in each result's `_meta` (SHOULD) |
| Server returns a different version | Server returns `UnsupportedProtocolVersionError` (`-32022`) with a `supported` list |
| — | Servers MUST implement `server/discover`, which returns `supportedVersions`, `capabilities` and optional `instructions` |

A dual-era server answers `initialize` with legacy behavior and answers requests that carry modern `_meta` statelessly. On stdio, a client that supports both eras SHOULD send `server/discover` first. If it gets any error that is not a recognized modern error, or no reply, it falls back to `initialize`.

## See also

- [[mcp-json-rpc-format]]
- [[mcp-streamable-http-sessions]]
- [[mcp-connection-errors]]
- [[mcp-tools-resources-prompts]]

## Sources

- [MCP Specification 2025-11-25 — Lifecycle](https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle)
- [MCP Specification 2026-07-28 — Versioning and Compatibility](https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning)
- [MCP Specification 2026-07-28 — server/discover](https://modelcontextprotocol.io/specification/2026-07-28/server/discover)
- [MCP Specification 2026-07-28 — Key changes](https://modelcontextprotocol.io/specification/2026-07-28/changelog)

## Sources

- [MCP Specification 2025-11-25 — Lifecycle](https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle)
- [MCP Specification 2026-07-28 — Versioning and Compatibility](https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning)
- [MCP Specification 2026-07-28 — server/discover](https://modelcontextprotocol.io/specification/2026-07-28/server/discover)
- [MCP Specification 2026-07-28 — Key changes](https://modelcontextprotocol.io/specification/2026-07-28/changelog)