Skip to content

Provider profiles cannot send custom HTTP headers (needed to opt out of gateway-side MCP tool injection) #933

Description

@marko-k0

Problem

Named provider profiles ([providers.X]) can customize the request body via extra_body (#341) but have no way to attach custom HTTP headers. Some OpenAI-compatible gateways make per-request behavior decisions based on headers, and clients that can't send them are stuck with gateway-global config.

Concrete case: Bifrost's MCP auto tool injection. When a Bifrost gateway has MCP clients connected, it appends those tools to every inference request's tools array (gateway-side names like exa_mcp-web_search_exa). Bifrost's default execution mode is stateless, so calls to those tools come back to the caller unexecuted. jcode — which registers its own MCP tools (e.g. bridged to the same gateway's /mcp endpoint via stdio) — then receives calls to tool names it doesn't own and refuses them. The model sees two names for the same tool and picks the unexecutable one.

Bifrost's documented per-request opt-out is an empty x-bf-mcp-include-tools header (deny-all). There is currently no way to make jcode send it, so jcode's correctness depends on a gateway-wide setting (mcp_disable_auto_tool_inject), which the client should not have to rely on.

Proposal

Add extra_headers to named provider profiles, mirroring extra_body:

[providers.bifrost]
type = openai-compatible
base_url = http://bifrost:4000/v1
extra_headers = { x-bf-mcp-include-tools =  }  # empty = deny-all injection opt-out
  • Attached to every chat/completions request, after jcode's own headers.
  • Empty values are preserved (present-but-empty is the opt-out signal).
  • Invalid header names are logged and skipped at construction rather than failing provider init.

Related: #761 (native Streamable HTTP MCP would make the bridge unnecessary, but the header need is orthogonal).

Implementation ready: branch on my fork (marko-k0/jcode, feat/provider-extra-headers), with unit + wire-level tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions