An MCP session has four phases: connect, initialize, operate, shutdown. The first one is transport-specific (open a stdio pipe, open an HTTP connection); the last one is graceful close. The middle two carry all the protocol weight.
Initialize is the handshake. The client sends an initialize request advertising its protocolVersion, its capabilities (e.g. sampling, roots, elicitation), and its clientInfo. The server replies with the same envelope: the negotiated version (the highest both sides understand), its own capabilities, and serverInfo. After this exchange, both sides have a precise, written agreement about what the rest of the session can use.
The handshake matters because it is what lets the protocol evolve without lock-step upgrades. A new client can talk to an old server and only use the capabilities both advertise. A new server can ship an experimental capability that older clients ignore. Capabilities in MCP play the role version numbers play in HTTP/REST — they are how the parts move at different speeds without breaking each other.
Operate is everything after the handshake: tool calls, resource reads, prompt requests, sampling round-trips, log messages, progress events. Shutdown is a goodbye that cleans up resources on both sides; servers should treat shutdown as a chance to flush logs and release file handles.