Problem
MCP::Client::OAuth::Flow already accepts http_client_factory:, and the comment on default_http_client explicitly anticipates a caller passing one. But MCP::Client::HTTP builds the flow itself, in both places, with no way to supply it (v1.5.1):
flow = MCP::Client::OAuth::Flow.new(provider: @oauth) # http.rb:850, run_oauth_flow!
flow = MCP::Client::OAuth::Flow.new(provider: @oauth) # http.rb:870, run_step_up_flow!
So a consumer using oauth: gets a Faraday connection for discovery and the token exchange that they cannot instrument. #303 added the block that customizes the transport's connection; the OAuth flow's connection has no equivalent.
Why it matters
We record every outbound request — method, URL, status, headers, body — into a per-turn trace used to debug production incidents, and our own token service puts that middleware on its connection, so token requests appear in traces today. That recording is what diagnosed #554: the response headers in the trace identified the failure.
Adopting oauth: would silently drop discovery and token requests from those traces. For us that's a blocker on using the SDK's OAuth at all — which is a shame, because #555 otherwise removes the last reason we couldn't.
Proposal
Let MCP::Client::HTTP.new take the factory and hand it to both call sites:
MCP::Client::HTTP.new(
url: ...,
oauth: provider,
oauth_http_client_factory: -> { Faraday.new { |f| f.use MyApp::HttpRecorder } },
)
No new concept — Flow already supports this. It's only unreachable from the one class that builds the flow.
The constraints in default_http_client still apply, and a caller supplying a factory takes them on: no redirect-following middleware, and leave Accept-Encoding unset so BoundedBody's cap stays on decoded bytes. Worth restating in the keyword's docs.
If you'd rather not add a keyword, passing the existing customizer block through would also work for us, though it's less precise — the token endpoint is a different origin from the MCP server, so reusing the transport's block there could surprise people.
Happy to open a PR.
Problem
MCP::Client::OAuth::Flowalready acceptshttp_client_factory:, and the comment ondefault_http_clientexplicitly anticipates a caller passing one. ButMCP::Client::HTTPbuilds the flow itself, in both places, with no way to supply it (v1.5.1):So a consumer using
oauth:gets a Faraday connection for discovery and the token exchange that they cannot instrument. #303 added the block that customizes the transport's connection; the OAuth flow's connection has no equivalent.Why it matters
We record every outbound request — method, URL, status, headers, body — into a per-turn trace used to debug production incidents, and our own token service puts that middleware on its connection, so token requests appear in traces today. That recording is what diagnosed #554: the response headers in the trace identified the failure.
Adopting
oauth:would silently drop discovery and token requests from those traces. For us that's a blocker on using the SDK's OAuth at all — which is a shame, because #555 otherwise removes the last reason we couldn't.Proposal
Let
MCP::Client::HTTP.newtake the factory and hand it to both call sites:No new concept —
Flowalready supports this. It's only unreachable from the one class that builds the flow.The constraints in
default_http_clientstill apply, and a caller supplying a factory takes them on: no redirect-following middleware, and leaveAccept-Encodingunset soBoundedBody's cap stays on decoded bytes. Worth restating in the keyword's docs.If you'd rather not add a keyword, passing the existing customizer block through would also work for us, though it's less precise — the token endpoint is a different origin from the MCP server, so reusing the transport's block there could surprise people.
Happy to open a PR.