createHTTPClient creates an HTTP client with custom headers and OAuth support. Header values may contain ${headers.NAME} placeholders that are resolved at request time from upstream headers stored in the request context. The oauthTransport is returned alongside the client so callers can inspect the
()
| 200 | // a no-op when OTel is disabled at runtime, so the laptop-mode default |
| 201 | // stays unchanged. |
| 202 | func (c *remoteMCPClient) createHTTPClient() (*http.Client, *oauthTransport, error) { |
| 203 | base := c.headerTransport() |
| 204 | |
| 205 | // Then wrap with OAuth support |
| 206 | oauthT := &oauthTransport{ |
| 207 | base: base, |
| 208 | client: c, |
| 209 | tokenStore: c.tokenStore, |
| 210 | baseURL: c.url, |
| 211 | managed: c.managed, |
| 212 | unmanagedOAuthRedirectURI: c.unmanagedOAuthRedirectURI, |
| 213 | oauthConfig: c.oauthConfig, |
| 214 | oauthHTTPClient: oauthHTTPClientWithHeaders(c.url, c.headers, c.allowPrivateIPs), |
| 215 | } |
| 216 | |
| 217 | // Persist cookies across requests |
| 218 | // So sticky sessions work if implemented by the server (e.g. in a multiple replica setup) |
| 219 | jar, err := cookiejar.New(nil) |
| 220 | if err != nil { |
| 221 | return nil, nil, fmt.Errorf("creating cookie jar: %w", err) |
| 222 | } |
| 223 | return &http.Client{Transport: httpclient.WrapWithOTel(oauthT), Jar: jar}, oauthT, nil |
| 224 | } |
| 225 | |
| 226 | func (c *remoteMCPClient) headerTransport() http.RoundTripper { |
| 227 | if len(c.headers) > 0 { |