@@ -12,6 +12,7 @@ import (
1212 "fmt"
1313 "io"
1414 "iter"
15+ "log/slog"
1516 "math"
1617 "math/rand/v2"
1718 "net/http"
@@ -39,6 +40,7 @@ const (
3940type StreamableHTTPHandler struct {
4041 getServer func (* http.Request ) * Server
4142 opts StreamableHTTPOptions
43+ logger * slog.Logger
4244
4345 onTransportDeletion func (sessionID string ) // for testing only
4446
@@ -67,6 +69,10 @@ type StreamableHTTPOptions struct {
6769 //
6870 // [§2.1.5]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server
6971 JSONResponse bool
72+
73+ // Logger specifies the logger to use.
74+ // If nil, do not log.
75+ Logger * slog.Logger
7076}
7177
7278// NewStreamableHTTPHandler returns a new [StreamableHTTPHandler].
@@ -82,6 +88,12 @@ func NewStreamableHTTPHandler(getServer func(*http.Request) *Server, opts *Strea
8288 if opts != nil {
8389 h .opts = * opts
8490 }
91+
92+ if h .opts .Logger == nil { // ensure we have a logger
93+ h .opts .Logger = ensureLogger (nil )
94+ }
95+ h .logger = h .opts .Logger
96+
8597 return h
8698}
8799
@@ -367,6 +379,8 @@ type StreamableServerTransport struct {
367379 // StreamableHTTPOptions.JSONResponse is exported.
368380 jsonResponse bool
369381
382+ logger * slog.Logger
383+
370384 // connection is non-nil if and only if the transport has been connected.
371385 connection * streamableServerConn
372386}
@@ -381,6 +395,7 @@ func (t *StreamableServerTransport) Connect(ctx context.Context) (Connection, er
381395 stateless : t .Stateless ,
382396 eventStore : t .EventStore ,
383397 jsonResponse : t .jsonResponse ,
398+ logger : t .logger ,
384399 incoming : make (chan jsonrpc.Message , 10 ),
385400 done : make (chan struct {}),
386401 streams : make (map [string ]* stream ),
@@ -407,6 +422,8 @@ type streamableServerConn struct {
407422 jsonResponse bool
408423 eventStore EventStore
409424
425+ logger * slog.Logger
426+
410427 incoming chan jsonrpc.Message // messages from the client to the server
411428
412429 mu sync.Mutex // guards all fields below
@@ -754,7 +771,7 @@ func (c *streamableServerConn) respondSSE(stream *stream, w http.ResponseWriter,
754771 }
755772 if _ , err := writeEvent (w , e ); err != nil {
756773 // Connection closed or broken.
757- // TODO(#170): log when we add server-side logging.
774+ c . logger . Warn ( "error writing event" , "error" , err )
758775 return false
759776 }
760777 writes ++
@@ -773,7 +790,13 @@ func (c *streamableServerConn) respondSSE(stream *stream, w http.ResponseWriter,
773790 // simplify.
774791 http .Error (w , http .StatusText (http .StatusInternalServerError ), http .StatusInternalServerError )
775792 } else {
776- // TODO(#170): log when we add server-side logging
793+ if ctx .Err () != nil {
794+ // Client disconnected or cancelled the request.
795+ c .logger .Info ("stream context done" , "error" , ctx .Err ())
796+ } else {
797+ // Some other error.
798+ c .logger .Warn ("error receiving message" , "error" , err )
799+ }
777800 }
778801 return
779802 }
0 commit comments