Skip to content

Allow custom fetch in SSEClientTransport and StreamableHTTPClientTransport #721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 3, 2025

Conversation

cliffhall
Copy link
Contributor

@cliffhall cliffhall commented Jul 1, 2025

Summary of Changes

This pull request significantly enhances the flexibility of the SSEClientTransport and StreamableHTTPClientTransport classes by enabling the injection of a custom fetch implementation. This change empowers users to exert fine-grained control over network requests, facilitating advanced use cases such as custom authentication flows or specialized request handling, thereby improving the adaptability of the transport layer.

Highlights

  • Custom Fetch Support: Added a fetch option to SSEClientTransport and StreamableHTTPClientTransport constructors, allowing consumers to provide their own custom fetch implementation for network requests.
  • Comprehensive Integration: The custom fetch implementation is now utilized for all internal network operations within these transports, including initial SSE connections (GET), sending messages (POST), and session termination (DELETE).
  • Type Standardization: Introduced a shared FetchLike type definition in src/shared/transport.ts to ensure consistent typing for custom fetch functions across the codebase.
  • Enhanced Test Coverage: New test cases were added to verify the correct usage and behavior of the custom fetch implementation, specifically ensuring proper authentication header propagation for various request types.
Changelog
  • src/client/sse.test.ts
    • Added a new test case to verify that SSEClientTransport correctly utilizes a custom fetch implementation for both initial connection and subsequent POST requests, ensuring proper header propagation.
  • src/client/sse.ts
    • Imported the new FetchLike type from src/shared/transport.ts.
    • Added a fetch option to SSEClientTransportOptions and a corresponding private _fetch property.
    • Updated internal fetch calls within _startOrAuth() and send() methods to use the provided custom fetch or fall back to the global fetch.
    • Applied nullish coalescing operator (??) for fetch fallback logic as per review suggestions.
  • src/client/streamableHttp.test.ts
    • Imported the StartSSEOptions interface for improved type safety in tests.
    • Added a new test case to confirm StreamableHTTPClientTransport uses the custom fetch implementation for all its network operations, including authentication.
    • Minor formatting adjustments.
  • src/client/streamableHttp.ts
    • Imported the new FetchLike type from src/shared/transport.ts.
    • Exported the StartSSEOptions interface.
    • Added a fetch option to StreamableHTTPClientTransportOptions and a corresponding private _fetch property.
    • Modified _startOrAuthSse(), send(), and terminate() methods to use the custom fetch implementation for their respective network requests.
    • Applied nullish coalescing operator (??) for fetch fallback logic as per review suggestions.
    • Minor formatting adjustments.
  • src/shared/transport.ts
    • Defined and exported the FetchLike type, standardizing the signature for custom fetch functions across the codebase.
    • Minor formatting adjustments to comments.

Motivation and Context

Picks up on the work started in abandoned PR #296, refining the implementation, extending it to include StreamableHttp in addition to SSE, and adds tests for both.

The ultimate motivation is in the requirement by a pending PR in the Inspector project, which seeks to bridge the WWW-Authenticate header returned by an MCP server back to the Inspector client within the Inspector proxy. This makes use of the custom fetch function to capture the header.

How Has This Been Tested?

New unit tests.

Breaking Changes

Nope.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Fixes #476

cliffhall and others added 8 commits July 1, 2025 13:20
nullish coalescing operator ?? instead of the logical OR operator || to handle the case where this?._eventSourceInit?.fetch or this._fetch might be null or undefined but not falsy

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
nullish coalescing operator ?? instead of the logical OR operator || to handle the case where this?._eventSourceInit?.fetch or this._fetch might be null or undefined but not falsy

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
nullish coalescing operator ?? instead of the logical OR operator || to handle the case where this?._eventSourceInit?.fetch or this._fetch might be null or undefined but not falsy

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
nullish coalescing operator ?? instead of the logical OR operator || to handle the case where this?._eventSourceInit?.fetch or this._fetch might be null or undefined but not falsy

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
nullish coalescing operator ?? instead of the logical OR operator || to handle the case where this?._eventSourceInit?.fetch or this._fetch might be null or undefined but not falsy

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
  - More specific expectations in test "uses custom fetch implementation from options"

* In sse.ts
  - Import FetchLike from transport.ts

* In steramableHttp.ts
  - Import FetchLike from transport.ts
  - Export StartSSEOptions interface for testing

* In streamableHttp.test.ts
  - import StartSSEOptions from streamableHttp.ts
  - use StartSSEOptions instead of any in test "uses custom fetch implementation"

* In transport.ts
  - Add FetchLike function type
…ablehttp.ts-and-sse.ts

Add custom fetch support to transports
@cliffhall
Copy link
Contributor Author

@ihrpr ihrpr added this to the HPR milestone Jul 2, 2025
Copy link
Contributor

@ihrpr ihrpr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

@ihrpr ihrpr merged commit 0b0ea5b into modelcontextprotocol:main Jul 3, 2025
2 checks passed
@cliffhall cliffhall deleted the allow-custom-fetch branch July 3, 2025 16:37
@cliffhall cliffhall changed the title Allow custom fetch Allow custom fetch in SSEClientTransport and StreamableHTTPClientTransport Jul 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Override client transport fetch
2 participants