From 80abbe61715b278958f67a61423f60e5d12f9208 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Mon, 27 Oct 2025 14:00:58 -0400 Subject: [PATCH] docs: document support for resumability and redelivery (#606) Add missing documentation on resumability and redelivery in the streamable transport. Indirectly, also update stale transcluded examples. Example changes weren't causing CI failure as we only trigger the docs check on changes to the raw docs. --- docs/client.md | 4 +++- docs/protocol.md | 14 ++++++++++++++ docs/troubleshooting.md | 4 ++-- internal/docs/protocol.src.md | 13 +++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/client.md b/docs/client.md index 8fc7544..6ce20c9 100644 --- a/docs/client.md +++ b/docs/client.md @@ -53,9 +53,11 @@ func Example_roots() { // Connect the server and client... t1, t2 := mcp.NewInMemoryTransports() - if _, err := s.Connect(ctx, t1, nil); err != nil { + serverSession, err := s.Connect(ctx, t1, nil) + if err != nil { log.Fatal(err) } + defer serverSession.Close() clientSession, err := c.Connect(ctx, t2, nil) if err != nil { diff --git a/docs/protocol.md b/docs/protocol.md index 3a031af..6d22c4b 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -148,6 +148,7 @@ To create a streamable MCP server, you create a `StreamableHTTPHandler` and pass it an `mcp.Server`: ```go +// TODO: Until we have a way to clean up abandoned sessions, this test will leak goroutines (see #499) func ExampleStreamableHTTPHandler() { // Create a new streamable handler, using the same MCP server for every request. // @@ -185,6 +186,19 @@ client, err := mcp.Connect(ctx, transport, &mcp.ClientOptions{...}) The `StreamableClientTransport` handles the HTTP requests and communicates with the server using the streamable transport protocol. +#### Resumability and Redelivery + +By default, the streamable server does not support [resumability or +redelivery](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#resumability-and-redelivery) +of messages, because doing so requires either a persistent storage solution or +unbounded memory usage (see also +[#580](https://github.com/modelcontextprotocol/go-sdk/issues/580)). + +To enable resumability, set `StreamableHTTPOptions.EventStore` to a non-nil +value. The SDK provides a `MemoryEventStore` for testing or simple use cases; +for production use it is generally advisable to use a more sophisticated +implementation. + #### Stateless Mode The streamable server supports a _stateless mode_ by setting diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 38410ad..c22a279 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -33,7 +33,7 @@ func ExampleLoggingTransport() { if err != nil { log.Fatal(err) } - defer serverSession.Wait() + defer serverSession.Close() client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) var b bytes.Buffer @@ -71,7 +71,7 @@ func ExampleStreamableHTTPHandler_middleware() { server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil) handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server { return server - }, nil) + }, &mcp.StreamableHTTPOptions{Stateless: true}) loggingHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { // Example debugging; you could also capture the response. body, err := io.ReadAll(req.Body) diff --git a/internal/docs/protocol.src.md b/internal/docs/protocol.src.md index e85374a..b0874cc 100644 --- a/internal/docs/protocol.src.md +++ b/internal/docs/protocol.src.md @@ -112,6 +112,19 @@ client, err := mcp.Connect(ctx, transport, &mcp.ClientOptions{...}) The `StreamableClientTransport` handles the HTTP requests and communicates with the server using the streamable transport protocol. +#### Resumability and Redelivery + +By default, the streamable server does not support [resumability or +redelivery](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#resumability-and-redelivery) +of messages, because doing so requires either a persistent storage solution or +unbounded memory usage (see also +[#580](https://github.com/modelcontextprotocol/go-sdk/issues/580)). + +To enable resumability, set `StreamableHTTPOptions.EventStore` to a non-nil +value. The SDK provides a `MemoryEventStore` for testing or simple use cases; +for production use it is generally advisable to use a more sophisticated +implementation. + #### Stateless Mode The streamable server supports a _stateless mode_ by setting