Skip to content

Commit a429ab3

Browse files
fix: Add missing session cleanup to the StreamableHTTPServer DELETE handler (#667)
* fix: Add missing session cleanup to the StreamableHTTPServer DELETE handler * Fix merge typo --------- Co-authored-by: Connor Zanin <[email protected]>
1 parent 4c4253a commit a429ab3

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

server/streamable_http.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ func (s *StreamableHTTPServer) handleDelete(w http.ResponseWriter, r *http.Reque
698698
s.sessionLogLevels.delete(sessionID)
699699
// remove current session's requstID information
700700
s.sessionRequestIDs.Delete(sessionID)
701+
s.activeSessions.Delete(sessionID)
702+
s.server.UnregisterSession(r.Context(), sessionID)
701703

702704
w.WriteHeader(http.StatusOK)
703705
}

server/streamable_http_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"time"
1616

1717
"github.com/mark3labs/mcp-go/mcp"
18+
"github.com/stretchr/testify/assert"
19+
"github.com/stretchr/testify/require"
1820
)
1921

2022
type jsonRPCResponse struct {
@@ -2485,6 +2487,45 @@ func TestStreamableHTTP_GET_NonFlusherReturns405(t *testing.T) {
24852487
})
24862488
}
24872489

2490+
func TestStreamableHTTP_Delete(t *testing.T) {
2491+
var hookCalled bool
2492+
var hookSession ClientSession
2493+
2494+
hooks := &Hooks{}
2495+
hooks.AddOnUnregisterSession(func(ctx context.Context, session ClientSession) {
2496+
hookCalled = true
2497+
hookSession = session
2498+
})
2499+
2500+
mcpServer := NewMCPServer("test-mcp-server", "1.0", WithHooks(hooks))
2501+
sseServer := NewStreamableHTTPServer(mcpServer, WithStateful(true))
2502+
testServer := httptest.NewServer(sseServer)
2503+
defer testServer.Close()
2504+
2505+
resp, err := postJSON(testServer.URL, initRequest)
2506+
require.NoError(t, err)
2507+
resp.Body.Close()
2508+
sessionID := resp.Header.Get(HeaderKeySessionID)
2509+
2510+
req, _ := http.NewRequest(http.MethodDelete, testServer.URL, nil)
2511+
req.Header.Set(HeaderKeySessionID, sessionID)
2512+
2513+
resp, err = testServer.Client().Do(req)
2514+
require.NoError(t, err)
2515+
resp.Body.Close()
2516+
2517+
require.Equal(t, http.StatusOK, resp.StatusCode)
2518+
2519+
_, activeSessionExists := sseServer.activeSessions.Load(sessionID)
2520+
assert.False(t, activeSessionExists)
2521+
2522+
_, serverSessionExists := mcpServer.sessions.Load(sessionID)
2523+
assert.False(t, serverSessionExists)
2524+
2525+
assert.True(t, hookCalled)
2526+
assert.Equal(t, sessionID, hookSession.SessionID())
2527+
}
2528+
24882529
func TestStreamableHTTP_DrainNotifications(t *testing.T) {
24892530
t.Run("drain pending notifications after response is computed", func(t *testing.T) {
24902531
mcpServer := NewMCPServer("test-mcp-server", "1.0")

0 commit comments

Comments
 (0)