@@ -65,11 +65,14 @@ public class HttpClientSseClientTransport implements McpClientTransport {
65
65
private static final String ENDPOINT_EVENT_TYPE = "endpoint" ;
66
66
67
67
/** Default SSE endpoint path */
68
- private static final String SSE_ENDPOINT = "/sse" ;
68
+ private static final String DEFAULT_SSE_ENDPOINT = "/sse" ;
69
69
70
70
/** Base URI for the MCP server */
71
71
private final String baseUri ;
72
72
73
+ /** SSE endpoint path */
74
+ private final String sseEndpoint ;
75
+
73
76
/** SSE client for handling server-sent events. Uses the /sse endpoint */
74
77
private final FlowSseClient sseClient ;
75
78
@@ -110,15 +113,104 @@ public HttpClientSseClientTransport(String baseUri) {
110
113
* @throws IllegalArgumentException if objectMapper or clientBuilder is null
111
114
*/
112
115
public HttpClientSseClientTransport (HttpClient .Builder clientBuilder , String baseUri , ObjectMapper objectMapper ) {
116
+ this (clientBuilder , baseUri , DEFAULT_SSE_ENDPOINT , objectMapper );
117
+ }
118
+
119
+ /**
120
+ * Creates a new transport instance with custom HTTP client builder and object mapper.
121
+ * @param clientBuilder the HTTP client builder to use
122
+ * @param baseUri the base URI of the MCP server
123
+ * @param sseEndpoint the SSE endpoint path
124
+ * @param objectMapper the object mapper for JSON serialization/deserialization
125
+ * @throws IllegalArgumentException if objectMapper or clientBuilder is null
126
+ */
127
+ public HttpClientSseClientTransport (HttpClient .Builder clientBuilder , String baseUri , String sseEndpoint ,
128
+ ObjectMapper objectMapper ) {
113
129
Assert .notNull (objectMapper , "ObjectMapper must not be null" );
114
130
Assert .hasText (baseUri , "baseUri must not be empty" );
131
+ Assert .hasText (sseEndpoint , "sseEndpoint must not be empty" );
115
132
Assert .notNull (clientBuilder , "clientBuilder must not be null" );
116
133
this .baseUri = baseUri ;
134
+ this .sseEndpoint = sseEndpoint ;
117
135
this .objectMapper = objectMapper ;
118
136
this .httpClient = clientBuilder .connectTimeout (Duration .ofSeconds (10 )).build ();
119
137
this .sseClient = new FlowSseClient (this .httpClient );
120
138
}
121
139
140
+ /**
141
+ * Creates a new builder for {@link HttpClientSseClientTransport}.
142
+ * @param baseUri the base URI of the MCP server
143
+ * @return a new builder instance
144
+ */
145
+ public static Builder builder (String baseUri ) {
146
+ return new Builder (baseUri );
147
+ }
148
+
149
+ /**
150
+ * Builder for {@link HttpClientSseClientTransport}.
151
+ */
152
+ public static class Builder {
153
+
154
+ private final String baseUri ;
155
+
156
+ private String sseEndpoint = DEFAULT_SSE_ENDPOINT ;
157
+
158
+ private HttpClient .Builder clientBuilder = HttpClient .newBuilder ();
159
+
160
+ private ObjectMapper objectMapper = new ObjectMapper ();
161
+
162
+ /**
163
+ * Creates a new builder with the specified base URI.
164
+ * @param baseUri the base URI of the MCP server
165
+ */
166
+ public Builder (String baseUri ) {
167
+ Assert .hasText (baseUri , "baseUri must not be empty" );
168
+ this .baseUri = baseUri ;
169
+ }
170
+
171
+ /**
172
+ * Sets the SSE endpoint path.
173
+ * @param sseEndpoint the SSE endpoint path
174
+ * @return this builder
175
+ */
176
+ public Builder sseEndpoint (String sseEndpoint ) {
177
+ Assert .hasText (sseEndpoint , "sseEndpoint must not be empty" );
178
+ this .sseEndpoint = sseEndpoint ;
179
+ return this ;
180
+ }
181
+
182
+ /**
183
+ * Sets the HTTP client builder.
184
+ * @param clientBuilder the HTTP client builder
185
+ * @return this builder
186
+ */
187
+ public Builder clientBuilder (HttpClient .Builder clientBuilder ) {
188
+ Assert .notNull (clientBuilder , "clientBuilder must not be null" );
189
+ this .clientBuilder = clientBuilder ;
190
+ return this ;
191
+ }
192
+
193
+ /**
194
+ * Sets the object mapper for JSON serialization/deserialization.
195
+ * @param objectMapper the object mapper
196
+ * @return this builder
197
+ */
198
+ public Builder objectMapper (ObjectMapper objectMapper ) {
199
+ Assert .notNull (objectMapper , "objectMapper must not be null" );
200
+ this .objectMapper = objectMapper ;
201
+ return this ;
202
+ }
203
+
204
+ /**
205
+ * Builds a new {@link HttpClientSseClientTransport} instance.
206
+ * @return a new transport instance
207
+ */
208
+ public HttpClientSseClientTransport build () {
209
+ return new HttpClientSseClientTransport (clientBuilder , baseUri , sseEndpoint , objectMapper );
210
+ }
211
+
212
+ }
213
+
122
214
/**
123
215
* Establishes the SSE connection with the server and sets up message handling.
124
216
*
@@ -137,7 +229,7 @@ public Mono<Void> connect(Function<Mono<JSONRPCMessage>, Mono<JSONRPCMessage>> h
137
229
CompletableFuture <Void > future = new CompletableFuture <>();
138
230
connectionFuture .set (future );
139
231
140
- sseClient .subscribe (this .baseUri + SSE_ENDPOINT , new FlowSseClient .SseEventHandler () {
232
+ sseClient .subscribe (this .baseUri + this . sseEndpoint , new FlowSseClient .SseEventHandler () {
141
233
@ Override
142
234
public void onEvent (SseEvent event ) {
143
235
if (isClosing ) {
0 commit comments