diff --git a/docs/python-sdk/fastmcp-server-dependencies.mdx b/docs/python-sdk/fastmcp-server-dependencies.mdx
index 88a756ebc..55ab7ca19 100644
--- a/docs/python-sdk/fastmcp-server-dependencies.mdx
+++ b/docs/python-sdk/fastmcp-server-dependencies.mdx
@@ -169,7 +169,7 @@ By default, strips problematic headers like `content-length` that cause issues
if forwarded to downstream clients. If `include_all` is True, all headers are returned.
-### `get_access_token`
+### `get_access_token`
```python
get_access_token() -> AccessToken | None
@@ -188,7 +188,7 @@ token snapshot stored in Redis at task submission time.
- The access token if an authenticated user is available, None otherwise.
-### `without_injected_parameters`
+### `without_injected_parameters`
```python
without_injected_parameters(fn: Callable[..., Any]) -> Callable[..., Any]
@@ -213,7 +213,7 @@ Handles:
- Async wrapper function without injected parameters
-### `resolve_dependencies`
+### `resolve_dependencies`
```python
resolve_dependencies(fn: Callable[..., Any], arguments: dict[str, Any]) -> AsyncGenerator[dict[str, Any], None]
@@ -239,7 +239,7 @@ time, so all injection goes through the unified DI system.
which will be filtered out)
-### `CurrentContext`
+### `CurrentContext`
```python
CurrentContext() -> Context
@@ -258,7 +258,7 @@ current MCP operation (tool/resource/prompt call).
- `RuntimeError`: If no active context found (during resolution)
-### `CurrentDocket`
+### `CurrentDocket`
```python
CurrentDocket() -> Docket
@@ -278,7 +278,7 @@ automatically creates for background task scheduling.
- `ImportError`: If fastmcp[tasks] not installed
-### `CurrentWorker`
+### `CurrentWorker`
```python
CurrentWorker() -> Worker
@@ -298,7 +298,7 @@ automatically creates for background task processing.
- `ImportError`: If fastmcp[tasks] not installed
-### `CurrentFastMCP`
+### `CurrentFastMCP`
```python
CurrentFastMCP() -> FastMCP
@@ -316,7 +316,7 @@ This dependency provides access to the active FastMCP server.
- `RuntimeError`: If no server in context (during resolution)
-### `CurrentRequest`
+### `CurrentRequest`
```python
CurrentRequest() -> Request
@@ -336,7 +336,7 @@ current HTTP request. Only available when running over HTTP transports
- `RuntimeError`: If no HTTP request in context (e.g., STDIO transport)
-### `CurrentHeaders`
+### `CurrentHeaders`
```python
CurrentHeaders() -> dict[str, str]
@@ -353,7 +353,7 @@ safe to use in code that might run over any transport.
- A dependency that resolves to a dictionary of header name -> value
-### `CurrentAccessToken`
+### `CurrentAccessToken`
```python
CurrentAccessToken() -> AccessToken
@@ -372,7 +372,7 @@ authenticated request. Raises an error if no authentication is present.
- `RuntimeError`: If no authenticated user (use get_access_token() for optional)
-### `TokenClaim`
+### `TokenClaim`
```python
TokenClaim(name: str) -> str
@@ -406,7 +406,7 @@ Returned by ``get_task_context()`` when running inside a Docket worker.
Contains identifiers needed to communicate with the MCP session.
-### `ProgressLike`
+### `ProgressLike`
Protocol for progress tracking interface.
@@ -417,7 +417,7 @@ and Docket's Progress (worker context).
**Methods:**
-#### `current`
+#### `current`
```python
current(self) -> int | None
@@ -426,7 +426,7 @@ current(self) -> int | None
Current progress value.
-#### `total`
+#### `total`
```python
total(self) -> int
@@ -435,7 +435,7 @@ total(self) -> int
Total/target progress value.
-#### `message`
+#### `message`
```python
message(self) -> str | None
@@ -444,7 +444,7 @@ message(self) -> str | None
Current progress message.
-#### `set_total`
+#### `set_total`
```python
set_total(self, total: int) -> None
@@ -453,7 +453,7 @@ set_total(self, total: int) -> None
Set the total/target value for progress tracking.
-#### `increment`
+#### `increment`
```python
increment(self, amount: int = 1) -> None
@@ -462,7 +462,7 @@ increment(self, amount: int = 1) -> None
Atomically increment the current progress value.
-#### `set_message`
+#### `set_message`
```python
set_message(self, message: str | None) -> None
@@ -471,7 +471,7 @@ set_message(self, message: str | None) -> None
Update the progress status message.
-### `InMemoryProgress`
+### `InMemoryProgress`
In-memory progress tracker for immediate tool execution.
@@ -483,25 +483,25 @@ progress doesn't need to be observable across processes.
**Methods:**
-#### `current`
+#### `current`
```python
current(self) -> int | None
```
-#### `total`
+#### `total`
```python
total(self) -> int
```
-#### `message`
+#### `message`
```python
message(self) -> str | None
```
-#### `set_total`
+#### `set_total`
```python
set_total(self, total: int) -> None
@@ -510,7 +510,7 @@ set_total(self, total: int) -> None
Set the total/target value for progress tracking.
-#### `increment`
+#### `increment`
```python
increment(self, amount: int = 1) -> None
@@ -519,7 +519,7 @@ increment(self, amount: int = 1) -> None
Atomically increment the current progress value.
-#### `set_message`
+#### `set_message`
```python
set_message(self, message: str | None) -> None
@@ -528,7 +528,7 @@ set_message(self, message: str | None) -> None
Update the progress status message.
-### `Progress`
+### `Progress`
FastMCP Progress dependency that works in both server and worker contexts.
diff --git a/src/fastmcp/server/dependencies.py b/src/fastmcp/server/dependencies.py
index 15c8c3124..2770cc867 100644
--- a/src/fastmcp/server/dependencies.py
+++ b/src/fastmcp/server/dependencies.py
@@ -457,6 +457,10 @@ def get_http_headers(include_all: bool = False) -> dict[str, str]:
"keep-alive",
"expect",
"accept",
+ # Auth headers — the MCP transport's credentials must not leak
+ # to downstream APIs (e.g. OpenAPI backends) which have their
+ # own authentication configured on the httpx client.
+ "authorization",
# Proxy-related headers
"proxy-authenticate",
"proxy-authorization",
diff --git a/tests/server/http/test_http_dependencies.py b/tests/server/http/test_http_dependencies.py
index e637af269..de6c2d25c 100644
--- a/tests/server/http/test_http_dependencies.py
+++ b/tests/server/http/test_http_dependencies.py
@@ -166,3 +166,39 @@ async def test_get_http_headers_excludes_content_type(sse_server: str):
# Custom headers should be included
assert "x-custom-header" in headers
assert headers["x-custom-header"] == "should-be-included"
+
+
+async def test_get_http_headers_excludes_authorization():
+ """Test that get_http_headers() excludes the authorization header (#3260).
+
+ The MCP transport's auth credentials must not be forwarded to downstream
+ APIs (e.g. OpenAPI backends) which use their own authentication.
+ """
+ from fastmcp.server.dependencies import get_http_headers
+
+ server = FastMCP()
+
+ @server.tool
+ def check_auth_header() -> dict[str, str]:
+ """Return filtered headers to verify authorization is excluded."""
+ return get_http_headers()
+
+ async with run_server_async(server, transport="sse") as url:
+ async with Client(
+ transport=SSETransport(
+ url,
+ headers={
+ "Authorization": "Bearer mcp-client-token",
+ "X-Custom-Header": "should-be-included",
+ },
+ )
+ ) as client:
+ result = await client.call_tool("check_auth_header")
+ headers = result.data
+
+ # Authorization header must be excluded
+ assert "authorization" not in headers
+
+ # Custom headers should still be included
+ assert "x-custom-header" in headers
+ assert headers["x-custom-header"] == "should-be-included"