FastMCP HTTP/SSE transport does not forward incoming request headers (e.g. Authorization) to the Polaris backend
- Dominant language
- TypeScript
- Stars
- 33
- Forks
- 46
- Avg merge
- 1d 4m
- Merged PRs (30d)
- 2
Description
When the MCP server is running in `http` or `sse` transport mode, incoming HTTP headers from the client request are **never extracted or forwarded** to the backend Polaris REST API. This makes it impossible to deploy the MCP server behind an authenticating reverse proxy (e.g. OAuth2 Proxy) and have the proxy-injected `Authorization` header passed through to Polaris.
### Use Case Scenario
```
Client → OAuth2 Proxy → Polaris MCP Server (http transport) → Polaris Server (external IDP)
```
1. The MCP server is deployed **without its own auth** (`POLARIS_CLIENT_ID` / `POLARIS_CLIENT_SECRET` are not set; the Polaris server has client credentials disabled).
2. An authenticating reverse proxy (e.g. [OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/)) sits in front of the MCP server.
3. The proxy handles the OAuth2/OIDC redirect flow with the external Identity Provider and injects an `Authorization: Bearer ` header into every request forwarded to the MCP server.
4. The MCP server should forward that `Authorization` header to the backend Polaris server, which validates the token against the same external IDP.
**This flow currently does not work** because the MCP server never reads headers from the incoming HTTP request.
### Current Behavior
The auth resolution in `server.py` (`_resolve_authorization_provider`) only considers:
1. **Static tokens** from env vars (`POLARIS_API_TOKEN`, `POLARIS_BEARER_TOKEN`, `POLARIS_TOKEN`)
2. **OAuth2 Client Credentials** from env vars (`POLARIS_CLIENT_ID` + `POLARIS_CLIENT_SECRET`)
3. **Realm-specific credentials** from `POLARIS_REALM_*` env vars
If none of these are set, the `AuthorizationProvider` resolves to `none()` — no `Authorization` header is added to outbound requests, and the incoming HTTP-layer `Authorization` header is silently dropped.
The `headers` parameter on each tool function (e.g. `polaris_iceberg_table`) only accepts headers passed **as MCP tool arguments by the LLM client**, not headers from the HTTP transport layer.
---
We should be able to use the `get_http_headers` from fast mcp in `RestTool::call()`.
Contributor guide
No contributing guide indexed for this repository
Research direction
Trace the HTTP and SSE request paths in server.py and the RestTool::call() entry point, starting with FastMCP's get_http_headers behavior. Check how _resolve_authorization_provider currently selects credentials and how outbound Polaris REST requests receive headers. Done means an incoming Authorization header is preserved for backend calls in HTTP/SSE mode without breaking the existing token and client-credential paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, typescript
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100