@@ -6,6 +6,7 @@ Welcome to the MCP Client implementation! This document provides a comprehensive
66
77- [ Overview] ( #overview )
88- [ Core Architecture] ( #core-architecture )
9+ - [ Session Status Lifecycle] ( #session-status-lifecycle )
910- [ Storage Architecture] ( #storage-architecture )
1011- [ Key Use Cases & Flows] ( #key-use-cases--flows )
1112- [ Architectural Decisions] ( #architectural-decisions )
@@ -336,6 +337,196 @@ This example demonstrates:
336337Each primitive solves a specific architectural challenge. You can mix and match them based on your deployment model (CLI vs web vs serverless).
337338
338339
340+ ---
341+
342+ ## Session Status Lifecycle
343+
344+ Sessions track their connection state through a comprehensive status lifecycle. This allows applications to handle connection failures gracefully without exceptions.
345+
346+ ** Design Philosophy:**
347+
348+ The ` connect() ` method ** does not raise exceptions** for connection failures. Instead, it sets the appropriate session status. This design enables:
349+ - Connecting to multiple servers where some may be unavailable
350+ - Graceful failure handling without try/catch blocks
351+ - Clear status inspection to determine appropriate actions
352+
353+ ### Status States
354+
355+ Sessions can be in one of the following states:
356+
357+ | State | Category | Description |
358+ | -------| ----------| -------------|
359+ | ` INITIALIZING ` | Initial | Session created but not yet connected |
360+ | ` CONNECTING ` | Active | Establishing connection to server |
361+ | ` AUTHENTICATING ` | Active | Connection established, authentication in progress |
362+ | ` AUTH_PENDING ` | Pending | Waiting for external auth (e.g., OAuth callback) |
363+ | ` CONNECTED ` | Active | Fully connected and operational |
364+ | ` RECONNECTING ` | Recovery | Attempting to reconnect after failure |
365+ | ` DISCONNECTING ` | Disconnection | Gracefully closing connection |
366+ | ` DISCONNECTED ` | Terminal | Clean disconnect, can reconnect |
367+ | ` CONNECTION_FAILED ` | Failure | Failed to establish connection |
368+ | ` SERVER_UNREACHABLE ` | Failure | Server not responding/not available |
369+ | ` AUTH_FAILED ` | Failure | Authentication failed |
370+ | ` FAILED ` | Failure | General failure state |
371+
372+ ### Status Categories
373+
374+ Status states are organized into logical groups:
375+
376+ ** Active States:** Session is attempting or maintaining a connection
377+ - ` CONNECTING ` , ` AUTHENTICATING ` , ` CONNECTED ` , ` RECONNECTING `
378+
379+ ** Failure States:** Session encountered an error
380+ - ` AUTH_FAILED ` , ` CONNECTION_FAILED ` , ` SERVER_UNREACHABLE ` , ` FAILED `
381+
382+ ** Recoverable States:** Failure states that can be retried
383+ - ` CONNECTION_FAILED ` , ` SERVER_UNREACHABLE ` , ` AUTH_FAILED `
384+
385+ ** Terminal States:** Session is not connected and requires action
386+ - ` DISCONNECTED ` , ` FAILED `
387+
388+ ** Pending States:** Session is waiting for external action
389+ - ` AUTH_PENDING `
390+
391+ ### Status Properties
392+
393+ Sessions provide convenient properties for checking status:
394+
395+ ``` python
396+ session = client.sessions[" my-server" ]
397+
398+ # Check if ready to use
399+ if session.is_operational: # Only true when CONNECTED
400+ result = await client.call_tool(" my_tool" , {})
401+
402+ # Check for failures
403+ if session.is_failed: # Any failure state
404+ print (f " Connection failed: { session.status} " )
405+ if session.can_retry: # Recoverable failure
406+ await client.connect(server = " my-server" , force_reconnect = True )
407+
408+ # Check if waiting for user action
409+ if session.requires_user_action: # AUTH_PENDING
410+ challenges = await client.get_auth_challenges()
411+ # Handle OAuth flow
412+
413+ # Check if currently connecting
414+ if session.is_connecting: # CONNECTING, AUTHENTICATING, or RECONNECTING
415+ print (" Connection in progress..." )
416+
417+ # Check connection health
418+ is_healthy = await session.check_connection_health()
419+ if not is_healthy:
420+ print (f " Connection unhealthy: { session.status} " )
421+ ```
422+
423+ ### Auto-Reconnection on Auth Completion
424+
425+ ** Important:** Sessions automatically reconnect when authentication completes. You ** do not** need to manually call ` connect() ` after OAuth finishes.
426+
427+ ** How it works:**
428+ 1 . Session enters ` AUTH_PENDING ` state when authentication is required
429+ 2 . Session subscribes to the coordinator's completion events
430+ 3 . When OAuth callback completes, the coordinator notifies all subscribers
431+ 4 . Session receives notification and automatically reconnects
432+ 5 . Status updates from ` AUTH_PENDING ` → ` CONNECTING ` → ` AUTHENTICATING ` → ` CONNECTED `
433+
434+ ### Usage Patterns
435+
436+ ** Pattern 1: Check Status After Connection**
437+
438+ ``` python
439+ await client.connect()
440+
441+ for server_name, session in client.sessions.items():
442+ if session.is_operational:
443+ print (f " { server_name} : Ready " )
444+ elif session.is_failed:
445+ print (f " { server_name} : Failed - { session.status} " )
446+ elif session.requires_user_action:
447+ print (f " { server_name} : Requires authentication " )
448+ ```
449+
450+ ** Pattern 2: Handle Mixed Server Availability**
451+
452+ ``` python
453+ # Connect to all servers (some may fail)
454+ await client.connect()
455+
456+ # Use only operational servers
457+ operational_servers = [
458+ name for name, session in client.sessions.items()
459+ if session.is_operational
460+ ]
461+
462+ if operational_servers:
463+ tools = await client.list_tools()
464+ # Work with available servers
465+ else :
466+ print (" No servers available" )
467+ ```
468+
469+ ** Pattern 3: Retry Failed Connections**
470+
471+ ``` python
472+ await client.connect()
473+
474+ for server_name, session in client.sessions.items():
475+ if session.is_failed and session.can_retry:
476+ print (f " Retrying { server_name} ... " )
477+ await client.connect(server = server_name, force_reconnect = True )
478+ ```
479+
480+ ** Pattern 4: Health Check for Long-Running Sessions**
481+
482+ ``` python
483+ # Periodically check connection health
484+ async def monitor_connections (client ):
485+ while True :
486+ await asyncio.sleep(60 ) # Check every minute
487+
488+ for server_name, session in client.sessions.items():
489+ if session.is_operational:
490+ is_healthy = await session.check_connection_health()
491+ if not is_healthy:
492+ print (f " { server_name} unhealthy, reconnecting... " )
493+ await client.connect(server = server_name, force_reconnect = True )
494+ ```
495+
496+ ### State Transition Examples
497+
498+ ** Successful Connection (No Auth):**
499+ ```
500+ INITIALIZING → CONNECTING → AUTHENTICATING → CONNECTED
501+ ```
502+
503+ ** Connection with OAuth:**
504+ ```
505+ INITIALIZING → CONNECTING → AUTHENTICATING → AUTH_PENDING
506+ (user completes OAuth)
507+ → CONNECTING → AUTHENTICATING → CONNECTED
508+ ```
509+
510+ ** Server Unreachable:**
511+ ```
512+ INITIALIZING → CONNECTING → SERVER_UNREACHABLE
513+ (retry)
514+ → CONNECTING → AUTHENTICATING → CONNECTED
515+ ```
516+
517+ ** Graceful Disconnect:**
518+ ```
519+ CONNECTED → DISCONNECTING → DISCONNECTED
520+ ```
521+
522+ ** Connection Lost During Operation:**
523+ ```
524+ CONNECTED → CONNECTION_FAILED
525+ (health check detects failure)
526+ ```
527+
528+ See [ ` SESSION_STATUS_DESIGN.md ` ] ( SESSION_STATUS_DESIGN.md ) and [ ` SESSION_LIFECYCLE.md ` ] ( SESSION_LIFECYCLE.md ) for detailed state transitions and sequence diagrams.
529+
339530---
340531
341532## Storage Architecture
@@ -635,11 +826,13 @@ sequenceDiagram
635826
636827 CallbackProcess-->>Browser: "Authorization successful"
637828
638- Note over Session,CallbackProcess: Process C - Reconnection
829+ Note over Session,CallbackProcess: Process C - Auto- Reconnection (Event-Driven)
639830
640- Session->>Session: await connect()
831+ Coordinator->>Session: on_completion_handled(event)
832+ Note over Session: Session was subscribed when AUTH_PENDING
833+ Session->>Session: Automatically await connect()
641834 Session->>Storage: get("tokens")
642- Storage-->>Session: Tokens available, connect with auth
835+ Storage-->>Session: Tokens available, CONNECTED!
643836```
644837
645838** Key Points:**
@@ -649,6 +842,7 @@ sequenceDiagram
649842- Different process can handle callback
650843- StarletteAuthCoordinator ** doesn't block** on redirect (returns HTTP response)
651844- Same strategy code as LocalAuthCoordinator, different coordinator behavior
845+ - ** Auto-reconnection** : Session subscribes to completion events and reconnects automatically (no manual ` connect() ` needed)
652846
653847---
654848
@@ -1120,6 +1314,7 @@ Clear boundaries help maintain clean architecture.
11201314 - Manage lifecycle (connect/disconnect)
11211315 - Create server-specific namespace
11221316 - Detect and expose auth challenges
1317+ - Subscribe to auth completion events (auto-reconnect)
11231318 - Delegate to upstream MCP ClientSession
11241319- ** Does NOT** :
11251320 - Implement transport (delegates to Connection)
0 commit comments