From c5a36628984fa214321b191872091df71eb803ff Mon Sep 17 00:00:00 2001 From: gyeo009 Date: Fri, 13 Feb 2026 21:47:07 +0900 Subject: [PATCH] Deprecate Builder.customizeRequest() in HttpClientSseClientTransport and HttpClientStreamableHttpTransport customizeRequest() executes its consumer once at build time, freezing headers into the shared requestBuilder. This silently breaks OAuth token refresh scenarios where the Authorization header needs to be updated after the transport is built. Add @Deprecated and update Javadoc to clarify the build-time-only semantics and guide users toward httpRequestCustomizer() or asyncHttpRequestCustomizer() which run on every request. Closes #788 --- .../transport/HttpClientSseClientTransport.java | 16 +++++++++++++++- .../HttpClientStreamableHttpTransport.java | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java index b9ed2711d..28f2973e4 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java @@ -254,10 +254,24 @@ public Builder requestBuilder(HttpRequest.Builder requestBuilder) { } /** - * Customizes the HTTP client builder. + * Applies the given consumer to the shared {@link HttpRequest.Builder} once, + * at build time. Any headers set here (e.g., {@code Authorization}) are + * frozen into the template and copied to every subsequent request via + * {@code requestBuilder.copy()}. They cannot be updated after the + * transport is built. + *

+ * For dynamic, per-request customization (e.g., OAuth token refresh), use + * {@link #httpRequestCustomizer(McpSyncHttpClientRequestCustomizer)} or + * {@link #asyncHttpRequestCustomizer(McpAsyncHttpClientRequestCustomizer)} + * instead. * @param requestCustomizer the consumer to customize the HTTP request builder * @return this builder + * @deprecated Use + * {@link #httpRequestCustomizer(McpSyncHttpClientRequestCustomizer)} or + * {@link #asyncHttpRequestCustomizer(McpAsyncHttpClientRequestCustomizer)} which + * run on every request and support dynamic headers. */ + @Deprecated public Builder customizeRequest(final Consumer requestCustomizer) { Assert.notNull(requestCustomizer, "requestCustomizer must not be null"); requestCustomizer.accept(requestBuilder); diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java index 00b80f1d5..88daedba0 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java @@ -707,10 +707,24 @@ public Builder requestBuilder(HttpRequest.Builder requestBuilder) { } /** - * Customizes the HTTP client builder. + * Applies the given consumer to the shared {@link HttpRequest.Builder} once, + * at build time. Any headers set here (e.g., {@code Authorization}) are + * frozen into the template and copied to every subsequent request via + * {@code requestBuilder.copy()}. They cannot be updated after the + * transport is built. + *

+ * For dynamic, per-request customization (e.g., OAuth token refresh), use + * {@link #httpRequestCustomizer(McpSyncHttpClientRequestCustomizer)} or + * {@link #asyncHttpRequestCustomizer(McpAsyncHttpClientRequestCustomizer)} + * instead. * @param requestCustomizer the consumer to customize the HTTP request builder * @return this builder + * @deprecated Use + * {@link #httpRequestCustomizer(McpSyncHttpClientRequestCustomizer)} or + * {@link #asyncHttpRequestCustomizer(McpAsyncHttpClientRequestCustomizer)} which + * run on every request and support dynamic headers. */ + @Deprecated public Builder customizeRequest(final Consumer requestCustomizer) { Assert.notNull(requestCustomizer, "requestCustomizer must not be null"); requestCustomizer.accept(requestBuilder);