modelcontextprotocol / modelcontextprotocol/java-sdk

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

Aberta Para iniciantes
#1,086 1 comentário 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

bug P2 ready for work
Linguagem predominante
Java
Estrelas
3.7k
Forks
1.1k
Merge médio
1d 15h
PRs com merge (30d)
9

Descrição

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.

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece pelos construtores de McpAsyncServer para McpServerTransportProvider e McpStreamableServerTransportProvider, onde serverCapabilities é construído a partir de features. Reproduza o servidor tools-only da issue e inspecione sua resposta initialize; considera-se concluído quando a resposta reflete as capabilities do chamador sem logging não solicitado.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
java
Domínio
api, backend
Tipo de issue
Bug
Dificuldade
2/5
Tempo estimado
1-3 horas
Status de atividade
Pouca atividade
Clareza
Claramente especificada
Facilidade para iniciantes
68/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.