Skip to content

Commit e016e85

Browse files
committed
Update closing of sse stream.
1 parent 829c0a8 commit e016e85

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

server/streamable_http.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111
"sync"
1212
"sync/atomic"
13+
"time"
1314

1415
"github.com/google/uuid"
1516
"github.com/mark3labs/mcp-go/mcp"
@@ -633,8 +634,17 @@ func (s *StreamableHTTPServer) handleSSEResponse(w http.ResponseWriter, r *http.
633634
fmt.Fprintf(w, "data: %s\n\n", data)
634635
}
635636
w.(http.Flusher).Flush()
637+
638+
// According to the MCP specification, the server SHOULD close the SSE stream
639+
// after all JSON-RPC responses have been sent.
640+
// Since we've sent the response, we can close the stream now.
641+
return
636642
}
637643

644+
// If there's no response (which shouldn't happen in normal operation),
645+
// we'll keep the stream open for a short time to handle any notifications
646+
// that might come in, then close it.
647+
638648
// Create a channel to pass notifications from the goroutine to the main handler
639649
notificationCh := make(chan struct {
640650
eventID string
@@ -683,8 +693,9 @@ func (s *StreamableHTTPServer) handleSSEResponse(w http.ResponseWriter, r *http.
683693
}
684694
}()
685695

686-
// Create a context with cancellation
687-
ctx, cancel := context.WithCancel(r.Context())
696+
// Create a context with cancellation and a timeout
697+
// We'll only keep the stream open for a short time if there's no response
698+
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
688699
defer cancel()
689700

690701
// Process notifications in the main handler goroutine
@@ -699,7 +710,7 @@ func (s *StreamableHTTPServer) handleSSEResponse(w http.ResponseWriter, r *http.
699710
}
700711
w.(http.Flusher).Flush()
701712
case <-ctx.Done():
702-
// Request context is done, exit the loop
713+
// Request context is done or timeout reached, exit the loop
703714
return
704715
}
705716
}
@@ -784,8 +795,11 @@ func (s *StreamableHTTPServer) handleGet(w http.ResponseWriter, r *http.Request)
784795
}
785796
}()
786797

787-
// Wait for the request context to be done
788-
<-r.Context().Done()
798+
// Create a context with cancellation
799+
// For standalone SSE streams, we'll keep the connection open until the client disconnects
800+
// or the context is canceled
801+
ctx := r.Context()
802+
<-ctx.Done()
789803
}
790804

791805
// handleDelete processes DELETE requests to the MCP endpoint (for session termination)

0 commit comments

Comments
 (0)