diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java index ce333675f..f62cd7c71 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java @@ -250,7 +250,6 @@ public McpSchema.InitializeResult currentInitializationResult() { * @param t The exception to handle */ public void handleException(Throwable t) { - logger.warn("Handling exception", t); if (t instanceof McpTransportSessionNotFoundException) { DefaultInitialization previous = this.initializationRef.getAndSet(null); if (previous != null) { diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java index 5556cd36e..810cc2026 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java @@ -484,9 +484,7 @@ public Mono addRoot(Root root) { if (this.isInitialized()) { return this.rootsListChangedNotification(); } - else { - logger.warn("Client is not initialized, ignore sending a roots list changed notification"); - } + logger.debug("Client is not initialized, ignore sending a roots list changed notification"); } return Mono.empty(); } @@ -514,10 +512,7 @@ public Mono removeRoot(String rootUri) { if (this.isInitialized()) { return this.rootsListChangedNotification(); } - else { - logger.warn("Client is not initialized, ignore sending a roots list changed notification"); - } - + logger.debug("Client is not initialized, ignore sending a roots list changed notification"); } return Mono.empty(); } diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java index 1b4eaca97..e73e43ef5 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java @@ -10,10 +10,13 @@ import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Executors; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.IntStream; import io.modelcontextprotocol.json.TypeRef; import io.modelcontextprotocol.json.McpJsonMapper; @@ -41,6 +44,15 @@ public class StdioClientTransport implements McpClientTransport { private static final Logger logger = LoggerFactory.getLogger(StdioClientTransport.class); + // @formatter:off + private static final Set EXIT_SUCCESS_CODES = Set.of( + 0, // success + 130, // interrupted (SIGINT) + 141, // pipeline shortcut (SIGPIPE) + 143 // graceful termination (SIGTERM) + ); + // @formatter:on + private final Sinks.Many inboundSink; private final Sinks.Many outboundSink; @@ -356,11 +368,12 @@ public Mono closeGracefully() { return Mono.empty(); } })).doOnNext(process -> { - if (process.exitValue() != 0) { - logger.warn("Process terminated with code {}", process.exitValue()); + int exitValue = process.exitValue(); + if (EXIT_SUCCESS_CODES.contains(exitValue)) { + logger.info("MCP server completed successfully with code {}", exitValue); } else { - logger.info("MCP server process stopped"); + logger.warn("MCP server process failed with code {}", exitValue); } }).then(Mono.fromRunnable(() -> { try { diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java index 2044d8b38..46b10985d 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java @@ -513,14 +513,13 @@ public Mono removeTool(String toolName) { return Mono.defer(() -> { if (this.tools.removeIf(toolSpecification -> toolSpecification.tool().name().equals(toolName))) { - logger.debug("Removed tool handler: {}", toolName); if (this.serverCapabilities.tools().listChanged()) { return notifyToolsListChanged(); } } else { - logger.warn("Ignore as a Tool with name '{}' not found", toolName); + logger.warn("Failed to remove tool with name '{}' (not found)", toolName); } return Mono.empty(); @@ -637,7 +636,7 @@ public Mono removeResource(String resourceUri) { return Mono.empty(); } else { - logger.warn("Ignore as a Resource with URI '{}' not found", resourceUri); + logger.warn("Failed to remove resource with URI '{}' (not found)", resourceUri); } return Mono.empty(); }); @@ -701,7 +700,7 @@ public Mono removeResourceTemplate(String uriTemplate) { logger.debug("Removed resource template: {}", uriTemplate); } else { - logger.warn("Ignore as a Resource Template with URI '{}' not found", uriTemplate); + logger.warn("Failed to remove a resource template with URI '{}' (not found)", uriTemplate); } return Mono.empty(); }); @@ -907,7 +906,7 @@ public Mono removePrompt(String promptName) { return Mono.empty(); } else { - logger.warn("Ignore as a Prompt with name '{}' not found", promptName); + logger.warn("Failed to remove a prompt with name '{}' (not found)", promptName); } return Mono.empty(); }); diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpStatelessAsyncServer.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpStatelessAsyncServer.java index 3d7054cba..48b17ed2a 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpStatelessAsyncServer.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpStatelessAsyncServer.java @@ -390,7 +390,7 @@ public Mono removeTool(String toolName) { logger.debug("Removed tool handler: {}", toolName); } else { - logger.warn("Ignore as a Tool with name '{}' not found", toolName); + logger.warn("Failed to remove a tool with name '{}' (not found)", toolName); } return Mono.empty(); @@ -492,7 +492,7 @@ public Mono removeResource(String resourceUri) { logger.debug("Removed resource handler: {}", resourceUri); } else { - logger.warn("Resource with URI '{}' not found", resourceUri); + logger.warn("Failed to remove a resource with URI '{}' (not found)", resourceUri); } return Mono.empty(); }); @@ -554,7 +554,7 @@ public Mono removeResourceTemplate(String uriTemplate) { logger.debug("Removed resource template: {}", uriTemplate); } else { - logger.warn("Ignore as a Resource Template with URI '{}' not found", uriTemplate); + logger.warn("Failed to remove a resource template with URI '{}' (not found)", uriTemplate); } return Mono.empty(); }); @@ -677,7 +677,7 @@ public Mono removePrompt(String promptName) { return Mono.empty(); } else { - logger.warn("Ignore as a Prompt with name '{}' not found", promptName); + logger.warn("Failed to remove a prompt with name '{}' (not found)", promptName); } return Mono.empty(); diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java index 9a785e150..d956a8726 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java @@ -200,7 +200,7 @@ public Mono notifyClients(String method, Object params) { session.sendNotification(method, params).block(); } catch (Exception e) { - logger.error("Failed to send message to session {}: {}", session.getId(), e.getMessage()); + logger.info("Failed to send message to session {}: {}", session.getId(), e.getMessage()); } }); }); @@ -233,12 +233,11 @@ public Mono closeGracefully() { session.closeGracefully().block(); } catch (Exception e) { - logger.error("Failed to close session {}: {}", session.getId(), e.getMessage()); + logger.warn("Failed to close session {}: {}", session.getId(), e.getMessage()); } }); this.sessions.clear(); - logger.debug("Graceful shutdown completed"); }).then().doOnSuccess(v -> { sessions.clear(); logger.debug("Graceful shutdown completed"); diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java index a5a51bff0..d6f6c0083 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpClientSession.java @@ -124,7 +124,7 @@ public McpClientSession(Duration requestTimeout, McpClientTransport transport, private void dismissPendingResponses() { this.pendingResponses.forEach((id, sink) -> { - logger.warn("Abruptly terminating exchange for request {}", id); + logger.info("Abruptly terminating exchange for request {}", id); sink.error(new RuntimeException("MCP session with server terminated")); }); this.pendingResponses.clear(); @@ -257,7 +257,8 @@ public Mono sendRequest(String method, Object requestParams, TypeRef t }); })).timeout(this.requestTimeout).handle((jsonRpcResponse, deliveredResponseSink) -> { if (jsonRpcResponse.error() != null) { - logger.error("Error handling request: {}", jsonRpcResponse.error()); + logger.info("Server returned a JSON-RPC error when calling method {}: {}", method, + jsonRpcResponse.error()); deliveredResponseSink.error(new McpError(jsonRpcResponse.error())); } else { diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java index 4655167ab..8f86138f0 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java @@ -256,8 +256,8 @@ else if (message instanceof McpSchema.JSONRPCNotification notification) { // happening first logger.debug("Received notification: {}", notification); // TODO: in case of error, should the POST request be signalled? - return handleIncomingNotification(notification, transportContext) - .doOnError(error -> logger.error("Error handling notification: {}", error.getMessage())); + return handleIncomingNotification(notification, transportContext).doOnError( + error -> logger.warn("Error handling notification {}: {}", notification, error.getMessage())); } else { logger.warn("Received unknown message type: {}", message); diff --git a/mcp-json-jackson2/src/main/java/io/modelcontextprotocol/json/schema/jackson2/DefaultJsonSchemaValidator.java b/mcp-json-jackson2/src/main/java/io/modelcontextprotocol/json/schema/jackson2/DefaultJsonSchemaValidator.java index 9975ce05f..d632b2d16 100644 --- a/mcp-json-jackson2/src/main/java/io/modelcontextprotocol/json/schema/jackson2/DefaultJsonSchemaValidator.java +++ b/mcp-json-jackson2/src/main/java/io/modelcontextprotocol/json/schema/jackson2/DefaultJsonSchemaValidator.java @@ -84,11 +84,9 @@ public ValidationResponse validate(Map schema, Object structured } catch (JsonProcessingException e) { - logger.error("Failed to validate CallToolResult: Error parsing schema: {}", e); return ValidationResponse.asInvalid("Error parsing tool JSON Schema: " + e.getMessage()); } catch (Exception e) { - logger.error("Failed to validate CallToolResult: Unexpected error: {}", e); return ValidationResponse.asInvalid("Unexpected validation error: " + e.getMessage()); } } @@ -113,7 +111,6 @@ public ValidationResponse validateSchema(Map schema) { return ValidationResponse.asValid(null); } catch (Exception e) { - logger.error("Failed to validate schema definition: {}", e.getMessage()); return ValidationResponse.asInvalid("Failed to validate schema definition: " + e.getMessage()); } } diff --git a/mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/schema/jackson3/DefaultJsonSchemaValidator.java b/mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/schema/jackson3/DefaultJsonSchemaValidator.java index d8ad09303..284289895 100644 --- a/mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/schema/jackson3/DefaultJsonSchemaValidator.java +++ b/mcp-json-jackson3/src/main/java/io/modelcontextprotocol/json/schema/jackson3/DefaultJsonSchemaValidator.java @@ -83,11 +83,9 @@ public ValidationResponse validate(Map schema, Object structured } catch (JacksonException e) { - logger.error("Failed to validate CallToolResult: Error parsing schema: {}", e); return ValidationResponse.asInvalid("Error parsing tool JSON Schema: " + e.getMessage()); } catch (Exception e) { - logger.error("Failed to validate CallToolResult: Unexpected error: {}", e); return ValidationResponse.asInvalid("Unexpected validation error: " + e.getMessage()); } } @@ -112,7 +110,6 @@ public ValidationResponse validateSchema(Map schema) { return ValidationResponse.asValid(null); } catch (Exception e) { - logger.error("Failed to validate schema definition: {}", e.getMessage()); return ValidationResponse.asInvalid("Failed to validate schema definition: " + e.getMessage()); } } diff --git a/mcp-test/src/test/resources/logback-test.xml b/mcp-test/src/test/resources/logback-test.xml new file mode 100644 index 000000000..7b87222c2 --- /dev/null +++ b/mcp-test/src/test/resources/logback-test.xml @@ -0,0 +1,37 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level [DOCKER] %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + +