14
14
15
15
import com .fasterxml .jackson .core .type .TypeReference ;
16
16
import com .fasterxml .jackson .databind .ObjectMapper ;
17
+ import io .modelcontextprotocol .server .DefaultMcpTransportContext ;
18
+ import io .modelcontextprotocol .server .McpTransportContext ;
19
+ import io .modelcontextprotocol .server .McpTransportContextExtractor ;
17
20
import io .modelcontextprotocol .spec .McpError ;
18
21
import io .modelcontextprotocol .spec .McpSchema ;
19
22
import io .modelcontextprotocol .spec .McpServerSession ;
@@ -99,6 +102,8 @@ public class HttpServletSseServerTransportProvider extends HttpServlet implement
99
102
/** Map of active client sessions, keyed by session ID */
100
103
private final Map <String , McpServerSession > sessions = new ConcurrentHashMap <>();
101
104
105
+ private McpTransportContextExtractor <HttpServletRequest > contextExtractor ;
106
+
102
107
/** Flag indicating if the transport is in the process of shutting down */
103
108
private final AtomicBoolean isClosing = new AtomicBoolean (false );
104
109
@@ -141,7 +146,7 @@ public HttpServletSseServerTransportProvider(ObjectMapper objectMapper, String m
141
146
@ Deprecated
142
147
public HttpServletSseServerTransportProvider (ObjectMapper objectMapper , String baseUrl , String messageEndpoint ,
143
148
String sseEndpoint ) {
144
- this (objectMapper , baseUrl , messageEndpoint , sseEndpoint , null );
149
+ this (objectMapper , baseUrl , messageEndpoint , sseEndpoint , null , null );
145
150
}
146
151
147
152
/**
@@ -160,11 +165,33 @@ public HttpServletSseServerTransportProvider(ObjectMapper objectMapper, String b
160
165
@ Deprecated
161
166
public HttpServletSseServerTransportProvider (ObjectMapper objectMapper , String baseUrl , String messageEndpoint ,
162
167
String sseEndpoint , Duration keepAliveInterval ) {
168
+ this (objectMapper , baseUrl , messageEndpoint , sseEndpoint , keepAliveInterval , null );
169
+ }
170
+
171
+ /**
172
+ * Creates a new HttpServletSseServerTransportProvider instance with a custom SSE
173
+ * endpoint.
174
+ * @param objectMapper The JSON object mapper to use for message
175
+ * serialization/deserialization
176
+ * @param baseUrl The base URL for the server transport
177
+ * @param messageEndpoint The endpoint path where clients will send their messages
178
+ * @param sseEndpoint The endpoint path where clients will establish SSE connections
179
+ * @param keepAliveInterval The interval for keep-alive pings, or null to disable
180
+ * @param contextExtractor The extractor for transport context from the request.
181
+ * keep-alive functionality
182
+ * @deprecated Use the builder {@link #builder()} instead for better configuration
183
+ * options.
184
+ */
185
+ @ Deprecated
186
+ public HttpServletSseServerTransportProvider (ObjectMapper objectMapper , String baseUrl , String messageEndpoint ,
187
+ String sseEndpoint , Duration keepAliveInterval ,
188
+ McpTransportContextExtractor <HttpServletRequest > contextExtractor ) {
163
189
164
190
this .objectMapper = objectMapper ;
165
191
this .baseUrl = baseUrl ;
166
192
this .messageEndpoint = messageEndpoint ;
167
193
this .sseEndpoint = sseEndpoint ;
194
+ this .contextExtractor = contextExtractor ;
168
195
169
196
if (keepAliveInterval != null ) {
170
197
@@ -336,10 +363,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
336
363
body .append (line );
337
364
}
338
365
366
+ final McpTransportContext transportContext = contextExtractor .extract (request ,
367
+ new DefaultMcpTransportContext ());
339
368
McpSchema .JSONRPCMessage message = McpSchema .deserializeJsonRpcMessage (objectMapper , body .toString ());
340
369
341
370
// Process the message through the session's handle method
342
- session .handle (message ).block (); // Block for Servlet compatibility
371
+ session .handle (message ).contextWrite (ctx -> ctx .put (McpTransportContext .KEY , transportContext )).block (); // Block
372
+ // for
373
+ // Servlet
374
+ // compatibility
343
375
344
376
response .setStatus (HttpServletResponse .SC_OK );
345
377
}
@@ -531,6 +563,8 @@ public static class Builder {
531
563
532
564
private String sseEndpoint = DEFAULT_SSE_ENDPOINT ;
533
565
566
+ private McpTransportContextExtractor <HttpServletRequest > contextExtractor = (serverRequest , context ) -> context ;
567
+
534
568
private Duration keepAliveInterval ;
535
569
536
570
/**
@@ -580,6 +614,19 @@ public Builder sseEndpoint(String sseEndpoint) {
580
614
return this ;
581
615
}
582
616
617
+ /**
618
+ * Sets the context extractor for extracting transport context from the request.
619
+ * @param contextExtractor The context extractor to use. Must not be null.
620
+ * @return this builder instance
621
+ * @throws IllegalArgumentException if contextExtractor is null
622
+ */
623
+ public HttpServletSseServerTransportProvider .Builder contextExtractor (
624
+ McpTransportContextExtractor <HttpServletRequest > contextExtractor ) {
625
+ Assert .notNull (contextExtractor , "Context extractor must not be null" );
626
+ this .contextExtractor = contextExtractor ;
627
+ return this ;
628
+ }
629
+
583
630
/**
584
631
* Sets the interval for keep-alive pings.
585
632
* <p>
@@ -606,7 +653,7 @@ public HttpServletSseServerTransportProvider build() {
606
653
throw new IllegalStateException ("MessageEndpoint must be set" );
607
654
}
608
655
return new HttpServletSseServerTransportProvider (objectMapper , baseUrl , messageEndpoint , sseEndpoint ,
609
- keepAliveInterval );
656
+ keepAliveInterval , contextExtractor );
610
657
}
611
658
612
659
}
0 commit comments