Skip to content

Commit 39e1423

Browse files
committed
feat(SSEServer): add WithAppendQueryToMessageEndpoint()
configures the SSE server to append the original request's RawQuery to message endpoint
1 parent b8dc82d commit 39e1423

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

server/sse.go

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,20 @@ var _ ClientSession = (*sseSession)(nil)
5353
// SSEServer implements a Server-Sent Events (SSE) based MCP server.
5454
// It provides real-time communication capabilities over HTTP using the SSE protocol.
5555
type SSEServer struct {
56-
server *MCPServer
57-
baseURL string
58-
basePath string
59-
useFullURLForMessageEndpoint bool
60-
messageEndpoint string
61-
sseEndpoint string
62-
sessions sync.Map
63-
srv *http.Server
64-
contextFunc SSEContextFunc
56+
server *MCPServer
57+
baseURL string
58+
basePath string
59+
useFullURLForMessageEndpoint bool
60+
messageEndpoint string
61+
sseEndpoint string
62+
sessions sync.Map
63+
srv *http.Server
64+
contextFunc SSEContextFunc
6565

6666
keepAlive bool
6767
keepAliveInterval time.Duration
68+
69+
appendQueryToMessageEndpoint bool
6870
}
6971

7072
// SSEOption defines a function type for configuring SSEServer
@@ -111,6 +113,17 @@ func WithMessageEndpoint(endpoint string) SSEOption {
111113
}
112114
}
113115

116+
// WithAppendQueryToMessageEndpoint configures the SSE server to append the original request's
117+
// query parameters to the message endpoint URL that is sent to clients during the SSE connection
118+
// initialization. This is useful when you need to preserve query parameters from the initial
119+
// SSE connection request and carry them over to subsequent message requests, maintaining
120+
// context or authentication details across the communication channel.
121+
func WithAppendQueryToMessageEndpoint() SSEOption {
122+
return func(s *SSEServer) {
123+
s.appendQueryToMessageEndpoint = true
124+
}
125+
}
126+
114127
// WithUseFullURLForMessageEndpoint controls whether the SSE server returns a complete URL (including baseURL)
115128
// or just the path portion for the message endpoint. Set to false when clients will concatenate
116129
// the baseURL themselves to avoid malformed URLs like "http://localhost/mcphttp://localhost/mcp/message".
@@ -158,12 +171,12 @@ func WithSSEContextFunc(fn SSEContextFunc) SSEOption {
158171
// NewSSEServer creates a new SSE server instance with the given MCP server and options.
159172
func NewSSEServer(server *MCPServer, opts ...SSEOption) *SSEServer {
160173
s := &SSEServer{
161-
server: server,
162-
sseEndpoint: "/sse",
163-
messageEndpoint: "/message",
164-
useFullURLForMessageEndpoint: true,
165-
keepAlive: false,
166-
keepAliveInterval: 10 * time.Second,
174+
server: server,
175+
sseEndpoint: "/sse",
176+
messageEndpoint: "/message",
177+
useFullURLForMessageEndpoint: true,
178+
keepAlive: false,
179+
keepAliveInterval: 10 * time.Second,
167180
}
168181

169182
// Apply all options
@@ -293,9 +306,12 @@ func (s *SSEServer) handleSSE(w http.ResponseWriter, r *http.Request) {
293306
}()
294307
}
295308

296-
297309
// Send the initial endpoint event
298-
fmt.Fprintf(w, "event: endpoint\ndata: %s\r\n\r\n", s.GetMessageEndpointForClient(sessionID))
310+
endpoint := s.GetMessageEndpointForClient(sessionID)
311+
if s.appendQueryToMessageEndpoint && len(r.URL.RawQuery) > 0 {
312+
endpoint += "&" + r.URL.RawQuery
313+
}
314+
fmt.Fprintf(w, "event: endpoint\ndata: %s\r\n\r\n", endpoint)
299315
flusher.Flush()
300316

301317
// Main event loop - this runs in the HTTP handler goroutine

0 commit comments

Comments
 (0)