mcp/server: enable server logging (#501)
mcp/server.go: implement server‑side logging - Thread a *slog.Logger through server paths to improve debuggability - Introduce no‑op discard handler + ensureLogger so loggers are never nil - Use ensured loggers in Server - address todo comments related to adding logging support All tests are passing and no functionality should change with this PR Fixes https://github.com/modelcontextprotocol/go-sdk/issues/170
This commit is contained in:
parent
49047aebe8
commit
1dcbf62661
1 changed files with 72 additions and 3 deletions
|
|
@ -68,6 +68,10 @@ type StreamableHTTPOptions struct {
|
|||
//
|
||||
// [§2.1.5]: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server
|
||||
JSONResponse bool
|
||||
|
||||
// Logger specifies the logger to use.
|
||||
// If nil, do not log.
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewStreamableHTTPHandler returns a new [StreamableHTTPHandler].
|
||||
|
|
@ -83,6 +87,11 @@ func NewStreamableHTTPHandler(getServer func(*http.Request) *Server, opts *Strea
|
|||
if opts != nil {
|
||||
h.opts = *opts
|
||||
}
|
||||
|
||||
if h.opts.Logger == nil { // ensure we have a logger
|
||||
h.opts.Logger = ensureLogger(nil)
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
|
|
@ -368,6 +377,8 @@ type StreamableServerTransport struct {
|
|||
// StreamableHTTPOptions.JSONResponse is exported.
|
||||
jsonResponse bool
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
// connection is non-nil if and only if the transport has been connected.
|
||||
connection *streamableServerConn
|
||||
}
|
||||
|
|
@ -382,6 +393,7 @@ func (t *StreamableServerTransport) Connect(ctx context.Context) (Connection, er
|
|||
stateless: t.Stateless,
|
||||
eventStore: t.EventStore,
|
||||
jsonResponse: t.jsonResponse,
|
||||
logger: t.logger,
|
||||
incoming: make(chan jsonrpc.Message, 10),
|
||||
done: make(chan struct{}),
|
||||
streams: make(map[string]*stream),
|
||||
|
|
@ -408,6 +420,8 @@ type streamableServerConn struct {
|
|||
jsonResponse bool
|
||||
eventStore EventStore
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
incoming chan jsonrpc.Message // messages from the client to the server
|
||||
|
||||
mu sync.Mutex // guards all fields below
|
||||
|
|
@ -755,7 +769,7 @@ func (c *streamableServerConn) respondSSE(stream *stream, w http.ResponseWriter,
|
|||
}
|
||||
if _, err := writeEvent(w, e); err != nil {
|
||||
// Connection closed or broken.
|
||||
// TODO(#170): log when we add server-side logging.
|
||||
c.logger.Warn("error writing event", "error", err)
|
||||
return false
|
||||
}
|
||||
writes++
|
||||
|
|
@ -774,7 +788,13 @@ func (c *streamableServerConn) respondSSE(stream *stream, w http.ResponseWriter,
|
|||
// simplify.
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
} else {
|
||||
// TODO(#170): log when we add server-side logging
|
||||
if ctx.Err() != nil {
|
||||
// Client disconnected or cancelled the request.
|
||||
c.logger.Error("stream context done", "error", ctx.Err())
|
||||
} else {
|
||||
// Some other error.
|
||||
c.logger.Error("error receiving message", "error", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue