fix: ServerCapabilities should not enable logging by default (#463)

- Change LoggingCapabilities from default-initialized to nullable in ServerCapabilities
- Add check if server logging is enabled in McpAsyncClient before setting logging level
- Ensure McpAsyncServer always enables logging capabilities when built
- Ensure McpStatelessAsyncServer has disabled logging capability by default
- Update tests to verify logging capabilities can be null

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
Co-authored-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
Jordan Zimmerman 2025-08-06 22:40:21 +01:00 • committed by Christian Tzolov
commit 713ee1add0
5 changed files with 9 additions and 5 deletions

View file

@ -950,7 +950,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
List<McpSchema.LoggingMessageNotification> receivedNotifications = new CopyOnWriteArrayList<>();
var clientBuilder = clientBuilders.get(clientType);
;
// Create server with a tool that sends logging notifications
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
.tool(Tool.builder()
@ -999,7 +999,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
.build();
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
.capabilities(ServerCapabilities.builder().logging().tools(true).build())
.capabilities(ServerCapabilities.builder().tools(true).build())
.tools(tool)
.build();

View file

@ -869,6 +869,9 @@ public class McpAsyncClient {
}
return this.initializer.withIntitialization("setting logging level", init -> {
if (init.initializeResult().capabilities().logging() == null) {
return Mono.error(new IllegalStateException("Server's Logging capabilities are not enabled!"));
}
var params = new McpSchema.SetLevelRequest(loggingLevel);
return init.mcpSession().sendRequest(McpSchema.METHOD_LOGGING_SET_LEVEL, params, OBJECT_TYPE_REF).then();
});

View file

@ -132,7 +132,7 @@ public class McpAsyncServer {
this.mcpTransportProvider = mcpTransportProvider;
this.objectMapper = objectMapper;
this.serverInfo = features.serverInfo();
this.serverCapabilities = features.serverCapabilities();
this.serverCapabilities = features.serverCapabilities().mutate().logging().build();
this.instructions = features.instructions();
this.tools.addAll(withStructuredOutputHandling(jsonSchemaValidator, features.tools()));
this.resources.putAll(features.resources());
@ -157,7 +157,7 @@ public class McpAsyncServer {
this.mcpTransportProvider = mcpTransportProvider;
this.objectMapper = objectMapper;
this.serverInfo = features.serverInfo();
this.serverCapabilities = features.serverCapabilities();
this.serverCapabilities = features.serverCapabilities().mutate().logging().build();
this.instructions = features.instructions();
this.tools.addAll(withStructuredOutputHandling(jsonSchemaValidator, features.tools()));
this.resources.putAll(features.resources());

View file

@ -548,7 +548,7 @@ public final class McpSchema {
private Map<String, Object> experimental;
private LoggingCapabilities logging = new LoggingCapabilities();
private LoggingCapabilities logging;
private PromptCapabilities prompts;

View file

@ -80,6 +80,7 @@ class McpAsyncClientResponseHandlerTests {
assertThat(result).isNotNull();
assertThat(result.protocolVersion()).isEqualTo(transport.protocolVersions().get(0));
assertThat(result.capabilities()).isEqualTo(serverCapabilities);
assertThat(result.capabilities().logging()).isNull();
assertThat(result.serverInfo()).isEqualTo(serverInfo);
assertThat(result.instructions()).isEqualTo("Test instructions");