@@ -643,39 +643,39 @@ async def serve_dual_era_loop(
643643 await write_stream .aclose ()
644644
645645
646- _OPENING_PEEK_LIMIT : int = 32
647- """How many frames may precede the client's first request before the loop
648- stops looking for one. Every legitimate client opens with a request, so this
649- only bounds a peer that streams other frames without ever sending one ."""
646+ _PRE_REQUEST_REPLAY_LIMIT : int = 8
647+ """How many frames arriving ahead of the client's first request are kept
648+ for the chosen era's loop (a bare `notifications/initialized` is the one that
649+ matters); further ones are dropped and never decide the era ."""
650650
651651
652652def _sender_context (stream : ReadStream [Any ]) -> contextvars .Context :
653653 """The per-message sender context a context-aware stream carries, else the current one."""
654- return getattr (stream , "last_context" , None ) or contextvars .copy_context ()
654+ ctx = getattr (stream , "last_context" , None )
655+ return ctx if ctx is not None else contextvars .copy_context ()
655656
656657
657658@asynccontextmanager
658659async def _replay_from_opening_request (
659660 read_stream : ReadStream [SessionMessage | Exception ],
660661) -> AsyncIterator [tuple [JSONRPCRequest | None , ReadStream [SessionMessage | Exception ]]]:
661- """Peek at the client's first request without consuming anything .
662+ """Peek at the client's first request without consuming it .
662663
663- Reads frames until the first JSON-RPC request arrives, then yields that
664- request together with a stream that replays every frame read so far and
665- relays the rest of `read_stream` behind it, sender contexts included. The
666- request is `None` if the channel closes - or `_OPENING_PEEK_LIMIT` frames
667- pass - before any request appears.
664+ Yields that request together with a stream that replays it - preceded by
665+ up to `_PRE_REQUEST_REPLAY_LIMIT` earlier frames - and relays the rest of
666+ `read_stream` behind it, sender contexts included. The request is `None`
667+ if the channel closes before one arrives.
668668 """
669- peeked : list [tuple [contextvars .Context , SessionMessage | Exception ]] = []
670- opening : JSONRPCRequest | None = None
669+ lead : list [tuple [contextvars .Context , SessionMessage | Exception ]] = []
670+ opening_request : JSONRPCRequest | None = None
671671 replay_send , replay_receive = anyio .create_memory_object_stream [
672672 tuple [contextvars .Context , SessionMessage | Exception ]
673673 ]()
674674 replayed = ContextReceiveStream (replay_receive )
675675
676676 async def replay_then_relay () -> None :
677677 async with replay_send :
678- for envelope in peeked :
678+ for envelope in lead :
679679 await replay_send .send (envelope )
680680 async for item in read_stream :
681681 await replay_send .send ((_sender_context (read_stream ), item ))
@@ -685,15 +685,17 @@ async def replay_then_relay() -> None:
685685 # closes it and the replay channel.
686686 try :
687687 async for item in read_stream :
688- peeked .append ((_sender_context (read_stream ), item ))
689688 if isinstance (item , SessionMessage ) and isinstance (item .message , JSONRPCRequest ):
690- opening = item .message
691- break
692- if len (peeked ) >= _OPENING_PEEK_LIMIT :
689+ opening_request = item .message
690+ elif len (lead ) >= _PRE_REQUEST_REPLAY_LIMIT :
691+ logger .debug ("dropped a frame received before the first request: %r" , item )
692+ continue
693+ lead .append ((_sender_context (read_stream ), item ))
694+ if opening_request is not None :
693695 break
694696 async with anyio .create_task_group () as tg :
695697 tg .start_soon (replay_then_relay )
696- yield opening , replayed
698+ yield opening_request , replayed
697699 tg .cancel_scope .cancel ()
698700 finally :
699701 await read_stream .aclose ()
@@ -728,8 +730,8 @@ async def on_request(
728730 if method != "initialize" and _has_modern_envelope (params ):
729731 raise MCPError (
730732 code = INVALID_REQUEST ,
731- message = "connection was opened with the initialize handshake; "
732- "2026-07-28 envelope requests are not accepted on it" ,
733+ message = "this connection's first request carried no 2026-07-28 envelope, so it "
734+ "serves the handshake era; enveloped requests are not accepted on it" ,
733735 )
734736 return await runner .on_request (dctx , method , params )
735737
0 commit comments