Skip to content

Commit c8ab341

Browse files
authored
feat: Refine logging levels (#985)
The logging is sometimes too verbose and uses inappropriate level. With this change there should be less disturbing logs and less duplication. Notable changes: * `LifeCycleInitializer#handleException` - duplicated log, already handled in transports that use the initializer. * `McpClientSession#sendRequest` - an MCP protocol level error in JSON-RPC is not really a reason for ERROR level log. Using INFO with more details. * `DefaultJsonSchemaValidator` - ERROR logs in `validate` are always logged by the users of this method. `validateSchema` surfaces as `IllegalArgumentException` and can be logged at higher levels by the user. Also: remove DEBUG logs from mcp-test module. Signed-off-by: Dariusz Jędrzejczyk <2554306+chemicL@users.noreply.github.com>
1 parent c6d365c commit c8ab341

11 files changed

Lines changed: 70 additions & 33 deletions

File tree

mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ public McpSchema.InitializeResult currentInitializationResult() {
250250
* @param t The exception to handle
251251
*/
252252
public void handleException(Throwable t) {
253-
logger.warn("Handling exception", t);
254253
if (t instanceof McpTransportSessionNotFoundException) {
255254
DefaultInitialization previous = this.initializationRef.getAndSet(null);
256255
if (previous != null) {

mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,7 @@ public Mono<Void> addRoot(Root root) {
484484
if (this.isInitialized()) {
485485
return this.rootsListChangedNotification();
486486
}
487-
else {
488-
logger.warn("Client is not initialized, ignore sending a roots list changed notification");
489-
}
487+
logger.debug("Client is not initialized, ignore sending a roots list changed notification");
490488
}
491489
return Mono.empty();
492490
}
@@ -514,10 +512,7 @@ public Mono<Void> removeRoot(String rootUri) {
514512
if (this.isInitialized()) {
515513
return this.rootsListChangedNotification();
516514
}
517-
else {
518-
logger.warn("Client is not initialized, ignore sending a roots list changed notification");
519-
}
520-
515+
logger.debug("Client is not initialized, ignore sending a roots list changed notification");
521516
}
522517
return Mono.empty();
523518
}

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
import java.nio.charset.StandardCharsets;
1111
import java.time.Duration;
1212
import java.util.ArrayList;
13+
import java.util.EnumSet;
1314
import java.util.List;
15+
import java.util.Set;
1416
import java.util.concurrent.Executors;
1517
import java.util.function.Consumer;
1618
import java.util.function.Function;
19+
import java.util.stream.IntStream;
1720

1821
import io.modelcontextprotocol.json.TypeRef;
1922
import io.modelcontextprotocol.json.McpJsonMapper;
@@ -41,6 +44,15 @@ public class StdioClientTransport implements McpClientTransport {
4144

4245
private static final Logger logger = LoggerFactory.getLogger(StdioClientTransport.class);
4346

47+
// @formatter:off
48+
private static final Set<Integer> EXIT_SUCCESS_CODES = Set.of(
49+
0, // success
50+
130, // interrupted (SIGINT)
51+
141, // pipeline shortcut (SIGPIPE)
52+
143 // graceful termination (SIGTERM)
53+
);
54+
// @formatter:on
55+
4456
private final Sinks.Many<JSONRPCMessage> inboundSink;
4557

4658
private final Sinks.Many<JSONRPCMessage> outboundSink;
@@ -356,11 +368,12 @@ public Mono<Void> closeGracefully() {
356368
return Mono.<Process>empty();
357369
}
358370
})).doOnNext(process -> {
359-
if (process.exitValue() != 0) {
360-
logger.warn("Process terminated with code {}", process.exitValue());
371+
int exitValue = process.exitValue();
372+
if (EXIT_SUCCESS_CODES.contains(exitValue)) {
373+
logger.info("MCP server completed successfully with code {}", exitValue);
361374
}
362375
else {
363-
logger.info("MCP server process stopped");
376+
logger.warn("MCP server process failed with code {}", exitValue);
364377
}
365378
}).then(Mono.fromRunnable(() -> {
366379
try {

mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,14 +513,13 @@ public Mono<Void> removeTool(String toolName) {
513513

514514
return Mono.defer(() -> {
515515
if (this.tools.removeIf(toolSpecification -> toolSpecification.tool().name().equals(toolName))) {
516-
517516
logger.debug("Removed tool handler: {}", toolName);
518517
if (this.serverCapabilities.tools().listChanged()) {
519518
return notifyToolsListChanged();
520519
}
521520
}
522521
else {
523-
logger.warn("Ignore as a Tool with name '{}' not found", toolName);
522+
logger.warn("Failed to remove tool with name '{}' (not found)", toolName);
524523
}
525524

526525
return Mono.empty();
@@ -637,7 +636,7 @@ public Mono<Void> removeResource(String resourceUri) {
637636
return Mono.empty();
638637
}
639638
else {
640-
logger.warn("Ignore as a Resource with URI '{}' not found", resourceUri);
639+
logger.warn("Failed to remove resource with URI '{}' (not found)", resourceUri);
641640
}
642641
return Mono.empty();
643642
});
@@ -701,7 +700,7 @@ public Mono<Void> removeResourceTemplate(String uriTemplate) {
701700
logger.debug("Removed resource template: {}", uriTemplate);
702701
}
703702
else {
704-
logger.warn("Ignore as a Resource Template with URI '{}' not found", uriTemplate);
703+
logger.warn("Failed to remove a resource template with URI '{}' (not found)", uriTemplate);
705704
}
706705
return Mono.empty();
707706
});
@@ -907,7 +906,7 @@ public Mono<Void> removePrompt(String promptName) {
907906
return Mono.empty();
908907
}
909908
else {
910-
logger.warn("Ignore as a Prompt with name '{}' not found", promptName);
909+
logger.warn("Failed to remove a prompt with name '{}' (not found)", promptName);
911910
}
912911
return Mono.empty();
913912
});

mcp-core/src/main/java/io/modelcontextprotocol/server/McpStatelessAsyncServer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ public Mono<Void> removeTool(String toolName) {
390390
logger.debug("Removed tool handler: {}", toolName);
391391
}
392392
else {
393-
logger.warn("Ignore as a Tool with name '{}' not found", toolName);
393+
logger.warn("Failed to remove a tool with name '{}' (not found)", toolName);
394394
}
395395

396396
return Mono.empty();
@@ -492,7 +492,7 @@ public Mono<Void> removeResource(String resourceUri) {
492492
logger.debug("Removed resource handler: {}", resourceUri);
493493
}
494494
else {
495-
logger.warn("Resource with URI '{}' not found", resourceUri);
495+
logger.warn("Failed to remove a resource with URI '{}' (not found)", resourceUri);
496496
}
497497
return Mono.empty();
498498
});
@@ -554,7 +554,7 @@ public Mono<Void> removeResourceTemplate(String uriTemplate) {
554554
logger.debug("Removed resource template: {}", uriTemplate);
555555
}
556556
else {
557-
logger.warn("Ignore as a Resource Template with URI '{}' not found", uriTemplate);
557+
logger.warn("Failed to remove a resource template with URI '{}' (not found)", uriTemplate);
558558
}
559559
return Mono.empty();
560560
});
@@ -677,7 +677,7 @@ public Mono<Void> removePrompt(String promptName) {
677677
return Mono.empty();
678678
}
679679
else {
680-
logger.warn("Ignore as a Prompt with name '{}' not found", promptName);
680+
logger.warn("Failed to remove a prompt with name '{}' (not found)", promptName);
681681
}
682682

