Session-lifecycle bookkeeping logs at info, spamming multiple log lines per request on stateless streamable HTTP
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 75/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- go
- 領域
- backend, observability
調査の方向性
Go SDK でセッションライフサイクルの正確なログメッセージ、特に "server connecting" と "client log level set" を検索します。提供されたステートレスな Streamable HTTP の再現を実行し、クライアントのログレベルが要求されていない場合も含め、これらのブックキーピングイベントが info レベルに表示されなくなったことを確認します。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
Found this while working on adding stateless HTTP support to the Prometheus MCP server
TL;DR: the current implementation of the new 2026-07-28 spec, and the stateless HTTP support specifically, are spamming logs with in-actionable session bookkeeping.
Summary:
The server's internal slog records for session bookkeeping (server connecting, server session connected, server session disconnected, session initialized, client log level set) all log at Info. These logs were reasonable when they were added and HTTP was stateful since they were per-session events. Now though, they're per-request:
- Stateless streamable HTTP mints a session per POST: every single request replays the connect/disconnect lifecycle.
- 2026-07-28 clients carry
_metaon every request, sosetLevelruns, loggingclient log level setonce per request, on every transport (stdio included), even when the client set no level at all (the record fires withlevel="").
The result:
A server running at a normal info log level gets four lines of pure bookkeeping for every tool call, and this is before it logs anything of its own.
To Reproduce
Steps to reproduce the behavior:
go-sdk v1.7.0, stateless streamable HTTP, one client connect plus one tools/call:
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"net/http/httptest"
"os"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey && len(groups) == 0 {
return slog.Attr{} // drop timestamps for a stable transcript
}
return a
},
}))
server := mcp.NewServer(&mcp.Implementation{Name: "probe-server", Version: "0.0.1"}, &mcp.ServerOptions{
Logger: logger,
})
mcp.AddTool(server, &mcp.Tool{Name: "echo", Description: "echo"}, func(ctx context.Context, req *mcp.CallToolRequest, input struct{}) (*mcp.CallToolResult, any, error) {
return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "ok"}}}, nil, nil
})
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server }, &mcp.StreamableHTTPOptions{
Stateless: true,
})
httpServer := httptest.NewServer(handler)
defer httpServer.Close()
ctx := context.Background()
client := mcp.NewClient(&mcp.Implementation{Name: "probe-client", Version: "0.0.1"}, nil)
session, err := client.Connect(ctx, &mcp.StreamableClientTransport{Endpoint: httpServer.URL}, nil)
if err != nil {
panic(err)
}
defer session.Close()
fmt.Println("--- one tools/call ---")
if _, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "echo"}); err != nil {
panic(err)
}
fmt.Println("--- end of tools/call ---")
}
Expected behavior
To see the debug logs in my debug stream 🙃
Logs
Output from repro ^
level=INFO msg="server connecting"
level=INFO msg="server session connected" session_id=""
level=INFO msg="client log level set" level=""
level=INFO msg="server session disconnected" session_id=""
--- one tools/call ---
level=INFO msg="server connecting"
level=INFO msg="server session connected" session_id=""
level=INFO msg="client log level set" level=""
level=INFO msg="server session disconnected" session_id=""
--- end of tools/call ---
Additional context
That's four info lines per request, none of which carry information an admin can act on. At any real request rate, these events dominate the log stream. Note also client log level set firing with level="" — the client never asked for anything.
On stdio the amplification is smaller but still per-request -- the client log level set event triggers on every request it sends.
These log events were added in #501 with the reasoning "to improve debuggability", so let's demote them to debug where they belong.
- 主要言語
- Go
- スター
- 5.2k
- フォーク
- 568
- 平均マージ
- 1日 18時間
- マージ済み PR(30日)
- 36
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
modelcontextprotocol/go-sdk のほかの issue
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensions対応中かも @ajuijas が 207 日前に担当しました。 オープンneeds investigation
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
modelcontextprotocol/go-sdk#745 · コメント 13 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
auth: Authorize fails against a 2025-03-26 server whose URL has a query string対応中かも @akshita317 が 2 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 40/100
modelcontextprotocol/go-sdk#1347 ·
メンテナーはふだん 1 日以内に返信
-
P3
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
modelcontextprotocol/go-sdk#1337 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
mcp: Client.Connect never falls back to initialize when a stdio server ignores server/discover対応中かも @crossxr が 6 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
modelcontextprotocol/go-sdk#1332 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 76/100
modelcontextprotocol/go-sdk#1331 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
modelcontextprotocol/go-sdk の issue をすべて見る
似ている issue
-
Service process inherits the caller's cwd at first use, holding that folder open on Windows (EBUSY)オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
[docs] Media elements cannot load from a custom protocol (video/audio report MEDIA_ERR_SRC_NOT_SUPPORTED)対応中かも @vst93 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
evilmartians/lefthook#1588 ·
メンテナーはふだん 1 日以内に返信
-
documentation
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
gravitational/teleport#69847 ·
メンテナーはふだん 11 日以内に返信