ServerCapabilities.logging is added unconditionally, overriding the caller's explicit capabilities

Abierto Apto para principiantes
#1,086 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
68/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Tranquilo
Stack tecnológico
java
Área
api, backend

Línea de trabajo

Empiece en los constructores de McpAsyncServer para McpServerTransportProvider y McpStreamableServerTransportProvider, donde serverCapabilities se construye a partir de features. Reproduzca el servidor tools-only del issue e inspeccione su respuesta initialize; se considera terminado cuando la respuesta refleja las capacidades del llamador sin logging no solicitado.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug P2 ready for work
What happens

McpAsyncServer adds the logging capability to every server it builds, overriding whatever the
caller passed to .capabilities(...). There is no flag and no branch, so a server cannot decline to
advertise it.

Both constructors — the McpServerTransportProvider one and the McpStreamableServerTransportProvider
one — run:

this.serverCapabilities = features.serverCapabilities().mutate().logging().build();
Reproduction

Build a server that asks for tools only:

McpServer.sync(transport)
        .serverInfo("example", "1.0.0")
        .capabilities(ServerCapabilities.builder().tools(true).build())
        .tools(theTools)
        .build();

initialize answers:

"capabilities": { "logging": {}, "tools": { "listChanged": true } }
Evidence

Verified in the bytecode of mcp-core-2.0.0.jar rather than from source, in case the mutation was
conditional at runtime. It is not — javap -c io/modelcontextprotocol/server/McpAsyncServer.class
shows the same three calls at identical offsets in both constructors:

101: invokevirtual  // McpServerFeatures$Async.serverCapabilities:()...ServerCapabilities;
104: invokevirtual  // ServerCapabilities.mutate:()...ServerCapabilities$Builder;
107: invokevirtual  // ServerCapabilities$Builder.logging:()...ServerCapabilities$Builder;
113: putfield       // serverCapabilities
Why this is worth changing

MCP's in-protocol logging utility is deprecated as of protocol revision 2026-07-28
(SEP-2577); new
implementations SHOULD NOT adopt it. The current behaviour means every server built with this SDK
advertises the deprecated capability
, whether or not it sends notifications/message — which is
close to the opposite of what the deprecation is trying to achieve, and it makes the advertisement
useless to clients as a signal, since it is true of everyone.

It also leaves implementors with only two honest options, neither of them "follow the spec's advice":

  1. implement a deprecated feature they did not want, purely so the advertisement is not empty; or
  2. advertise a capability that does nothing, and hope no client acts on it.

Worth noting the gap is narrower than it first appears, which is why this is a small fix rather than
a design change: the SDK does implement logging/setLevel and filters on
McpServerSession.minLoggingLevel (default INFO) inside loggingNotification. So a server that
never calls loggingNotification is offering an always-empty stream rather than a broken method.
The problem is only that it cannot say so.

Suggested fix

Honour what the caller passed:

this.serverCapabilities = features.serverCapabilities();

If the unconditional .logging() is load-bearing for existing users, an opt-out on the builder would
also do — anything that lets a server say "I do not implement this". Happy to open a PR if you have a
preference between the two.

Related but not the same ask: #872 (constructors package-private, so behaviour cannot be customised
by subclassing).

Version

io.modelcontextprotocol.sdk:mcp:2.0.0, Java 21.

Lenguaje dominante
Java
Estrellas
3.7k
Forks
1.1k
Merge medio
1 d 15 h
PR fusionados (30 d)
9

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de modelcontextprotocol/java-sdk

Todos los issues de modelcontextprotocol/java-sdk

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.