Client: Session Management
Relevant source files
The following files were used as context for generating this wiki page:
The ClientSession class is the primary interface for a client to establish and manage a stateful, long-lived communication session with a Model Context Protocol (MCP) server. It provides a high-level, transport-agnostic API for sending requests, receiving responses, and handling server-initiated messages such as notifications and requests. The session manages the entire communication lifecycle, from the initial handshake to termination, abstracting away the underlying transport complexities.
The ClientSession is designed to be used as an asynchronous context manager, ensuring that resources are properly initialized and cleaned up. It operates over various transports like StreamableHTTP and WebSockets by consuming generic read and write streams, making it a versatile component for building MCP clients.
Core Concepts
The ClientSession Class
The ClientSession class orchestrates all client-side communication with an MCP server. It is responsible for serializing outgoing requests, deserializing incoming messages, and dispatching them to the appropriate handlers.
Sources: src/mcp/client/session.py
Class Diagram
This diagram shows the key components and methods of the ClientSession class.
Sources: src/mcp/client/session.py:38-415
Constructor Parameters
The ClientSession is initialized with streams and optional callbacks for handling server-initiated messages.
| Parameter | Type | Description |
|---|---|---|
read_stream | MemoryObjectReceiveStream | An asynchronous stream for receiving messages from the server. |
write_stream | MemoryObjectSendStream | An asynchronous stream for sending messages to the server. |
message_handler | Callable (optional) | A callback to handle server-initiated notifications and requests that are not direct responses to a client request. |
sampling_callback | Callable (optional) | A specific callback to handle message/create requests from the server, typically for LLM interaction. |
elicitation_callback | Callable (optional) | A specific callback to handle $/elicit requests from the server, used for interactive user prompts. |
Sources: src/mcp/client/session.py:65-81
Session Lifecycle
A ClientSession follows a well-defined lifecycle, managed effectively using an async with block. This ensures that the connection is established, used, and then gracefully terminated.
- Creation: A transport-specific client (e.g.,
streamablehttp_clientorwebsocket_client) is used to create the read/write streams. - Initialization: The
ClientSessionis instantiated with these streams. - Handshake: The client must call
session.initialize()to perform the initial handshake with the server, exchanging capabilities. - Interaction: The client sends requests (e.g.,
call_tool) and receives responses. The session runs a background task to listen for and process incoming messages. - Termination: When the
async withblock exits, theclose()method is called, which terminates the session on the server (if applicable) and closes the streams.
Typical Lifecycle Flow
The following sequence diagram illustrates the standard lifecycle of a client session.
Key Operations
Initialization
Every session must begin with an initialize() call. This method sends the client's information and capabilities to the server and receives the server's information in return. This handshake is mandatory before any other requests can be sent.
# tests/shared/test_streamable_http.py:772-783
async with streamablehttp_client(f"{basic_server_url}/mcp") as (
read_stream,
write_stream,
_,
):
async with ClientSession(
read_stream,
write_stream,
) as session:
# Test initialization
result = await session.initialize()
assert isinstance(result, InitializeResult)
assert result.serverInfo.name == SERVER_NAME
Sources: src/mcp/client/session.py:102-114, tests/shared/test_streamable_http.py:772-783
Sending Requests
The ClientSession provides a set of high-level async methods for common MCP operations. These methods abstract the underlying send_request call.
| Method | Description | Returns |
|---|---|---|
list_tools() | Lists the tools available on the server. | ListToolsResult |
call_tool(...) | Executes a specific tool with given arguments. | CallToolResult |
list_resources() | Lists the resources available on the server. | ListResourcesResult |
read_resource(...) | Reads the content of a resource specified by a URI. | ReadResourceResult |
list_prompts() | Lists the available prompts on the server. | ListPromptsResult |
get_prompt(...) | Renders a specific prompt with given arguments. | GetPromptResult |
complete(...) | Requests completion suggestions for a resource or prompt argument. | CompletionResult |
send_ping() | Sends a ping to the server to check connectivity. | EmptyResult |
Sources: src/mcp/client/session.py:116-291
Handling Server-Initiated Messages
A key feature of MCP is the server's ability to send messages to the client that are not direct responses to a request. The ClientSession handles these through optional callbacks provided during instantiation.
Message Handler
The generic message_handler is a powerful callback that receives all server-initiated messages. This includes:
ServerNotification: For messages likewindow/logMessageor$/progress.ServerRequest: For when the server requests something from the client, like$/elicitormessage/create.Exception: For any errors encountered during message processing.
This handler is crucial for observing server state changes and handling custom notifications.
Sources: src/mcp/client/session.py:71-73, tests/shared/test_streamable_http.py:863-870
Sampling and Elicitation
For the common server-to-client requests (message/create and $/elicit), ClientSession provides dedicated callbacks for cleaner implementation.
sampling_callback: Invoked when the server sends amessage/createrequest. The client is expected to generate a response (e.g., from an LLM) and return aCreateMessageResult.elicitation_callback: Invoked for$/elicitrequests, which are used to ask the user for input or confirmation. The client returns anElicitResult.
The following diagram shows a server-initiated sampling request flow.
Transport Integration
ClientSession is decoupled from the network transport. It relies on transport-specific factory functions to provide the necessary read and write streams.
StreamableHTTP Transport
The streamablehttp_client function manages sessions over HTTP. It performs an initial POST request to create the session and then a GET request to establish a Server-Sent Events (SSE) stream for bidirectional communication. It manages HTTP headers like mcp-session-id and mcp-protocol-version automatically.
This diagram shows the session setup for StreamableHTTP.
WebSocket Transport
The websocket_client function provides streams over a WebSocket connection. It handles the WebSocket handshake and wraps the connection in the required memory streams for ClientSession to consume.
Sources: src/mcp/client/websocket.py, tests/shared/test_ws.py:126-136
Advanced Features
Progress Notifications
The client can both send and receive progress notifications, which is useful for long-running tasks.
- Receiving Progress: A
progress_callbackcan be passed to methods likecall_tool. This callback will be invoked whenever the server sends a$/progressnotification related to that request. - Sending Progress: The client can call
session.send_progress_notification()to report its own progress to the server, which is useful in scenarios like file uploads. Themcp.shared.progress.progresscontext manager provides a convenient way to manage and report progress.
Sources: tests/shared/test_progress_notifications.py, src/mcp/client/session.py:202-205
Session Resumption (StreamableHTTP)
The StreamableHTTP transport supports session resumption. If a client disconnects unexpectedly, it can reconnect to the same session and receive any messages it missed, provided the server supports it with an EventStore.
This is managed via the ClientMessageMetadata object passed to send_request.
on_resumption_token_update: A callback that receives alast-event-idfrom the server's SSE stream. The client should persist this token.resumption_token: When reconnecting, the client provides the last known token to the server, which then replays all events that occurred after that token.
Sources: tests/shared/test_streamable_http.py:943-1049
Conclusion
The ClientSession is the cornerstone of the MCP Python SDK's client-side functionality. It offers a robust, developer-friendly abstraction for managing complex, stateful interactions with an MCP server. By decoupling session logic from the underlying transport, it provides flexibility while handling the core protocol mechanics of request/response mapping, server-initiated messages, and advanced features like progress reporting and session resumption. Its asynchronous, callback-driven design makes it well-suited for building responsive and powerful client applications.