diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransport.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransport.java index 2dbc929..bed7293 100644 --- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransport.java +++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransport.java @@ -251,7 +251,7 @@ public class WebFluxSseServerTransport implements ServerMcpTransport { .then(Mono.fromRunnable(() -> sessions.remove(sessionId))); }).toList())) .timeout(Duration.ofSeconds(5)) - .doOnSuccess(v -> logger.info("Graceful shutdown completed")) + .doOnSuccess(v -> logger.debug("Graceful shutdown completed")) .doOnError(e -> logger.error("Error during graceful shutdown: {}", e.getMessage())); } diff --git a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransport.java b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransport.java index 7339311..f2d1d3e 100644 --- a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransport.java +++ b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransport.java @@ -353,7 +353,7 @@ public class WebMvcSseServerTransport implements ServerMcpTransport { sessions.remove(sessionId); }); - logger.info("Graceful shutdown completed"); + logger.debug("Graceful shutdown completed"); }); } diff --git a/mcp/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java b/mcp/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java index 31d3175..a49ad7f 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java +++ b/mcp/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java @@ -173,7 +173,7 @@ public class McpAsyncClient { // Tools Change Notification List, Mono>> toolsChangeConsumersFinal = new ArrayList<>(); toolsChangeConsumersFinal - .add((notification) -> Mono.fromRunnable(() -> logger.info("Tools changed: {}", notification))); + .add((notification) -> Mono.fromRunnable(() -> logger.debug("Tools changed: {}", notification))); if (!Utils.isEmpty(features.toolsChangeConsumers())) { toolsChangeConsumersFinal.addAll(features.toolsChangeConsumers()); @@ -184,7 +184,7 @@ public class McpAsyncClient { // Resources Change Notification List, Mono>> resourcesChangeConsumersFinal = new ArrayList<>(); resourcesChangeConsumersFinal - .add((notification) -> Mono.fromRunnable(() -> logger.info("Resources changed: {}", notification))); + .add((notification) -> Mono.fromRunnable(() -> logger.debug("Resources changed: {}", notification))); if (!Utils.isEmpty(features.resourcesChangeConsumers())) { resourcesChangeConsumersFinal.addAll(features.resourcesChangeConsumers()); @@ -196,7 +196,7 @@ public class McpAsyncClient { // Prompts Change Notification List, Mono>> promptsChangeConsumersFinal = new ArrayList<>(); promptsChangeConsumersFinal - .add((notification) -> Mono.fromRunnable(() -> logger.info("Prompts changed: {}", notification))); + .add((notification) -> Mono.fromRunnable(() -> logger.debug("Prompts changed: {}", notification))); if (!Utils.isEmpty(features.promptsChangeConsumers())) { promptsChangeConsumersFinal.addAll(features.promptsChangeConsumers()); } @@ -205,7 +205,7 @@ public class McpAsyncClient { // Utility Logging Notification List>> loggingConsumersFinal = new ArrayList<>(); - loggingConsumersFinal.add((notification) -> Mono.fromRunnable(() -> logger.info("Logging: {}", notification))); + loggingConsumersFinal.add((notification) -> Mono.fromRunnable(() -> logger.debug("Logging: {}", notification))); if (!Utils.isEmpty(features.loggingConsumers())) { loggingConsumersFinal.addAll(features.loggingConsumers()); } @@ -364,7 +364,7 @@ public class McpAsyncClient { this.roots.put(root.uri(), root); - logger.info("Added root: {}", root); + logger.debug("Added root: {}", root); if (this.clientCapabilities.roots().listChanged()) { return this.rootsListChangedNotification(); @@ -390,7 +390,7 @@ public class McpAsyncClient { Root removed = this.roots.remove(rootUri); if (removed != null) { - logger.info("Removed Root: {}", rootUri); + logger.debug("Removed Root: {}", rootUri); if (this.clientCapabilities.roots().listChanged()) { return this.rootsListChangedNotification(); } diff --git a/mcp/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java b/mcp/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java index 462837b..614c651 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java +++ b/mcp/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java @@ -68,7 +68,7 @@ public class StdioClientTransport implements ClientMcpTransport { private volatile boolean isClosing = false; // visible for tests - private Consumer errorHandler = error -> logger.error("Error received: {}", error); + private Consumer stdErrorHandler = error -> logger.info("STDERR Message received: {}", error); /** * Creates a new StdioClientTransport with the specified parameters and default @@ -164,8 +164,8 @@ public class StdioClientTransport implements ClientMcpTransport { *

* @param errorHandler a consumer that processes error messages */ - public void setErrorHandler(Consumer errorHandler) { - this.errorHandler = errorHandler; + public void setStdErrorHandler(Consumer errorHandler) { + this.stdErrorHandler = errorHandler; } /** @@ -192,7 +192,6 @@ public class StdioClientTransport implements ClientMcpTransport { String line; while (!isClosing && (line = processErrorReader.readLine()) != null) { try { - logger.error("Received error line: {}", line); if (!this.errorSink.tryEmitNext(line).isSuccess()) { if (!isClosing) { logger.error("Failed to emit error message"); @@ -230,7 +229,7 @@ public class StdioClientTransport implements ClientMcpTransport { private void handleIncomingErrors() { this.errorSink.asFlux().subscribe(e -> { - this.errorHandler.accept(e); + this.stdErrorHandler.accept(e); }); } @@ -355,7 +354,7 @@ public class StdioClientTransport implements ClientMcpTransport { // Give a short time for any pending messages to be processed return Mono.delay(Duration.ofMillis(100)); })).then(Mono.fromFuture(() -> { - logger.info("Sending TERM to process"); + logger.debug("Sending TERM to process"); if (this.process != null) { this.process.destroy(); return process.onExit(); @@ -375,7 +374,7 @@ public class StdioClientTransport implements ClientMcpTransport { errorScheduler.dispose(); outboundScheduler.dispose(); - logger.info("Graceful shutdown completed"); + logger.debug("Graceful shutdown completed"); } catch (Exception e) { logger.error("Error during graceful shutdown", e); diff --git a/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java b/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java index a6c9475..5fbc676 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java +++ b/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java @@ -318,7 +318,7 @@ public class McpAsyncServer { } this.tools.add(toolRegistration); - logger.info("Added tool handler: {}", toolRegistration.tool().name()); + logger.debug("Added tool handler: {}", toolRegistration.tool().name()); if (this.serverCapabilities.tools().listChanged()) { return notifyToolsListChanged(); @@ -343,7 +343,7 @@ public class McpAsyncServer { return Mono.defer(() -> { boolean removed = this.tools.removeIf(toolRegistration -> toolRegistration.tool().name().equals(toolName)); if (removed) { - logger.info("Removed tool handler: {}", toolName); + logger.debug("Removed tool handler: {}", toolName); if (this.serverCapabilities.tools().listChanged()) { return notifyToolsListChanged(); } @@ -411,7 +411,7 @@ public class McpAsyncServer { return Mono .error(new McpError("Resource with URI '" + resourceHandler.resource().uri() + "' already exists")); } - logger.info("Added resource handler: {}", resourceHandler.resource().uri()); + logger.debug("Added resource handler: {}", resourceHandler.resource().uri()); if (this.serverCapabilities.resources().listChanged()) { return notifyResourcesListChanged(); } @@ -435,7 +435,7 @@ public class McpAsyncServer { return Mono.defer(() -> { McpServerFeatures.AsyncResourceRegistration removed = this.resources.remove(resourceUri); if (removed != null) { - logger.info("Removed resource handler: {}", resourceUri); + logger.debug("Removed resource handler: {}", resourceUri); if (this.serverCapabilities.resources().listChanged()) { return notifyResourcesListChanged(); } @@ -507,7 +507,7 @@ public class McpAsyncServer { new McpError("Prompt with name '" + promptRegistration.prompt().name() + "' already exists")); } - logger.info("Added prompt handler: {}", promptRegistration.prompt().name()); + logger.debug("Added prompt handler: {}", promptRegistration.prompt().name()); // Servers that declared the listChanged capability SHOULD send a // notification, @@ -536,7 +536,7 @@ public class McpAsyncServer { McpServerFeatures.AsyncPromptRegistration removed = this.prompts.remove(promptName); if (removed != null) { - logger.info("Removed prompt handler: {}", promptName); + logger.debug("Removed prompt handler: {}", promptName); // Servers that declared the listChanged capability SHOULD send a // notification, when the list of available prompts changes if (this.serverCapabilities.prompts().listChanged()) { diff --git a/mcp/src/main/java/io/modelcontextprotocol/server/transport/StdioServerTransport.java b/mcp/src/main/java/io/modelcontextprotocol/server/transport/StdioServerTransport.java index 818aa28..e375cd1 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/server/transport/StdioServerTransport.java +++ b/mcp/src/main/java/io/modelcontextprotocol/server/transport/StdioServerTransport.java @@ -141,6 +141,8 @@ public class StdioServerTransport implements ServerMcpTransport { break; } + logger.debug("Received JSON message: {}", line); + try { JSONRPCMessage message = McpSchema.deserializeJsonRpcMessage(this.objectMapper, line); if (!this.inboundSink.tryEmitNext(message).isSuccess()) { @@ -229,7 +231,7 @@ public class StdioServerTransport implements ServerMcpTransport { // Completing the inbound causes the outbound to be completed as well, so // we only close the inbound. inboundSink.tryEmitComplete(); - logger.info("Graceful shutdown complete"); + logger.debug("Graceful shutdown complete"); return Mono.empty(); }).subscribeOn(Schedulers.boundedElastic()); } diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/DefaultMcpSession.java b/mcp/src/main/java/io/modelcontextprotocol/spec/DefaultMcpSession.java index eb7ce49..e2d354f 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/spec/DefaultMcpSession.java +++ b/mcp/src/main/java/io/modelcontextprotocol/spec/DefaultMcpSession.java @@ -124,7 +124,7 @@ public class DefaultMcpSession implements McpSession { // consumer this.connection = this.transport.connect(mono -> mono.doOnNext(message -> { if (message instanceof McpSchema.JSONRPCResponse response) { - logger.info("Received Response: {}", response); + logger.debug("Received Response: {}", response); var sink = pendingResponses.remove(response.id()); if (sink == null) { logger.warn("Unexpected response for unkown id {}", response.id()); @@ -134,7 +134,7 @@ public class DefaultMcpSession implements McpSession { } } else if (message instanceof McpSchema.JSONRPCRequest request) { - logger.info("Received request: {}", request); + logger.debug("Received request: {}", request); handleIncomingRequest(request).subscribe(response -> transport.sendMessage(response).subscribe(), error -> { var errorResponse = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), @@ -144,7 +144,7 @@ public class DefaultMcpSession implements McpSession { }); } else if (message instanceof McpSchema.JSONRPCNotification notification) { - logger.info("Received notification: {}", notification); + logger.debug("Received notification: {}", notification); handleIncomingNotification(notification).subscribe(null, error -> logger.error("Error handling notification: {}", error.getMessage())); } diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java index 1c6bb61..e721468 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java +++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java @@ -17,6 +17,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Based on the JSON-RPC 2.0 @@ -28,6 +30,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; */ public final class McpSchema { + private static final Logger logger = LoggerFactory.getLogger(McpSchema.class); + private McpSchema() { } @@ -144,6 +148,8 @@ public final class McpSchema { public static JSONRPCMessage deserializeJsonRpcMessage(ObjectMapper objectMapper, String jsonText) throws IOException { + logger.debug("Received JSON message: {}", jsonText); + var map = objectMapper.readValue(jsonText, MAP_TYPE_REF); // Determine message type based on specific JSON structure @@ -662,8 +668,8 @@ public final class McpSchema { @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) record JsonSchema( // @formatter:off - @JsonProperty("type") String type, - @JsonProperty("properties") Map properties, + @JsonProperty("type") String type, + @JsonProperty("properties") Map properties, @JsonProperty("required") List required, @JsonProperty("additionalProperties") Boolean additionalProperties) { } // @formatter:on diff --git a/mcp/src/test/java/io/modelcontextprotocol/client/StdioMcpSyncClientTests.java b/mcp/src/test/java/io/modelcontextprotocol/client/StdioMcpSyncClientTests.java index 9f2bc4a..7ae6525 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/client/StdioMcpSyncClientTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/client/StdioMcpSyncClientTests.java @@ -36,7 +36,7 @@ class StdioMcpSyncClientTests extends AbstractMcpSyncClientTests { void customErrorHandlerShouldReceiveErrors() { AtomicReference receivedError = new AtomicReference<>(); - ((StdioClientTransport) mcpTransport).setErrorHandler(error -> receivedError.set(error)); + ((StdioClientTransport) mcpTransport).setStdErrorHandler(error -> receivedError.set(error)); String errorMessage = "Test error"; ((StdioClientTransport) mcpTransport).getErrorSink().tryEmitNext(errorMessage);