Skip to content

feat: Support separate registration and published paths in WebMvcSseS… #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
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 @@ -91,6 +91,8 @@ public class WebMvcSseServerTransportProvider implements McpServerTransportProvi

private final String sseEndpoint;

private final String publishedMessageEndpoint;

private final RouterFunction<ServerResponse> routerFunction;

private McpServerSession.Factory sessionFactory;
Expand All @@ -105,6 +107,36 @@ public class WebMvcSseServerTransportProvider implements McpServerTransportProvi
*/
private volatile boolean isClosing = false;

/**
* Constructs a new WebMvcSseServerTransportProvider instance.
*
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
* of messages.
* @param messageEndpoint The endpoint URI where clients should send their JSON-RPC
* messages via HTTP POST. This endpoint will be communicated to clients through the
* SSE connection's initial endpoint event.
* @param publishedMessageEndpoint The published endpoint URI that will be sent to clients
* (might differ from the actual messageEndpoint in case of proxies, load balancers, etc.)
* @param sseEndpoint The endpoint URI where clients establish their SSE connections.
* @throws IllegalArgumentException if any parameter is null
*/
public WebMvcSseServerTransportProvider(ObjectMapper objectMapper, String messageEndpoint,
String publishedMessageEndpoint, String sseEndpoint) {
Assert.notNull(objectMapper, "ObjectMapper must not be null");
Assert.notNull(messageEndpoint, "Message endpoint must not be null");
Assert.notNull(publishedMessageEndpoint, "Published message endpoint must not be null");
Assert.notNull(sseEndpoint, "SSE endpoint must not be null");

this.objectMapper = objectMapper;
this.messageEndpoint = messageEndpoint;
this.publishedMessageEndpoint = publishedMessageEndpoint;
this.sseEndpoint = sseEndpoint;
this.routerFunction = RouterFunctions.route()
.GET(this.sseEndpoint, this::handleSseConnection)
.POST(this.messageEndpoint, this::handleMessage)
.build();
}

/**
* Constructs a new WebMvcSseServerTransportProvider instance.
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
Expand All @@ -122,6 +154,7 @@ public WebMvcSseServerTransportProvider(ObjectMapper objectMapper, String messag

this.objectMapper = objectMapper;
this.messageEndpoint = messageEndpoint;
this.publishedMessageEndpoint = messageEndpoint;
this.sseEndpoint = sseEndpoint;
this.routerFunction = RouterFunctions.route()
.GET(this.sseEndpoint, this::handleSseConnection)
Expand Down Expand Up @@ -248,7 +281,7 @@ private ServerResponse handleSseConnection(ServerRequest request) {
try {
sseBuilder.id(sessionId)
.event(ENDPOINT_EVENT_TYPE)
.data(messageEndpoint + "?sessionId=" + sessionId);
.data(publishedMessageEndpoint + "?sessionId=" + sessionId);
}
catch (Exception e) {
logger.error("Failed to send initial endpoint event: {}", e.getMessage());
Expand Down