Summary
The CLI cannot connect to any modern-era server that advertises the logging capability. Every command fails at connect — not just logging ones — because the client sends the legacy logging/setLevel during the post-connect sequence, and the modern wire era rejects it.
$ mcp-inspector --cli --config <catalog> --server showcase --method tools/list --format json
{"error":{"code":"error","message":"Method 'logging/setLevel' is not supported by the negotiated protocol version (wire era 2026-07-28)"}}
Reproduce
npm run test-servers:build
node test-servers/build/server-composable.js --config test-servers/configs/logging-modern-http.json
# note the announced URL, then point a catalog at it with "protocolEra": "modern"
node clients/cli/build/index.js --config <catalog> --server showcase --method tools/list --format json
tools/list is incidental — any method fails, because the failure is in connect, before the method runs.
Cause
Two things combine:
-
clients/cli/src/cli.ts:152 hardcodes initialLoggingLevel: "debug" for every CLI connection.
-
core/mcp/inspectorClient.ts:1940 gates the connect-time call on the server capability but not on the protocol era:
// Set initial logging level if configured and server supports it
if (this.initialLoggingLevel && this.capabilities?.logging) {
await this.client.setLoggingLevel(this.initialLoggingLevel, this.getRequestOptions());
}
logging/setLevel is a legacy-era method. On the modern era the equivalent is the per-request _meta["io.modelcontextprotocol/logLevel"] opt-in (the modernLogLevel server field) — which is exactly what the root README documents for logging-modern-http.json:
Modern — the same tab instead shows Log Level per Request. Pick a level to opt in and the client stamps _meta["io.modelcontextprotocol/logLevel"] on every subsequent request.
So the call is not merely rejected, it is the wrong mechanism for that era.
Scope
CLI only. initialLoggingLevel is set in exactly one place, and neither web nor TUI passes it — they drive logging through the Logs tab, which already era-splits correctly. That is why this has gone unnoticed: the showcase config is documented as a by-hand web exercise, and the web path works.
Not a regression
Verified against both SDK versions: it reproduces identically on 2.0.0-beta.5 and on 2.0.0. Found while verifying the showcase configs for #1988 / #1989, but it predates that bump and is not caused by it.
Fix
Gate the connect-time call on the negotiated era — legacy connections keep setLoggingLevel, modern ones fall through to the modernLogLevel per-request path they already have. The guard belongs in inspectorClient.ts next to the capability check rather than in the CLI, so any future caller passing initialLoggingLevel is covered too.
Acceptance criteria
Summary
The CLI cannot connect to any modern-era server that advertises the
loggingcapability. Every command fails at connect — not just logging ones — because the client sends the legacylogging/setLevelduring the post-connect sequence, and the modern wire era rejects it.Reproduce
tools/listis incidental — any method fails, because the failure is in connect, before the method runs.Cause
Two things combine:
clients/cli/src/cli.ts:152hardcodesinitialLoggingLevel: "debug"for every CLI connection.core/mcp/inspectorClient.ts:1940gates the connect-time call on the server capability but not on the protocol era:logging/setLevelis a legacy-era method. On the modern era the equivalent is the per-request_meta["io.modelcontextprotocol/logLevel"]opt-in (themodernLogLevelserver field) — which is exactly what the root README documents forlogging-modern-http.json:So the call is not merely rejected, it is the wrong mechanism for that era.
Scope
CLI only.
initialLoggingLevelis set in exactly one place, and neither web nor TUI passes it — they drive logging through the Logs tab, which already era-splits correctly. That is why this has gone unnoticed: the showcase config is documented as a by-hand web exercise, and the web path works.Not a regression
Verified against both SDK versions: it reproduces identically on
2.0.0-beta.5and on2.0.0. Found while verifying the showcase configs for #1988 / #1989, but it predates that bump and is not caused by it.Fix
Gate the connect-time call on the negotiated era — legacy connections keep
setLoggingLevel, modern ones fall through to themodernLogLevelper-request path they already have. The guard belongs ininspectorClient.tsnext to the capability check rather than in the CLI, so any future caller passinginitialLoggingLevelis covered too.Acceptance criteria
--cliconnects tologging-modern-http.jsonatprotocolEra: "modern"andtools/listsucceeds.--cliagainstlogging-legacy-http.jsonstill applies the initial level vialogging/setLevel(no behavior change on legacy).inspectorClient.tsguard, so a modern connection never emitslogging/setLevel.npm run cipasses.