Skip to content

Commit 38225de

Browse files
author
Buf Generate
committed
fix java mcp message endpoint
1 parent 14151a0 commit 38225de

File tree

2 files changed

+27
-24
lines changed

2 files changed

+27
-24
lines changed

server/sse.go

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

6666
// SSEOption defines a function type for configuring SSEServer
@@ -107,10 +107,12 @@ func WithMessageEndpoint(endpoint string) SSEOption {
107107
}
108108
}
109109

110-
// WithIsCompleteMessageEndpoint sets the flag for whether the endpoint is for complete messages or not
111-
func WithIsCompleteMessageEndpoint(isCompleteMessageEndpoint bool) SSEOption {
110+
// WithUseFullURLForMessageEndpoint controls whether the SSE server returns a complete URL (including baseURL)
111+
// or just the path portion for the message endpoint. Set to false when clients will concatenate
112+
// the baseURL themselves to avoid malformed URLs like "http://localhost/mcphttp://localhost/mcp/message".
113+
func WithUseFullURLForMessageEndpoint(useFullURLForMessageEndpoint bool) SSEOption {
112114
return func(s *SSEServer) {
113-
s.isCompleteMessageEndpoint = isCompleteMessageEndpoint
115+
s.useFullURLForMessageEndpoint = useFullURLForMessageEndpoint
114116
}
115117
}
116118

@@ -139,10 +141,10 @@ func WithSSEContextFunc(fn SSEContextFunc) SSEOption {
139141
// NewSSEServer creates a new SSE server instance with the given MCP server and options.
140142
func NewSSEServer(server *MCPServer, opts ...SSEOption) *SSEServer {
141143
s := &SSEServer{
142-
server: server,
143-
sseEndpoint: "/sse",
144-
messageEndpoint: "/message",
145-
isCompleteMessageEndpoint: true,
144+
server: server,
145+
sseEndpoint: "/sse",
146+
messageEndpoint: "/message",
147+
useFullURLForMessageEndpoint: true,
146148
}
147149

148150
// Apply all options
@@ -252,9 +254,10 @@ func (s *SSEServer) handleSSE(w http.ResponseWriter, r *http.Request) {
252254
}
253255
}
254256
}()
255-
257+
// Use either just the path or the complete URL based on configuration.
258+
// This prevents issues with clients that concatenate the base URL themselves.
256259
messageEndpoint := s.messageEndpoint
257-
if s.isCompleteMessageEndpoint {
260+
if s.useFullURLForMessageEndpoint {
258261
messageEndpoint = s.CompleteMessageEndpoint()
259262
}
260263
messageEndpoint = fmt.Sprintf("%s?sessionId=%s", messageEndpoint, sessionID)

server/sse_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func TestSSEServer(t *testing.T) {
418418
cancel()
419419
})
420420

421-
t.Run("test isCompleteMessageEndpoint", func(t *testing.T) {
421+
t.Run("test useFullURLForMessageEndpoint", func(t *testing.T) {
422422
mcpServer := NewMCPServer("test", "1.0.0")
423423
sseServer := NewSSEServer(mcpServer)
424424

@@ -429,7 +429,7 @@ func TestSSEServer(t *testing.T) {
429429
defer ts.Close()
430430

431431
sseServer.baseURL = ts.URL + "/mcp"
432-
sseServer.isCompleteMessageEndpoint = false
432+
sseServer.useFullURLForMessageEndpoint = false
433433
ctx, cancel := context.WithCancel(context.Background())
434434
defer cancel()
435435

@@ -696,13 +696,13 @@ func TestSSEServer(t *testing.T) {
696696
baseURL := "http://localhost:8080/test"
697697
messageEndpoint := "/message-test"
698698
sseEndpoint := "/sse-test"
699-
isCompleteMessageEndpoint := false
699+
useFullURLForMessageEndpoint := false
700700
srv := &http.Server{}
701701
rands := []SSEOption{
702702
WithBasePath(basePath),
703703
WithBaseURL(baseURL),
704704
WithMessageEndpoint(messageEndpoint),
705-
WithIsCompleteMessageEndpoint(isCompleteMessageEndpoint),
705+
WithUseFullURLForMessageEndpoint(useFullURLForMessageEndpoint),
706706
WithSSEEndpoint(sseEndpoint),
707707
WithHTTPServer(srv),
708708
}
@@ -718,8 +718,8 @@ func TestSSEServer(t *testing.T) {
718718
if sseServer.basePath != basePath {
719719
t.Fatalf("basePath %v, got: %v", basePath, sseServer.basePath)
720720
}
721-
if sseServer.isCompleteMessageEndpoint != isCompleteMessageEndpoint {
722-
t.Fatalf("isCompleteMessageEndpoint %v, got: %v", isCompleteMessageEndpoint, sseServer.isCompleteMessageEndpoint)
721+
if sseServer.useFullURLForMessageEndpoint != useFullURLForMessageEndpoint {
722+
t.Fatalf("useFullURLForMessageEndpoint %v, got: %v", useFullURLForMessageEndpoint, sseServer.useFullURLForMessageEndpoint)
723723
}
724724

725725
if sseServer.baseURL != baseURL {

0 commit comments

Comments
 (0)