diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfiguration.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfiguration.java index 5c8d9f140ec..84322fa0835 100644 --- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfiguration.java +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/main/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfiguration.java @@ -55,6 +55,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; import org.springframework.core.log.LogAccessor; import org.springframework.util.CollectionUtils; import org.springframework.util.MimeType; @@ -168,6 +169,7 @@ private List toSyncToolSpecifications(L } @Bean + @Lazy(false) @ConditionalOnProperty(prefix = McpServerProperties.CONFIG_PREFIX, name = "type", havingValue = "SYNC", matchIfMissing = true) public McpSyncServer mcpSyncServer(McpServerTransportProvider transportProvider, @@ -299,6 +301,7 @@ private List toAsyncToolSpecification( } @Bean + @Lazy(false) @ConditionalOnProperty(prefix = McpServerProperties.CONFIG_PREFIX, name = "type", havingValue = "ASYNC") public McpAsyncServer mcpAsyncServer(McpServerTransportProvider transportProvider, McpSchema.ServerCapabilities.Builder capabilitiesBuilder, McpServerProperties serverProperties, diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfigurationIT.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfigurationIT.java index 07fd683403e..53bb2da4bd2 100644 --- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfigurationIT.java +++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerAutoConfigurationIT.java @@ -490,6 +490,40 @@ public Mono closeGracefully() { } + @Test + void lazyInitializationConfiguration() { + this.contextRunner.withPropertyValues("spring.main.lazy-initialization=true").run(context -> { + // With lazy initialization enabled, MCP servers should still be created due + // to @Lazy(false) + assertThat(context).hasSingleBean(McpSyncServer.class); + assertThat(context).doesNotHaveBean(McpAsyncServer.class); + + // Verify properties are properly configured even with lazy init + McpServerProperties properties = context.getBean(McpServerProperties.class); + assertThat(properties.getName()).isEqualTo("mcp-server"); + assertThat(properties.getType()).isEqualTo(McpServerProperties.ServerType.SYNC); + + // Verify server is properly initialized (not just created) + McpSyncServer server = context.getBean(McpSyncServer.class); + assertThat(server).isNotNull(); + }); + } + + @Test + void asyncServerLazyInitializationConfiguration() { + this.contextRunner.withPropertyValues("spring.main.lazy-initialization=true", "spring.ai.mcp.server.type=ASYNC") + .run(context -> { + // With lazy initialization enabled, async MCP server should still be + // created due to @Lazy(false) + assertThat(context).hasSingleBean(McpAsyncServer.class); + assertThat(context).doesNotHaveBean(McpSyncServer.class); + + // Verify server is properly initialized (not just created) + McpAsyncServer server = context.getBean(McpAsyncServer.class); + assertThat(server).isNotNull(); + }); + } + @Configuration static class CustomTransportConfiguration { 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 index 5f0e5fc4baa..e4cae829b67 100644 --- 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 @@ -68,4 +68,21 @@ void serverBaseUrlConfiguration() { .isEqualTo("/test")); } + @Test + void lazyInitializationWithWebMvcCompatibility() { + this.contextRunner.withPropertyValues("spring.main.lazy-initialization=true").run(context -> { + // Even with lazy initialization, WebMvc transport should work properly + assertThat(context).hasSingleBean(WebMvcSseServerTransportProvider.class); + assertThat(context).hasSingleBean(RouterFunction.class); + + // Transport provider should be properly configured + WebMvcSseServerTransportProvider transport = context.getBean(WebMvcSseServerTransportProvider.class); + assertThat(transport).isNotNull(); + + // Router function should be available + RouterFunction routerFunction = context.getBean(RouterFunction.class); + assertThat(routerFunction).isNotNull(); + }); + } + }