fix: gate the connect-time logging/setLevel on the negotiated era (#1990)

`logging/setLevel` is a legacy-era method, but connect() called it on any
server advertising the `logging` capability, era regardless. The modern wire
era rejects it outright, and because the call sits in the post-handshake
sequence that rejection failed the *connection* — so the CLI (the one caller
passing `initialLoggingLevel`, hardcoded to "debug") could not run any method
at all against a modern server that advertised logging.

Gate it on `protocolEra !== "modern"`. Modern has no session-scoped level to
set: the equivalent is the per-request `io.modelcontextprotocol/logLevel`
`_meta` opt-in, already driven by `modernLogLevel` from the server settings.
So modern skips the call rather than translating it. Legacy is unchanged.

The guard lives next to the capability check in inspectorClient.ts rather
than in the CLI, so any future caller passing `initialLoggingLevel` is
covered too.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-15 17:39:43 -04:00
commit 2b2e157511

View file

@ -1936,8 +1936,23 @@ export class InspectorClient extends InspectorClientEventTarget {
// capabilities and wipe tools/prompts/resources to empty on every connect.
await this.fetchServerInfo();
// Set initial logging level if configured and server supports it
if (this.initialLoggingLevel && this.capabilities?.logging) {
// Set initial logging level if configured and server supports it.
//
// Era-gated (#1990): `logging/setLevel` is a legacy-era method, and the
// modern wire era rejects it outright — so an unconditional call here
// failed the *connect* of every modern server advertising `logging`,
// taking down commands that have nothing to do with logging. Modern has
// no session-scoped level at all: the equivalent is the per-request
// `io.modelcontextprotocol/logLevel` `_meta` opt-in, which
// `modernLogLevel` already drives from the server settings (see
// {@link setModernLogLevel}). So the right behavior on modern is to skip
// this call rather than translate it — `initialLoggingLevel` names a
// mechanism that era does not have.
if (
this.initialLoggingLevel &&
this.capabilities?.logging &&
this.protocolEra !== "modern"
) {
await this.client.setLoggingLevel(
this.initialLoggingLevel,
this.getRequestOptions(),