Description
Bug description
When using MCP Client with setLogLevel
the Server can't find the suitable handler:
DEBUG io.modelcontextprotocol.spec.McpSchema - Received JSON message: {"jsonrpc":"2.0","method":"logging/setLevel","params":{"level":"info"}}
DEBUG io.modelcontextprotocol.spec.McpServerSession - Received notification: JSONRPCNotification[jsonrpc=2.0, method=logging/setLevel, params={level=info}]
ERROR io.modelcontextprotocol.spec.McpServerSession - No handler registered for notification method: logging/setLevel
According to the spec setLogLevel should be a request rather than a notification since it contains an id:
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
After changing this to a request there was another problem when deserializing the params since it currently tries to map the above params directly to a LoggingLevel enum:
//Currently tries to map to this
public enum LoggingLevel {// @formatter:off
@JsonProperty("debug") DEBUG(0),
@JsonProperty("info") INFO(1)
//....
}
Would work when using Logging Level in a separate object as outlined in the official json schema:
// This would properly deserialize it
@JsonIgnoreProperties(ignoreUnknown = true)
public record SetLevelRequest(@JsonProperty("level") LoggingLevel level) {
}
I have a working version ready and can provide a PR for fixing both issues shortly.
Environment
Java version: 17
MCP: 0.8.1
Steps to reproduce
Create a minimal MCP client with StdioTransport and setLoggingLevel. Create a minimal Stdio server that enables logging (See sample below).
Expected behavior
MCP Server should use the existing setLoggerRequestHandler and set the log level properly.
Minimal Complete Reproducible example
Create an MCP Client that leverages setLoggingLevel
public static void main( String[] args ) {
var transport = new StdioClientTransport(getServerParams());
try (var mcpClientSync = McpClient.sync(transport).loggingConsumer(loggingConsumer()).build()) {
mcpClientSync.initialize();
mcpClientSync.setLoggingLevel(McpSchema.LoggingLevel.INFO);
}
}
public static ServerParameters getServerParams(){
return ServerParameters.builder("java").
args("-jar", "/Users/XXXX/java-mcp-server/target/java-mcp-server-1.0-SNAPSHOT.jar").
build();
}
private static Consumer<McpSchema.LoggingMessageNotification> loggingConsumer(){
return loggingMessageNotification -> {
switch (loggingMessageNotification.level()) {
case ERROR -> customLogger.error("{}: {}", loggingMessageNotification.logger(), loggingMessageNotification.data());
case WARNING -> customLogger.warn("{}: {}", loggingMessageNotification.logger(), loggingMessageNotification.data());
default -> customLogger.info("{}: {}", loggingMessageNotification.logger(), loggingMessageNotification.data());
}
};
}
Create an MCP Server with Logging enabled
var transportProvider = new StdioServerTransportProvider();
var mcpServer = McpServer.sync(transportProvider)
.serverInfo("StandardJavaMCPServer", "1.0.0")
.capabilities(McpSchema.ServerCapabilities.builder().
logging().
build())
.build();
try {
while(true) {
//Do nothing
}
} catch (Exception e) {
mcpServer.close();
}