SIGN IN SIGN UP

feat: secure headers for remote MCP proxy (#90)

## Summary

- support optional upstream headers through an Azure Key Vault secret
reference
- load header values at adapter startup with workload identity
- reject raw header values in adapter metadata
- require HTTPS whenever secret-backed headers are configured
- reject redirects before credentials can reach another origin
- validate header names and visible ASCII values before connecting
upstream
- keep FastMCP debug output free of header values
- run focused proxy security tests in GitHub Actions

## Security model

Adapters submit only `MCP_PROXY_HEADERS_SECRET_URL`. The gateway stores
and returns that non-secret reference. The proxy retrieves the secret
value directly from Key Vault. Raw `MCP_PROXY_HEADERS` configuration
fails closed.

The proxy requires an `https://` upstream for secret-backed headers. It
passes a redacting transport object to FastMCP instead of an MCP config
containing credentials. Its HTTP client disables redirects even when
FastMCP asks to follow them. Unauthenticated internal HTTP proxying
remains supported.

OAuth remains preferred where an upstream supports it. The documentation
uses `Authorization: Bearer <token>` for static-token servers.

## Validation

- `python -m pytest sample-servers/mcp-proxy/tests -W error`: 26 passed
- `ruff check sample-servers/mcp-proxy/src
sample-servers/mcp-proxy/tests`
- `ruff format --check sample-servers/mcp-proxy/src
sample-servers/mcp-proxy/tests`
- `actionlint .github/workflows/main.yml`
- `dotnet build dotnet/Microsoft.McpGateway.sln --configuration Release
--no-restore`: succeeded with 0 warnings and 0 errors
- installed Python dependency set: compatible and has no known conflicts

The .NET test assemblies build locally. Execution needs the x64 .NET
host provided by the GitHub runner.

Co-authored-by: kriptoburak <kriptoburak@users.noreply.github.com>
B
Burak Bayır committed
f5eb0932adb1baf1bc47e175e5d66bf980d685b2
Parent: a998cd6
Committed by GitHub <noreply@github.com> on 8/25/2026, 10:31:51 PM