diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfiguration.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfiguration.java index eadb2b7cd90..8fe05c88057 100644 --- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfiguration.java +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfiguration.java @@ -20,6 +20,7 @@ import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider; import io.modelcontextprotocol.spec.McpServerTransportProvider; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -60,9 +61,9 @@ * } * * @author Christian Tzolov - * @since 1.0.0 * @see McpServerProperties * @see WebFluxSseServerTransportProvider + * @since 1.0.0 */ @AutoConfiguration @ConditionalOnClass({ WebFluxSseServerTransportProvider.class }) @@ -73,8 +74,10 @@ public class McpWebFluxServerAutoConfiguration { @Bean @ConditionalOnMissingBean - public WebFluxSseServerTransportProvider webFluxTransport(McpServerProperties serverProperties) { - return new WebFluxSseServerTransportProvider(new ObjectMapper(), serverProperties.getSseMessageEndpoint()); + public WebFluxSseServerTransportProvider webFluxTransport(ObjectProvider objectMapperProvider, + McpServerProperties serverProperties) { + ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new); + return new WebFluxSseServerTransportProvider(objectMapper, serverProperties.getSseMessageEndpoint()); } // Router function for SSE transport used by Spring WebFlux to start an HTTP server. diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfiguration.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfiguration.java index 828ef836a47..259fc3b37a2 100644 --- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfiguration.java +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfiguration.java @@ -20,6 +20,7 @@ import io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider; import io.modelcontextprotocol.spec.McpServerTransportProvider; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -68,8 +69,9 @@ public class McpWebMvcServerAutoConfiguration { @Bean @ConditionalOnMissingBean - public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider(ObjectMapper objectMapper, - McpServerProperties serverProperties) { + public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider( + ObjectProvider objectMapperProvider, McpServerProperties serverProperties) { + ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new); return new WebMvcSseServerTransportProvider(objectMapper, serverProperties.getSseMessageEndpoint()); } diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfigurationIT.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfigurationIT.java new file mode 100644 index 00000000000..5015c2682e1 --- /dev/null +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebFluxServerAutoConfigurationIT.java @@ -0,0 +1,41 @@ +package org.springframework.ai.mcp.server.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.modelcontextprotocol.server.transport.WebFluxSseServerTransport; +import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.web.reactive.function.server.RouterFunction; + +import static org.assertj.core.api.Assertions.assertThat; + +class McpWebFluxServerAutoConfigurationIT { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( + AutoConfigurations.of(McpWebFluxServerAutoConfiguration.class, McpServerAutoConfiguration.class)); + + @Test + void defaultConfiguration() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(WebFluxSseServerTransportProvider.class); + assertThat(context).hasSingleBean(RouterFunction.class); + }); + } + + @Test + void objectMapperConfiguration() { + this.contextRunner.withBean(ObjectMapper.class, ObjectMapper::new).run(context -> { + assertThat(context).hasSingleBean(WebFluxSseServerTransportProvider.class); + assertThat(context).hasSingleBean(RouterFunction.class); + }); + } + + @Test + void stdioEnabledConfiguration() { + this.contextRunner.withPropertyValues("spring.ai.mcp.server.stdio=true").run(context -> { + assertThat(context).doesNotHaveBean(WebFluxSseServerTransportProvider.class); + }); + } + +} diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfigurationIT.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfigurationIT.java new file mode 100644 index 00000000000..67265f1fb16 --- /dev/null +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpWebMvcServerAutoConfigurationIT.java @@ -0,0 +1,39 @@ +package org.springframework.ai.mcp.server.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.web.servlet.function.RouterFunction; +import static org.assertj.core.api.Assertions.assertThat; + +class McpWebMvcServerAutoConfigurationIT { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( + AutoConfigurations.of(McpWebMvcServerAutoConfiguration.class, McpServerAutoConfiguration.class)); + + @Test + void defaultConfiguration() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(WebMvcSseServerTransportProvider.class); + assertThat(context).hasSingleBean(RouterFunction.class); + }); + } + + @Test + void objectMapperConfiguration() { + this.contextRunner.withBean(ObjectMapper.class, ObjectMapper::new).run(context -> { + assertThat(context).hasSingleBean(WebMvcSseServerTransportProvider.class); + assertThat(context).hasSingleBean(RouterFunction.class); + }); + } + + @Test + void stdioEnabledConfiguration() { + this.contextRunner.withPropertyValues("spring.ai.mcp.server.stdio=true").run(context -> { + assertThat(context).doesNotHaveBean(WebMvcSseServerTransportProvider.class); + }); + } + +}