MCPcopy Create free account
hub / github.com/modelcontextprotocol/go-sdk / TestStreamableServerShutdown

Function TestStreamableServerShutdown

mcp/streamable_test.go:291–364  ·  view source on GitHub ↗
(t *testing.T)

Source from the content-addressed store, hash-verified

289}
290
291func TestStreamableServerShutdown(t *testing.T) {
292 ctx := context.Background()
293
294 // This test checks that closing the streamable HTTP server actually results
295 // in client session termination, provided one of following holds:
296 // 1. The server is stateful, and therefore the hanging GET fails the connection.
297 // 2. The server is stateless, and the client uses a KeepAlive.
298 tests := []struct {
299 name string
300 stateless, keepalive bool
301 }{
302 {"stateful", false, false},
303 {"stateless with keepalive", true, true},
304 }
305
306 for _, test := range tests {
307 t.Run(test.name, func(t *testing.T) {
308 server := NewServer(testImpl, nil)
309 // Add a tool, just so we can check things are working.
310 AddTool(server, &Tool{Name: "greet"}, sayHi)
311
312 handler := NewStreamableHTTPHandler(
313 func(req *http.Request) *Server { return server },
314 &StreamableHTTPOptions{Stateless: test.stateless})
315
316 // When we shut down the server, we need to explicitly close ongoing
317 // connections. Otherwise, the hanging GET may never terminate.
318 httpServer := httptest.NewUnstartedServer(handler)
319 httpServer.Config.RegisterOnShutdown(func() {
320 for session := range server.Sessions() {
321 session.Close()
322 }
323 })
324 httpServer.Start()
325 defer httpServer.Close()
326
327 // Connect and run a tool.
328 var opts ClientOptions
329 if test.keepalive {
330 opts.KeepAlive = 50 * time.Millisecond
331 }
332 client := NewClient(testImpl, &opts)
333 clientSession, err := client.Connect(ctx, &StreamableClientTransport{
334 Endpoint: httpServer.URL,
335 MaxRetries: -1, // avoid slow tests during exponential retries
336 }, nil)
337 if err != nil {
338 t.Fatal(err)
339 }
340 defer clientSession.Close()
341
342 params := &CallToolParams{
343 Name: "greet",
344 Arguments: map[string]any{"Name": "foo"},
345 }
346 // Verify that we can call a tool.
347 if _, err := clientSession.CallTool(ctx, params); err != nil {
348 t.Fatalf("CallTool() failed: %v", err)

Callers

nothing calls this directly

Calls 13

SessionsMethod · 0.95
ConnectMethod · 0.95
NewServerFunction · 0.85
AddToolFunction · 0.85
NewStreamableHTTPHandlerFunction · 0.85
NewClientFunction · 0.85
RunMethod · 0.80
CallToolMethod · 0.80
IsMethod · 0.80
LogMethod · 0.80
CloseMethod · 0.65
StartMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…