Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ public WebFluxSseServerTransportProvider webFluxTransport(ObjectProvider<ObjectM
// Router function for SSE transport used by Spring WebFlux to start an HTTP
// server.
@Bean
public RouterFunction<?> webfluxMcpRouterFunction(WebFluxSseServerTransportProvider webFluxProvider) {
@ConditionalOnMissingBean(name = "webfluxSseServerRouterFunction")
public RouterFunction<?> webfluxSseServerRouterFunction(WebFluxSseServerTransportProvider webFluxProvider) {
return webFluxProvider.getRouterFunction();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

/**
* @author Christian Tzolov
* @author Yanming Zhou
*/
@AutoConfiguration(before = McpServerStatelessAutoConfiguration.class)
@ConditionalOnClass({ McpSchema.class })
Expand All @@ -60,6 +61,7 @@ public WebFluxStatelessServerTransport webFluxStatelessServerTransport(
// Router function for stateless http transport used by Spring WebFlux to start an
// HTTP server.
@Bean
@ConditionalOnMissingBean(name = "webFluxStatelessServerRouterFunction")
public RouterFunction<?> webFluxStatelessServerRouterFunction(
WebFluxStatelessServerTransport webFluxStatelessTransport) {
return webFluxStatelessTransport.getRouterFunction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

/**
* @author Christian Tzolov
* @author Yanming Zhou
*/
@AutoConfiguration(before = McpServerAutoConfiguration.class)
@ConditionalOnClass({ McpSchema.class })
Expand All @@ -62,6 +63,7 @@ public WebFluxStreamableServerTransportProvider webFluxStreamableServerTransport
// Router function for streamable http transport used by Spring WebFlux to start an
// HTTP server.
@Bean
@ConditionalOnMissingBean(name = "webFluxStreamableServerRouterFunction")
public RouterFunction<?> webFluxStreamableServerRouterFunction(
WebFluxStreamableServerTransportProvider webFluxProvider) {
return webFluxProvider.getRouterFunction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import org.springframework.web.reactive.function.server.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerSseWebFluxAutoConfigurationIT {

Expand Down Expand Up @@ -96,4 +98,30 @@ void serverBaseUrlConfiguration() {
.isEqualTo("/test"));
}

@Test
void routerFunctionIsCreatedFromProvider() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);
assertThat(context).hasSingleBean(WebFluxSseServerTransportProvider.class);

// Verify that the RouterFunction is created from the provider
WebFluxSseServerTransportProvider serverTransport = context
.getBean(WebFluxSseServerTransportProvider.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull().isEqualTo(serverTransport.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webfluxSseServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@

import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerStatelessWebFluxAutoConfigurationIT {

Expand Down Expand Up @@ -135,11 +139,24 @@ void routerFunctionIsCreatedFromProvider() {
assertThat(context).hasSingleBean(WebFluxStatelessServerTransport.class);

// Verify that the RouterFunction is created from the provider
WebFluxStatelessServerTransport serverTransport = context.getBean(WebFluxStatelessServerTransport.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull();
assertThat(routerFunction).isNotNull().isEqualTo(serverTransport.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webFluxStatelessServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

@Test
void allPropertiesConfiguration() {
this.contextRunner
Expand Down Expand Up @@ -172,4 +189,15 @@ void enabledPropertyExplicitlyTrue() {
});
}

@Configuration
private static class CustomRouterFunctionConfig {

@Bean
public RouterFunction<?> webFluxStatelessServerRouterFunction(
WebFluxStatelessServerTransport webFluxStatelessTransport) {
return mock(RouterFunction.class);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.springframework.web.reactive.function.server.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerStreamableWebFluxAutoConfigurationIT {

Expand Down Expand Up @@ -137,11 +139,25 @@ void routerFunctionIsCreatedFromProvider() {
assertThat(context).hasSingleBean(WebFluxStreamableServerTransportProvider.class);

// Verify that the RouterFunction is created from the provider
WebFluxStreamableServerTransportProvider serverTransport = context
.getBean(WebFluxStreamableServerTransportProvider.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull();
assertThat(routerFunction).isNotNull().isEqualTo(serverTransport.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webFluxStreamableServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

@Test
void allPropertiesConfiguration() {
this.contextRunner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider(
}

@Bean
public RouterFunction<ServerResponse> mvcMcpRouterFunction(WebMvcSseServerTransportProvider transportProvider) {
@ConditionalOnMissingBean(name = "webMvcSseServerRouterFunction")
public RouterFunction<ServerResponse> webMvcSseServerRouterFunction(
WebMvcSseServerTransportProvider transportProvider) {
return transportProvider.getRouterFunction();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;

/**
* @author Christian Tzolov
* @author Yanming Zhou
*/
@AutoConfiguration(before = McpServerStatelessAutoConfiguration.class)
@ConditionalOnClass({ McpSchema.class })
Expand All @@ -60,7 +62,8 @@ public WebMvcStatelessServerTransport webMvcStatelessServerTransport(
// Router function for stateless http transport used by Spring WebFlux to start an
// HTTP server.
@Bean
public RouterFunction<?> webMvcStatelessServerRouterFunction(
@ConditionalOnMissingBean(name = "webMvcStatelessServerRouterFunction")
public RouterFunction<ServerResponse> webMvcStatelessServerRouterFunction(
WebMvcStatelessServerTransport webMvcStatelessTransport) {
return webMvcStatelessTransport.getRouterFunction();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;

/**
* @author Christian Tzolov
* @author Yanming Zhou
*/
@AutoConfiguration(before = McpServerAutoConfiguration.class)
@ConditionalOnClass({ McpSchema.class })
Expand All @@ -62,7 +64,8 @@ public WebMvcStreamableServerTransportProvider webMvcStreamableServerTransportPr
// Router function for streamable http transport used by Spring WebFlux to start an
// HTTP server.
@Bean
public RouterFunction<?> webMvcStreamableServerRouterFunction(
@ConditionalOnMissingBean(name = "webMvcStreamableServerRouterFunction")
public RouterFunction<ServerResponse> webMvcStreamableServerRouterFunction(
WebMvcStreamableServerTransportProvider webMvcProvider) {
return webMvcProvider.getRouterFunction();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.springframework.web.servlet.function.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerSseWebMvcAutoConfigurationIT {

Expand Down Expand Up @@ -117,4 +119,29 @@ public ConfigurableEnvironment getEnvironment() {
});
}

@Test
void routerFunctionIsCreatedFromProvider() {
this.contextRunner.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);
assertThat(context).hasSingleBean(WebMvcSseServerTransportProvider.class);

// Verify that the RouterFunction is created from the provider
WebMvcSseServerTransportProvider serverTransport = context.getBean(WebMvcSseServerTransportProvider.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull().isEqualTo(serverTransport.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webMvcSseServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.springframework.web.servlet.function.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerStatelessWebMvcAutoConfigurationIT {

Expand Down Expand Up @@ -135,11 +137,24 @@ void routerFunctionIsCreatedFromProvider() {
assertThat(context).hasSingleBean(WebMvcStatelessServerTransport.class);

// Verify that the RouterFunction is created from the provider
WebMvcStatelessServerTransport serverTransport = context.getBean(WebMvcStatelessServerTransport.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull();
assertThat(routerFunction).isNotNull().isEqualTo(serverTransport.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webMvcStatelessServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

@Test
void allPropertiesConfiguration() {
this.contextRunner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.springframework.web.servlet.function.RouterFunction;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;

class McpServerStreamableWebMvcAutoConfigurationIT {

Expand Down Expand Up @@ -137,11 +139,25 @@ void routerFunctionIsCreatedFromProvider() {
assertThat(context).hasSingleBean(WebMvcStreamableServerTransportProvider.class);

// Verify that the RouterFunction is created from the provider
WebMvcStreamableServerTransportProvider serverTransportProvider = context
.getBean(WebMvcStreamableServerTransportProvider.class);
RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(routerFunction).isNotNull();
assertThat(routerFunction).isNotNull().isEqualTo(serverTransportProvider.getRouterFunction());
});
}

@Test
void routerFunctionIsCustom() {
this.contextRunner
.withBean("webMvcStreamableServerRouterFunction", RouterFunction.class, () -> mock(RouterFunction.class))
.run(context -> {
assertThat(context).hasSingleBean(RouterFunction.class);

RouterFunction<?> routerFunction = context.getBean(RouterFunction.class);
assertThat(mockingDetails(routerFunction).isMock()).isTrue();
});
}

@Test
void allPropertiesConfiguration() {
this.contextRunner
Expand Down