MP-201c · Module 1

Session Management

3 min read

Every MCP connection begins with a capability negotiation. The client sends an initialize request declaring the protocol version it supports and the capabilities it offers (roots, sampling). The server responds with its own capabilities (tools, resources, prompts) and the protocol version it will use. This handshake is mandatory — no tool calls, no resource reads, nothing happens until both sides agree on what they can do. Only after the client sends the initialized notification is the session considered active.

Connection lifecycle management separates reliable MCP deployments from fragile ones. Keepalive mechanisms vary by transport: stdio relies on process liveness (if the child process exits, the connection is dead), while Streamable HTTP uses the SSE stream's built-in heartbeat or application-level ping/pong messages. For long-lived sessions, implement a heartbeat interval — a periodic no-op message that confirms both sides are still responsive. Without it, you discover a dead connection only when the next real request times out.

  1. Implement the handshake Handle initialize and initialized as the mandatory first exchange. Reject any requests that arrive before initialization completes.
  2. Add heartbeat monitoring For stdio, check process.alive periodically. For HTTP, send a ping event on the SSE stream every 30 seconds. If three consecutive pings go unacknowledged, consider the session dead.
  3. Build graceful shutdown On SIGTERM, stop accepting new requests, wait up to 10 seconds for in-flight requests to complete, send a close notification, then exit. Log any requests that were abandoned.