683683
return Mono.empty();

mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public Mono<Void> notifyClients(String method, Object params) {
200200
session.sendNotification(method, params).block();
201201
}
202202
catch (Exception e) {
203-
logger.error("Failed to send message to session {}: {}", session.getId(), e.getMessage());
203+
logger.info("Failed to send message to session {}: {}", session.getId(), e.getMessage());
204204
}
205205
});
206206
});
@@ -233,12 +233,11 @@ public Mono<Void> closeGracefully() {
233233
session.closeGracefully().block();
234234
}
235235
catch (Exception e) {
236-
logger.error("Failed to close session {}: {}", session.getId(), e.getMessage());
236+
logger.warn("Failed to close session {}: {}", session.getId(), e.getMessage());
237237
}
238238
});
239239

240240
this.sessions.clear();
241-
logger.debug("Graceful shutdown completed");
242241
}).then().doOnSuccess(v -> {
243242
sessions.clear();
244243
logger.debug("Graceful shutdown completed");

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public McpClientSession(Duration requestTimeout, McpClientTransport transport,
124124

125125
private void dismissPendingResponses() {
126126
this.pendingResponses.forEach((id, sink) -> {
127-
logger.warn("Abruptly terminating exchange for request {}", id);
127+
logger.info("Abruptly terminating exchange for request {}", id);
128128
sink.error(new RuntimeException("MCP session with server terminated"));
129129
});
130130
this.pendingResponses.clear();
@@ -257,7 +257,8 @@ public <T> Mono<T> sendRequest(String method, Object requestParams, TypeRef<T> t
257257
});
258258
})).timeout(this.requestTimeout).handle((jsonRpcResponse, deliveredResponseSink) -> {
259259
if (jsonRpcResponse.error() != null) {
260-
logger.error("Error handling request: {}", jsonRpcResponse.error());
260+
logger.info("Server returned a JSON-RPC error when calling method {}: {}", method,
261+
jsonRpcResponse.error());
261262
deliveredResponseSink.error(new McpError(jsonRpcResponse.error()));
262263
}
263264
else {

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ else if (message instanceof McpSchema.JSONRPCNotification notification) {
256256
// happening first
257257
logger.debug("Received notification: {}", notification);
258258
// TODO: in case of error, should the POST request be signalled?
259-
return handleIncomingNotification(notification, transportContext)
260-
.doOnError(error -> logger.error("Error handling notification: {}", error.getMessage()));
259+
return handleIncomingNotification(notification, transportContext).doOnError(
260+
error -> logger.warn("Error handling notification {}: {}", notification, error.getMessage()));
261261
}
262262
else {
263263
logger.warn("Received unknown message type: {}", message);

mcp-json-jackson2/src/main/java/io/modelcontextprotocol/json/schema/jackson2/DefaultJsonSchemaValidator.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,9 @@ public ValidationResponse validate(Map<String, Object> schema, Object structured
8484

8585
}
8686
catch (JsonProcessingException e) {
87-
logger.error("Failed to validate CallToolResult: Error parsing schema: {}", e);
8887
return ValidationResponse.asInvalid("Error parsing tool JSON Schema: " + e.getMessage());
8988
}
9089
catch (Exception e) {
91-
logger.error("Failed to validate CallToolResult: Unexpected error: {}", e);
9290
return ValidationResponse.asInvalid("Unexpected validation error: " + e.getMessage());
9391
}
9492
}
@@ -113,7 +111,6 @@ public ValidationResponse validateSchema(Map<String, Object> schema) {
113111
return ValidationResponse.asValid(null);
114112
}
115113
catch (Exception e) {
116-
logger.error("Failed to validate schema definition: {}", e.getMessage());
117114
return ValidationResponse.asInvalid("Failed to validate schema definition: " + e.getMessage());
118115
}
119116
}

mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/schema/jackson3/DefaultJsonSchemaValidator.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,9 @@ public ValidationResponse validate(Map<String, Object> schema, Object structured
8383

8484
}
8585
catch (JacksonException e) {
86-
logger.error("Failed to validate CallToolResult: Error parsing schema: {}", e);
8786
return ValidationResponse.asInvalid("Error parsing tool JSON Schema: " + e.getMessage());
8887
}
8988
catch (Exception e) {
90-
logger.error("Failed to validate CallToolResult: Unexpected error: {}", e);
9189
return ValidationResponse.asInvalid("Unexpected validation error: " + e.getMessage());
9290
}
9391
}
@@ -112,7 +110,6 @@ public ValidationResponse validateSchema(Map<String, Object> schema) {
112110
return ValidationResponse.asValid(null);
113111
}
114112
catch (Exception e) {
115-
logger.error("Failed to validate schema definition: {}", e.getMessage());
116113
return ValidationResponse.asInvalid("Failed to validate schema definition: " + e.getMessage());
117114
}
118115
}

0 commit comments

Comments
 (0)