The session lifecycle
An MCP session always follows the same four phases:
- Initialize — client → server
initializerequest. - Capability negotiation — both sides declare what they support.
- Initialized — client sends
notifications/initializedand the session is live. - Shutdown — either side closes the transport. No formal method.
The initialize handshake
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"roots": { "listChanged": true },
"sampling": {},
"elicitation": { "form": {} }
},
"clientInfo": { "name": "claude-desktop", "version": "0.7.0" }
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-11-25",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true, "listChanged": true },
"logging": {}
},
"serverInfo": { "name": "weather", "version": "1.0.0" },
"instructions": "Use get_forecast for 7-day outlooks."
}
}
{ "jsonrpc": "2.0", "method": "notifications/initialized" }
Capability matrix
| Side | Capability | What it unlocks |
|---|---|---|
| Client | roots | Server may call roots/list. |
| Client | sampling | Server may call sampling/createMessage. |
| Client | elicitation | Server may call elicitation/create. |
| Client | tasks | Server may emit task-augmented requests. |
| Server | tools | Client may call tools/list and tools/call. |
| Server | resources | Client may list, read, and (optionally) subscribe. |
| Server | prompts | Client may list and get prompts. |
| Server | logging | Server may emit notifications/message. |
| Server | completions | Client may call completion/complete. |
Rule: the server MUST NOT call a feature the client didn't advertise, and vice versa.
Sub-capabilities
listChanged— emitnotifications/tools/list_changed(or resources/prompts) when the list changes.subscribe— acceptresources/subscribeand pushnotifications/resources/updated.form/url— which elicitation modes the client implements.
Version negotiation
The client proposes a protocolVersion (a calendar string like 2025-11-25). The server returns its supported version. If they don't match the client MUST disconnect.
Operation & shutdown
During operation both sides MUST respect the negotiated version and capabilities. ping works as a lightweight keepalive. There is no formal shutdown method — closing the transport ends the session.
Quick summary
- Three-message handshake: initialize → result → initialized
- Both sides declare capabilities — never use features that weren't negotiated
- Sub-capabilities (listChanged, subscribe, form/url) refine the contract
- Closing the transport is the only "shutdown"