Skip to content

Commit ea500a4

Browse files
committed
Fix the baseUrl is configured with a trailing slash
Signed-off-by: lance <leehaut@gmail.com>
1 parent e5e4441 commit ea500a4

File tree

5 files changed

+55
-436
lines changed

5 files changed

+55
-436
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletSseServerTransportProvider.java

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
import java.util.concurrent.ConcurrentHashMap;
1515
import java.util.concurrent.atomic.AtomicBoolean;
1616

17+
import io.modelcontextprotocol.common.McpTransportContext;
1718
import io.modelcontextprotocol.json.McpJsonMapper;
1819
import io.modelcontextprotocol.json.TypeRef;
19-
import io.modelcontextprotocol.common.McpTransportContext;
2020
import io.modelcontextprotocol.server.McpTransportContextExtractor;
2121
import io.modelcontextprotocol.spec.McpError;
2222
import io.modelcontextprotocol.spec.McpSchema;
@@ -26,7 +26,6 @@
2626
import io.modelcontextprotocol.spec.ProtocolVersions;
2727
import io.modelcontextprotocol.util.Assert;
2828
import io.modelcontextprotocol.util.KeepAliveScheduler;
29-
import io.modelcontextprotocol.util.UriBuilder;
3029
import jakarta.servlet.AsyncContext;
3130
import jakarta.servlet.ServletException;
3231
import jakarta.servlet.annotation.WebServlet;
@@ -70,7 +69,9 @@
7069
@WebServlet(asyncSupported = true)
7170
public class HttpServletSseServerTransportProvider extends HttpServlet implements McpServerTransportProvider {
7271

73-
/** Logger for this class */
72+
/**
73+
* Logger for this class
74+
*/
7475
private static final Logger logger = LoggerFactory.getLogger(HttpServletSseServerTransportProvider.class);
7576

7677
public static final String UTF_8 = "UTF-8";
@@ -79,40 +80,60 @@ public class HttpServletSseServerTransportProvider extends HttpServlet implement
7980

8081
public static final String FAILED_TO_SEND_ERROR_RESPONSE = "Failed to send error response: {}";
8182

82-
/** Default endpoint path for SSE connections */
83+
/**
84+
* Default endpoint path for SSE connections
85+
*/
8386
public static final String DEFAULT_SSE_ENDPOINT = "/sse";
8487

85-
/** Event type for regular messages */
88+
/**
89+
* Event type for regular messages
90+
*/
8691
public static final String MESSAGE_EVENT_TYPE = "message";
8792

88-
/** Event type for endpoint information */
93+
/**
94+
* Event type for endpoint information
95+
*/
8996
public static final String ENDPOINT_EVENT_TYPE = "endpoint";
9097

9198
public static final String SESSION_ID = "sessionId";
9299

93100
public static final String DEFAULT_BASE_URL = "";
94101

95-
/** JSON mapper for serialization/deserialization */
102+
/**
103+
* JSON mapper for serialization/deserialization
104+
*/
96105
private final McpJsonMapper jsonMapper;
97106

98-
/** Base URL for the server transport */
107+
/**
108+
* Base URL for the server transport
109+
*/
99110
private final String baseUrl;
100111

101-
/** The endpoint path for handling client messages */
112+
/**
113+
* The endpoint path for handling client messages
114+
*/
102115
private final String messageEndpoint;
103116

104-
/** The endpoint path for handling SSE connections */
117+
/**
118+
* The endpoint path for handling SSE connections
119+
*/
105120
private final String sseEndpoint;
106121

107-
/** Map of active client sessions, keyed by session ID */
122+
/**
123+
* Map of active client sessions, keyed by session ID
124+
*/
108125
private final Map<String, McpServerSession> sessions = new ConcurrentHashMap<>();
109126

110127
private McpTransportContextExtractor<HttpServletRequest> contextExtractor;
111128

112-
/** Flag indicating if the transport is in the process of shutting down */
129+
/**
130+
* Flag indicating if the transport is in the process of shutting down
131+
*/
113132
private final AtomicBoolean isClosing = new AtomicBoolean(false);
114133

115-
/** Session factory for creating new sessions */
134+
/**
135+
* Session factory for creating new sessions
136+
*/
116137
private McpServerSession.Factory sessionFactory;
117138

118139
/**
@@ -256,7 +277,12 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
256277
* @return the fully qualified endpoint URL as a string
257278
*/
258279
private String buildEndpointUrl(String sessionId) {
259-
return UriBuilder.from(this.baseUrl).path(this.messageEndpoint).queryParam(SESSION_ID, sessionId).buildString();
280+
// for WebMVC compatibility
281+
if (this.baseUrl.endsWith("/")) {
282+
return this.baseUrl.substring(0, this.baseUrl.length() - 1) + this.messageEndpoint + "?sessionId="
283+
+ sessionId;
284+
}
285+
return this.baseUrl + this.messageEndpoint + "?sessionId=" + sessionId;
260286
}
261287

262288
/**
@@ -447,8 +473,8 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
447473
* Converts data from one type to another using the configured JsonMapper.
448474
* @param data The source data object to convert
449475
* @param typeRef The target type reference
450-
* @return The converted object of type T
451476
* @param <T> The target type
477+
* @return The converted object of type T
452478
*/
453479
@Override
454480
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {

0 commit comments

Comments
 (0)