modelcontextprotocol / modelcontextprotocol/java-sdk
ServerCapabilities.logging is added unconditionally, overriding the caller's explicit capabilities
Nessuno ha ancora preso questa issue.
- Lingua principale
- Java
- Stelle
- 3.7k
- Fork
- 1.1k
- Merge medio
- 1g 15h
- PR unite (30g)
- 9
Descrizione
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":
- implement a deprecated feature they did not want, purely so the advertisement is not empty; or
- 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.
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Iniziate dai costruttori di McpAsyncServer per McpServerTransportProvider e McpStreamableServerTransportProvider, dove serverCapabilities viene costruito a partire da features. Riproducete il server tools-only dell’issue e analizzate la sua risposta initialize; il lavoro è completato quando la risposta riflette le capacità del chiamante senza logging non richiesto.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- java
- Ambito
- api, backend
- Tipo di issue
- Bug
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Stato di attività
- Tranquilla
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 68/100