Skip to content

vMCP: add header_passthrough outgoing auth strategy to forward dynamic incoming headers to backends #3958

@juancarlosm

Description

@juancarlosm

Problem

When a client calls vMCP with dynamic request headers (e.g. x-mcp-api-key, x-mcp-auth), those headers are silently dropped. The vMCP creates a new HTTP client per backend call and only forwards pre-configured static auth headers — the original incoming headers never reach the backend.

This breaks use cases where the backend MCP server requires per-user/per-session headers for authentication (e.g. an external API that is API-key filtered and the key varies per client).

Observed: Backend receives requests with only vMCP-generated headers.
Expected: Backend receives selected incoming headers forwarded transparently.

Current workarounds

  • header_injection: Only supports static pre-configured values — unusable for dynamic per-client keys.
  • token_exchange: Requires an OAuth IdP; not applicable for simple API key forwarding.

Proposed solution

Add a new outgoing auth strategy: header_passthrough.

Configuration example:

outgoingAuth:
  type: header_passthrough
  headerPassthrough:
    headers:
      - x-mcp-api-key
      - x-mcp-auth

Implementation touch points:

  1. pkg/vmcp/auth/types/types.go — add StrategyTypeHeaderPassthrough + HeaderPassthroughConfig struct
  2. pkg/vmcp/auth/strategies/header_passthrough.go — new strategy reads specified headers from context
  3. Incoming middleware / server — store raw incoming request headers in context (currently only Identity is stored)
  4. pkg/vmcp/client/client.goidentityPropagatingRoundTripper pattern can be extended to carry selected headers

Security considerations

  • Only explicitly listed headers should be forwarded (allowlist, not passthrough-all)
  • Header names should be validated (CRLF injection prevention, same as header_injection)
  • Sensitive headers (e.g. authorization) should be allowed but documented as requiring care

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions