Skip to content

MCP invocation can replace a valid provider header with Bearer None #7587

Closed

Description

@CorgiBoyG

Describe the bug

After #7550 made explicit auth headers authoritative over header_provider, an unusable OAuth2 credential can replace a valid provider Authorization header with the literal value Bearer None during MCP tool invocation.

Current main (18a41a543f2db1dd8856b8f887d48d0c4c2ab56e) still has this behavior in McpTool._get_headers():

if credential.oauth2:
  headers = {"Authorization": f"Bearer {credential.oauth2.access_token}"}

The discovery path already avoids this through build_auth_headers(), which only emits an OAuth2 header when access_token is truthy. Invocation therefore diverges again for this edge case:

  • discovery: no usable auth header, so the provider header survives;
  • invocation: Bearer None is treated as auth and overrides the provider header.

This follow-up is necessary because Copybara imported the earlier #7550 patch as f82aa222, before the final PR revision added the empty-token guard and regression test.

Reproduction

credential = AuthCredential(
    auth_type=AuthCredentialTypes.OAUTH2,
    oauth2=OAuth2Auth(access_token=None),
)

auth_headers = await McpTool._get_headers(tool, tool_context, credential)
merged = _merge_auth_and_provider_headers(
    auth_headers=auth_headers,
    provider_headers={"Authorization": "Bearer provider-token"},
)

assert auth_headers == {"Authorization": "Bearer None"}
assert merged == {"Authorization": "Bearer None"}

The same result is reproducible on current main.

Expected behavior

An OAuth2 credential without an access token is not usable auth and should not emit an Authorization header. The valid provider header should remain in effect, matching the discovery path.

Proposed fix

Require a truthy credential.oauth2.access_token before building the OAuth2 header in McpTool._get_headers(), and add a regression test at the create_session() boundary.

Related changes

Activity

  1. CorgiBoyG commented on Oct 17, 2026

    @CorgiBoyG
    ContributorAuthor

    I'd like to take this follow-up. I reproduced it on current main, have a focused regression test that fails with Bearer None, and will prepare the minimal one-line guard plus relevant MCP/auth verification.

  2. added a commit that references this issue on Oct 20, 2026
    dc78d0a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions