Skip to content

Proposal: Add option to disable continuous listening in StreamableClientTransport #728

@zxxf18

Description

@zxxf18

Is your feature request related to a problem? Please describe.

Yes, I'm experiencing issues with the current implementation where StreamableClientTransport always establishes a standalone SSE (Server-Sent Events) connection after initialization, which causes problems in several scenarios:

  1. Unnecessary resource usage: In many use cases, especially in scientific computing scenarios, I only need simple request-response communication. I don't need to receive server-initiated notifications, so maintaining a persistent SSE connection is wasteful.

  2. Server compatibility issues: Some third-party MCP servers don't properly handle GET requests for SSE streams. When the client automatically tries to establish the SSE connection, it fails or hangs, blocking the entire connection process. This is particularly problematic when using third-party servers that I cannot modify. (Related to issue streamable HTTP client: Don't block on standalone SSE Get #634)

  3. Lack of user control: Currently, there's no way to opt out of the standalone SSE stream. The SDK always attempts to establish it, which doesn't align with the MCP specification that states the standalone SSE stream is optional.

Describe the solution you'd like

I would like to add a DisableListening boolean field to StreamableClientTransport that allows users to control whether the client establishes the standalone SSE stream.

  • Default value should be false (maintains current behavior for backward compatibility)
  • When set to true, the client should skip establishing the standalone SSE connection
  • Add a convenience function WithDisableListening() similar to other transport options

This would give users explicit control over SSE connection establishment, similar to how github.com/mark3labs/mcp-go implements getListeningEnabled (though with inverse semantics to maintain backward compatibility).

Describe alternatives you've considered

  1. Always disable by default: This would break backward compatibility and isn't desirable.

  2. Use a pointer type: Could use *bool to distinguish between "not set" (default) and "explicitly false", but a simple bool with default false is cleaner and maintains backward compatibility.

  3. Separate transport type: Creating a new transport type would be overkill for this simple option.

  4. Environment variable or config file: Less idiomatic in Go and doesn't provide programmatic control.

The proposed solution (simple bool field with default false) is the most straightforward and maintains backward compatibility while providing the needed flexibility.

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalA proposal for an a new API or behavior. See CONTRIBUTING.md.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions