Skip to content

Accept a header provider on MCPClient and scope injected headers to the server origin #63

Description

@shibayan

Motivation

MCPClient accepts headers as a static record, which is placed into the transport's
requestInit once, when the connection is opened. A bearer token that has to be refreshed — or
any value belonging to the request in flight — cannot be expressed that way, and a long-lived
connection shared across users would replay whatever was captured when it was opened.

FoundryToolbox already solves this: it passes a fetch hook to the transport and builds the
headers per request, attaching a cached token and the call id of the request in flight. Its class
documentation spells out why this cannot be a static header set — the connection outlives any one
user, so a credential captured at connect time would be sent on behalf of whoever comes later.
That pattern should be the supported one rather than something each integration rebuilds.

Proposal

  1. Widen headers to
    Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>),
    documenting that the provider is called per request, so token refresh works without a custom
    transport.
  2. Move the implementation from requestInit.headers to the fetch hook, wrapping any
    caller-supplied fetch on the outside so a replacement cannot drop the headers.
  3. Attach injected headers only to requests whose origin (scheme, host, port) matches the
    configured URL, so they are not carried to a third-party origin across a redirect. Python
    applies exactly this rule to its header provider. Node strips authorization on a cross-origin
    redirect on its own, but custom headers are not covered, and the ones this framework injects
    today include a call id and W3C trace context.
  4. Rebase FoundryToolbox onto the shared implementation.

Acceptance criteria

  • A dynamic provider's headers appear on each request, against a mock server.
  • An expiring token is refreshed without writing a transportFactory.
  • Injected headers are not attached to a cross-origin redirect target.
  • The existing FoundryToolbox authorization tests still pass against the shared path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    foundryUsage: [Issues, PRs], Target: Microsoft Foundry integrationsmcpUsage: [Issues, PRs], Target: Model Context Protocol integrationssecurityUsage: [Issues, PRs], Target: public security hardening; report vulnerabilities privately

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions