@@ -165,48 +165,66 @@ func (s *InMemoryEventStore) ReplayEventsAfter(lastEventID string, send func(eve
165165 return nil
166166}
167167
168- // StreamableHTTPOption defines a function type for configuring StreamableHTTPServer
169- type StreamableHTTPOption func (* StreamableHTTPServer )
170-
171168// WithSessionIDGenerator sets a custom session ID generator
172169func WithSessionIDGenerator (generator func () string ) StreamableHTTPOption {
173- return func (s * StreamableHTTPServer ) {
174- s .sessionIDGenerator = generator
175- }
170+ return streamableHTTPOption (func (s * StreamableHTTPServer ) {
171+ // Store the generator for later use
172+ generatorFunc = generator
173+ })
176174}
177175
176+ // Generator function stored for later use
177+ var generatorFunc func () string
178+
178179// WithStatelessMode enables stateless mode (no sessions)
179180func WithStatelessMode (enable bool ) StreamableHTTPOption {
180- return func (s * StreamableHTTPServer ) {
181- s .statelessMode = enable
182- }
181+ return streamableHTTPOption (func (s * StreamableHTTPServer ) {
182+ // Store the mode for later use
183+ statelessModeEnabled = enable
184+ })
183185}
184186
187+ // Stateless mode flag stored for later use
188+ var statelessModeEnabled bool
189+
185190// WithEnableJSONResponse enables direct JSON responses instead of SSE streams
186191func WithEnableJSONResponse (enable bool ) StreamableHTTPOption {
187- return func (s * StreamableHTTPServer ) {
188- s .enableJSONResponse = enable
189- }
192+ return streamableHTTPOption (func (s * StreamableHTTPServer ) {
193+ // Store the setting for later use
194+ enableJSONResponseFlag = enable
195+ })
190196}
191197
198+ // JSON response flag stored for later use
199+ var enableJSONResponseFlag bool
200+
192201// WithEventStore sets a custom event store for resumability
193202func WithEventStore (store EventStore ) StreamableHTTPOption {
194- return func (s * StreamableHTTPServer ) {
195- s .eventStore = store
196- }
203+ return streamableHTTPOption (func (s * StreamableHTTPServer ) {
204+ // Store the event store for later use
205+ customEventStore = store
206+ })
197207}
198208
209+ // Event store stored for later use
210+ var customEventStore EventStore
211+
199212// WithStreamableHTTPContextFunc sets a function that will be called to customize the context
200213// to the server using the incoming request.
201214func WithStreamableHTTPContextFunc (fn SSEContextFunc ) StreamableHTTPOption {
202- return func (s * StreamableHTTPServer ) {
203- s .contextFunc = fn
204- }
215+ return streamableHTTPOption (func (s * StreamableHTTPServer ) {
216+ // Store the context function for later use
217+ contextFunction = fn
218+ })
205219}
206220
207- // StreamableHTTPServer implements a Streamable HTTP based MCP server.
221+ // Context function stored for later use
222+ var contextFunction SSEContextFunc
223+
224+ // realStreamableHTTPServer is the concrete implementation of StreamableHTTPServer.
208225// It provides HTTP transport capabilities following the MCP Streamable HTTP specification.
209226type StreamableHTTPServer struct {
227+ // Implement the httpTransportConfigurable interface
210228 server * MCPServer
211229 baseURL string
212230 basePath string
@@ -224,6 +242,7 @@ type StreamableHTTPServer struct {
224242
225243// NewStreamableHTTPServer creates a new Streamable HTTP server instance with the given MCP server and options.
226244func NewStreamableHTTPServer (server * MCPServer , opts ... StreamableHTTPOption ) * StreamableHTTPServer {
245+ // Create our implementation
227246 s := & StreamableHTTPServer {
228247 server : server ,
229248 endpoint : "/mcp" ,
@@ -233,14 +252,28 @@ func NewStreamableHTTPServer(server *MCPServer, opts ...StreamableHTTPOption) *S
233252
234253 // Apply all options
235254 for _ , opt := range opts {
236- opt (s )
255+ opt .applyToStreamableHTTP (s )
256+ }
257+
258+ // Apply the stored option values to our implementation
259+ if generatorFunc != nil {
260+ s .sessionIDGenerator = generatorFunc
261+ }
262+ s .statelessMode = statelessModeEnabled
263+ s .enableJSONResponse = enableJSONResponseFlag
264+ if customEventStore != nil {
265+ s .eventStore = customEventStore
266+ }
267+ if contextFunction != nil {
268+ s .contextFunc = contextFunction
237269 }
238270
239271 // If no event store is provided, create an in-memory one
240272 if s .eventStore == nil {
241273 s .eventStore = NewInMemoryEventStore ()
242274 }
243275
276+ // Return the stub
244277 return s
245278}
246279
@@ -455,6 +488,7 @@ func (s *StreamableHTTPServer) handleRequest(w http.ResponseWriter, r *http.Requ
455488 }
456489 }
457490}
491+
458492func (s * StreamableHTTPServer ) handleSSEResponse (w http.ResponseWriter , r * http.Request , ctx context.Context , initialResponse mcp.JSONRPCMessage , session SessionWithTools ) {
459493 // Set SSE headers
460494 w .Header ().Set ("Content-Type" , "text/event-stream" )
@@ -780,9 +814,15 @@ func splitAndTrim(s string, sep rune) []string {
780814
781815// NewTestStreamableHTTPServer creates a test server for testing purposes
782816func NewTestStreamableHTTPServer (server * MCPServer , opts ... StreamableHTTPOption ) * httptest.Server {
783- streamableServer := NewStreamableHTTPServer (server , opts ... )
784- testServer := httptest .NewServer (streamableServer )
785- streamableServer .baseURL = testServer .URL
817+ // Create the server
818+ base := NewStreamableHTTPServer (server , opts ... )
819+
820+ // Create the test server
821+ testServer := httptest .NewServer (base )
822+
823+ // Set the base URL
824+ base .baseURL = testServer .URL
825+
786826 return testServer
787827}
788828
0 commit comments