Skip to content

Streamable HTTP clients can get stuck connecting #633

@richard-rance

Description

@richard-rance

Describe the bug
When connecting to some MCP servers that support making SSE GET requests, client.Connect gets hung up waiting for the first notification from the server. This is particularly a problem if they don't manually flush the response buffer after writing the headers.

To Reproduce
I found the problem when running the following to connect to Zapier's MCP server. I then adjusted the unit tests to reproduce it locally in https://github.com/modelcontextprotocol/go-sdk/pull/634/files#diff-bc2db7f8b168cfd247ed95d1ac34698f70d9ad808c40102361253f4beda91058R110-R121

func main() {
	ctx := context.Background()

	client := mcp.NewClient(&mcp.Implementation{}, &mcp.ClientOptions{})
	logging.Infof(ctx, "Initializing...")

	cs, err := client.Connect(ctx,
		&mcp.StreamableClientTransport{
			Endpoint: "https://mcp.zapier.com/api/mcp/s/my-streamable-server-key-here/mcp",
		},
		&mcp.ClientSessionOptions{})
	if err != nil {
		logging.Errorf(ctx, "Failed to connect to MCP: %v", err)
		return
	}
	defer cs.Close()

	logging.Infof(ctx, "This doesn't run until the GET request times out 5 times")
}

Expected behavior
I expect creating a client connection to complete in under 1 second. (I tested this same server URL in other MCP clients.)
If the MCP server has configured their server correctly they will be able to send the client notifications.
If they haven't the client should still be able to use the server's tools, prompts and resources.

Additional context
This works as expected using the SDK version prior to #604 / #583. That PR changed initialization of the standalone SSE connection to be synchronous. That allows some server errors from starting the stand alone SSE connection be returned as part of client.Connect.

As a client developer I have no control over the server's behaviour. The server misbehaving only affects the server's ability to send notifications. If the POST initialization request is successful but the GET SSE stream is not it is probably because the server does not send messages so didn't test it. I don't think that creating the connection needs to wait for the stand alone SSE connection.

In my particular use case I am building a stateless client so would like to disable creating the standalone SSE connections entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions