diff --git a/examples/server/sequentialthinking/main.go b/examples/server/sequentialthinking/main.go index e0ae5219..4775c33d 100644 --- a/examples/server/sequentialthinking/main.go +++ b/examples/server/sequentialthinking/main.go @@ -234,7 +234,7 @@ func deepCopyThoughts(thoughts []*Thought) []*Thought { func StartThinking(ctx context.Context, _ *mcp.CallToolRequest, args StartThinkingArgs) (*mcp.CallToolResult, any, error) { sessionID := args.SessionID if sessionID == "" { - sessionID = randText() + sessionID = rand.Text() } estimatedSteps := args.EstimatedSteps @@ -480,20 +480,6 @@ func ThinkingHistory(ctx context.Context, req *mcp.ReadResourceRequest) (*mcp.Re }, nil } -// Copied from crypto/rand. -// TODO: once 1.24 is assured, just use crypto/rand. -const base32alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" - -func randText() string { - // ⌈log₃₂ 2¹²⁸⌉ = 26 chars - src := make([]byte, 26) - rand.Read(src) - for i := range src { - src[i] = base32alphabet[src[i]%32] - } - return string(src) -} - func main() { flag.Parse() diff --git a/mcp/event_test.go b/mcp/event_test.go index dacf30e8..b774e10d 100644 --- a/mcp/event_test.go +++ b/mcp/event_test.go @@ -6,6 +6,7 @@ package mcp import ( "context" + "crypto/rand" "fmt" "slices" "strings" @@ -281,7 +282,7 @@ func BenchmarkMemoryEventStore(b *testing.B) { for i := range sessionIDs { sessionIDs[i] = fmt.Sprint(i) for j := range 3 { - streamIDs[i][j] = randText() + streamIDs[i][j] = rand.Text() } } payload := make([]byte, test.datasize) diff --git a/mcp/logging.go b/mcp/logging.go index 96a96b82..b1bd82b1 100644 --- a/mcp/logging.go +++ b/mcp/logging.go @@ -89,21 +89,12 @@ type LoggingHandler struct { handler slog.Handler } -// discardHandler is a slog.Handler that drops all logs. -// TODO: use slog.DiscardHandler when we require Go 1.24+. -type discardHandler struct{} - -func (discardHandler) Enabled(context.Context, slog.Level) bool { return false } -func (discardHandler) Handle(context.Context, slog.Record) error { return nil } -func (discardHandler) WithAttrs([]slog.Attr) slog.Handler { return discardHandler{} } -func (discardHandler) WithGroup(string) slog.Handler { return discardHandler{} } - // ensureLogger returns l if non-nil, otherwise a discard logger. func ensureLogger(l *slog.Logger) *slog.Logger { if l != nil { return l } - return slog.New(discardHandler{}) + return slog.New(slog.DiscardHandler) } // NewLoggingHandler creates a [LoggingHandler] that logs to the given [ServerSession] using a diff --git a/mcp/server.go b/mcp/server.go index d68a8c23..930410e7 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -7,6 +7,7 @@ package mcp import ( "bytes" "context" + "crypto/rand" "encoding/base64" "encoding/gob" "encoding/json" @@ -175,7 +176,7 @@ func NewServer(impl *Implementation, options *ServerOptions) *Server { } if opts.GetSessionID == nil { - opts.GetSessionID = randText + opts.GetSessionID = rand.Text } if opts.Logger == nil { // ensure we have a logger diff --git a/mcp/sse.go b/mcp/sse.go index ae65c16c..e57dad10 100644 --- a/mcp/sse.go +++ b/mcp/sse.go @@ -7,6 +7,7 @@ package mcp import ( "bytes" "context" + "crypto/rand" "fmt" "io" "net/http" @@ -216,7 +217,7 @@ func (h *SSEHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") - sessionID = randText() + sessionID = rand.Text() endpoint, err := req.URL.Parse("?sessionid=" + sessionID) if err != nil { http.Error(w, "internal error: failed to create endpoint", http.StatusInternalServerError) diff --git a/mcp/streamable.go b/mcp/streamable.go index f2a28955..c1f20ea0 100644 --- a/mcp/streamable.go +++ b/mcp/streamable.go @@ -11,6 +11,7 @@ package mcp import ( "bytes" "context" + crand "crypto/rand" "encoding/json" "errors" "fmt" @@ -1140,7 +1141,7 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques // Important: don't publish the incoming messages until the stream is // registered, as the server may attempt to respond to imcoming messages as // soon as they're published. - stream, err := c.newStream(req.Context(), calls, randText()) + stream, err := c.newStream(req.Context(), calls, crand.Text()) if err != nil { http.Error(w, fmt.Sprintf("storing stream: %v", err), http.StatusInternalServerError) return diff --git a/mcp/util.go b/mcp/util.go index 5ada466e..f4a1f31f 100644 --- a/mcp/util.go +++ b/mcp/util.go @@ -5,7 +5,6 @@ package mcp import ( - "crypto/rand" "encoding/json" ) @@ -15,20 +14,6 @@ func assert(cond bool, msg string) { } } -// Copied from crypto/rand. -// TODO: once 1.24 is assured, just use crypto/rand. -const base32alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" - -func randText() string { - // ⌈log₃₂ 2¹²⁸⌉ = 26 chars - src := make([]byte, 26) - rand.Read(src) - for i := range src { - src[i] = base32alphabet[src[i]%32] - } - return string(src) -} - // remarshal marshals from to JSON, and then unmarshals into to, which must be // a pointer type. func remarshal(from, to any) error {