From 7c30184f3b2c605ae47a748fe3435162e8a15924 Mon Sep 17 00:00:00 2001 From: William Easton Date: Tue, 14 Apr 2026 11:14:18 -0500 Subject: [PATCH] Preserve media-type parameters in Content-Type header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use raw_content_type (with charset etc.) for the outgoing header, normalized form only for dispatch matching. 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.6 (1M context) --- src/fastmcp/utilities/openapi/director.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/fastmcp/utilities/openapi/director.py b/src/fastmcp/utilities/openapi/director.py index b0b29f0ba..5cd33153d 100644 --- a/src/fastmcp/utilities/openapi/director.py +++ b/src/fastmcp/utilities/openapi/director.py @@ -76,11 +76,13 @@ class RequestDirector: content: str | bytes | None = None # Step 5: Determine the declared content type from the OpenAPI spec. - # Strip parameters (e.g. "; charset=utf-8") for dispatch matching. + # Use the raw value for outgoing Content-Type headers (preserves + # parameters like charset), but normalize for dispatch matching. + raw_content_type: str | None = None declared_content_type: str | None = None if route.request_body and route.request_body.content_schema: - raw_ct = next(iter(route.request_body.content_schema)) - declared_content_type = raw_ct.split(";")[0].strip().lower() + raw_content_type = next(iter(route.request_body.content_schema)) + declared_content_type = raw_content_type.split(";")[0].strip().lower() # httpx requires cookie values to be strings; use OpenAPI-style # serialization (e.g. true/false for booleans, not True/False) @@ -124,7 +126,7 @@ class RequestDirector: # sets application/json. content = _json.dumps(body, allow_nan=False).encode("utf-8") headers = dict(headers) if headers else {} - headers["Content-Type"] = declared_content_type + headers["Content-Type"] = raw_content_type else: json_body = body else: