@@ -401,7 +401,7 @@ func NewStreamableServerTransport(sessionID string, opts *StreamableServerTransp
401401}
402402
403403// Connect implements the [Transport] interface.
404- func (t * StreamableServerTransport ) Connect (context.Context ) (Connection , error ) {
404+ func (t * StreamableServerTransport ) Connect (ctx context.Context ) (Connection , error ) {
405405 if t .connection != nil {
406406 return nil , fmt .Errorf ("transport already connected" )
407407 }
@@ -415,13 +415,17 @@ func (t *StreamableServerTransport) Connect(context.Context) (Connection, error)
415415 streams : make (map [StreamID ]* stream ),
416416 requestStreams : make (map [jsonrpc.ID ]StreamID ),
417417 }
418+ if t .connection .eventStore == nil {
419+ t .connection .eventStore = NewMemoryEventStore (nil )
420+ }
418421 // Stream 0 corresponds to the hanging 'GET'.
419422 //
420423 // It is always text/event-stream, since it must carry arbitrarily many
421424 // messages.
422- t .connection .streams ["" ] = newStream ("" , false )
423- if t .connection .eventStore == nil {
424- t .connection .eventStore = NewMemoryEventStore (nil )
425+ var err error
426+ t .connection .streams ["" ], err = t .connection .newStream (ctx , "" , false )
427+ if err != nil {
428+ return nil , err
425429 }
426430 return t .connection , nil
427431}
@@ -508,12 +512,15 @@ type stream struct {
508512 requests map [jsonrpc.ID ]struct {}
509513}
510514
511- func newStream (id StreamID , jsonResponse bool ) * stream {
515+ func (c * streamableServerConn ) newStream (ctx context.Context , id StreamID , jsonResponse bool ) (* stream , error ) {
516+ if err := c .eventStore .Open (ctx , c .sessionID , id ); err != nil {
517+ return nil , err
518+ }
512519 return & stream {
513520 id : id ,
514521 jsonResponse : jsonResponse ,
515522 requests : make (map [jsonrpc.ID ]struct {}),
516- }
523+ }, nil
517524}
518525
519526func signalChanPtr () * chan struct {} {
@@ -664,7 +671,11 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
664671 // notifications or server->client requests made in the course of handling.
665672 // Update accounting for this incoming payload.
666673 if len (requests ) > 0 {
667- stream = newStream (StreamID (randText ()), c .jsonResponse )
674+ stream , err = c .newStream (req .Context (), StreamID (randText ()), c .jsonResponse )
675+ if err != nil {
676+ http .Error (w , fmt .Sprintf ("storing stream: %v" , err ), http .StatusInternalServerError )
677+ return
678+ }
668679 c .mu .Lock ()
669680 c .streams [stream .id ] = stream
670681 stream .requests = requests
@@ -800,18 +811,19 @@ func (c *streamableServerConn) respondSSE(stream *stream, w http.ResponseWriter,
800811func (c * streamableServerConn ) messages (ctx context.Context , stream * stream , persistent bool , lastIndex int ) iter.Seq2 [json.RawMessage , error ] {
801812 return func (yield func (json.RawMessage , error ) bool ) {
802813 for {
814+ c .mu .Lock ()
815+ nOutstanding := len (stream .requests )
816+ c .mu .Unlock ()
803817 for data , err := range c .eventStore .After (ctx , c .SessionID (), stream .id , lastIndex ) {
804818 if err != nil {
805- break
819+ yield (nil , err )
820+ return
806821 }
807822 if ! yield (data , nil ) {
808823 return
809824 }
810825 lastIndex ++
811826 }
812- c .mu .Lock ()
813- nOutstanding := len (stream .requests )
814- c .mu .Unlock ()
815827 // If all requests have been handled and replied to, we should terminate this connection.
816828 // "After the JSON-RPC response has been sent, the server SHOULD close the SSE stream."
817829 // §6.4, https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server
0 commit comments