You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: address PR review feedback on transport abstractions
- Remove __init__ and WireMessageT from AbstractBaseSession, making it a pure
abstract interface without state management. BaseSession now owns all state.
- Convert BaseClientSession from ABC to @runtime_checkable Protocol with structural
subtyping. This eliminates the diamond inheritance in ClientSession and removes
the need for inheritance to satisfy the interface.
- Add missing methods to BaseClientSession protocol: complete(), set_logging_level(),
and explicitly declare send_request(), send_notification(), send_progress_notification().
- Remove commented-out import in context.py.
- Add comprehensive tests for BaseClientSession protocol satisfaction and E2E usage.
- Document all breaking changes in docs/migration.md including:
* ClientRequestContext type change to BaseClientSession
* Generic callback protocols (SamplingFnT[ClientSession], etc.)
* SessionT renamed to SessionT_co
* AbstractBaseSession simplification
* BaseClientSession Protocol conversion
Fixes structural issues identified in PR review:
- AbstractBaseSession no longer manages state it doesn't own
- Eliminates double initialization of _response_streams and _task_group
- Removes Any leakage for WireMessageT
- BaseClientSession now earns its place as a pure interface
The session hierarchy has been refactored to support pluggable transport implementations. This introduces several breaking changes:
477
+
478
+
#### `ClientRequestContext` type changed
479
+
480
+
`ClientRequestContext` is now `RequestContext[BaseClientSession]` instead of `RequestContext[ClientSession]`. This means callbacks receive the more general `BaseClientSession` type, which may not have all methods available on `ClientSession`.
481
+
482
+
**Before:**
483
+
484
+
```python
485
+
from mcp.client.context import ClientRequestContext
In `mcp.shared._context` and `mcp.shared.progress`, the `SessionT` TypeVar has been renamed to `SessionT_co` to follow naming conventions for covariant type variables.
540
+
541
+
**Before:**
542
+
543
+
```python
544
+
from mcp.shared._context import SessionT
545
+
```
546
+
547
+
**After:**
548
+
549
+
```python
550
+
from mcp.shared._context import SessionT_co
551
+
```
552
+
553
+
#### `AbstractBaseSession` simplified
554
+
555
+
`AbstractBaseSession` is now a pure abstract interface with no `__init__` method and no `WireMessageT` type parameter. If you were subclassing it directly, you now need to manage all state in your subclass.
556
+
557
+
**Before:**
558
+
559
+
```python
560
+
from mcp.shared.session import AbstractBaseSession
super().__init__() # Would set up _response_streams, _task_group
565
+
```
566
+
567
+
**After:**
568
+
569
+
```python
570
+
from mcp.shared.session import AbstractBaseSession
571
+
572
+
classMySession(AbstractBaseSession[...]):
573
+
def__init__(self):
574
+
# Manage your own state - no super().__init__() to call
575
+
self._my_state = {}
576
+
```
577
+
578
+
#### `BaseClientSession` is now a Protocol
579
+
580
+
`BaseClientSession` is now a `typing.Protocol` (structural subtyping) instead of an abstract base class. It no longer inherits from `AbstractBaseSession` and requires no inheritance to satisfy.
581
+
582
+
**Before:**
583
+
584
+
```python
585
+
from mcp.client.base_client_session import BaseClientSession
586
+
587
+
classMyClientSession(BaseClientSession):
588
+
asyncdefinitialize(self) -> InitializeResult:
589
+
...
590
+
```
591
+
592
+
**After:**
593
+
594
+
```python
595
+
from mcp.client.base_client_session import BaseClientSession
596
+
597
+
classMyClientSession:
598
+
# Just implement the methods - no inheritance needed
0 commit comments