Skip to content

cherry-pick: OpenAPI MCP extra_headers (#27383) onto litellm_1.84.0rc2#27768

Merged
yuneng-berri merged 3 commits into
BerriAI:litellm_1.84.0rc2from
milan-berri:litellm_cherry-pick-27383-onto-1.84.0rc2
May 12, 2026
Merged

cherry-pick: OpenAPI MCP extra_headers (#27383) onto litellm_1.84.0rc2#27768
yuneng-berri merged 3 commits into
BerriAI:litellm_1.84.0rc2from
milan-berri:litellm_cherry-pick-27383-onto-1.84.0rc2

Conversation

@milan-berri

Copy link
Copy Markdown
Collaborator

Relevant issues

Cherry-picks #27383 onto litellm_1.84.0rc2.

Fixes #26794 (same as #27383).

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Screenshots / Proof of Fix

No UI change. Locally, python3 -m pytest tests/test_litellm/proxy/_experimental/mcp_server/test_openapi_to_mcp_generator.py passed (49 tests) after the cherry-pick and test alignment commit.

Type

🐛 Bug Fix

Changes

Summary

Bring #27383 onto litellm_1.84.0rc2 so the RC matches staging for OpenAPI MCP header behavior.

Included commits (cherry-picked)

  1. fix(mcp): forward extra_headers for OpenAPI MCP tools — copy MCPServer.extra_headers into _request_extra_headers before local tool dispatch; merge in openapi_to_mcp_generator. OAuth2 M2M: do not forward caller Authorization from raw_headers (same idea as managed MCP).
  2. refactor(mcp): access has_client_credentials on MCPServer directly — small cleanup.
  3. fix(mcp): static headers win over forwarded headers in OpenAPI MCP — operator static headers override forwarded headers on name conflict (case-insensitive); BYOK _request_auth_header still overrides Authorization last.

Not cherry-picked

Two merge commits from litellm_internal_staging on the original PR branch were skipped (unrelated history).

Follow-up on this branch

milan-berri and others added 3 commits May 12, 2026 23:33
OpenAPI-generated tools only applied static closure headers and BYOK
Authorization via ContextVar. Copy MCPServer.extra_headers from the
incoming MCP request into _request_extra_headers (set in server.py before
local tool dispatch), merge in openapi_to_mcp_generator via a small helper.

OAuth2 M2M: do not forward caller Authorization from raw_headers (same rule
as _prepare_mcp_server_headers for managed MCP).

Adds TestRequestExtraHeaders and clarifies mcp_server_manager registration
comment.

Fixes BerriAI#26794

Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile: getattr default was redundant; property exists on MCPServer and
mcp_server is non-None inside the extra_headers forwarding block.

Co-authored-by: Cursor <cursoragent@cursor.com>
Match the existing MCP invariant in merge_mcp_headers and the managed MCP
path: operator-configured static headers always override caller-forwarded
headers on name conflict, with case-insensitive comparison so different
casing cannot bypass the precedence. _request_auth_header (BYOK) still
overrides Authorization last.

Addresses Veria review on PR BerriAI#27383.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ milan-berri
❌ cursoragent
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Cherry-picks the OpenAPI MCP extra_headers forwarding feature (#27383) onto the litellm_1.84.0rc2 branch, bringing the RC in sync with staging. The change adds a _request_extra_headers ContextVar that is populated in server.py from MCPServer.extra_headers allowlist entries before local tool dispatch, and consumed in openapi_to_mcp_generator.py when building request headers.

  • Adds _merge_openapi_tool_request_headers with a clear 3-level precedence: BYOK _request_auth_header > operator static_headers > caller-forwarded extra_headers; case-insensitive conflict detection prevents header spoofing by callers.
  • Preserves the OAuth2 M2M invariant: if has_client_credentials is true, the caller's Authorization header is never forwarded, matching the managed MCP path.
  • Covers the new paths with 7 mock-only unit tests including edge cases for casing, conflict resolution, and ContextVar isolation between requests.

Confidence Score: 5/5

Safe to merge; all changes are scoped to the experimental OpenAPI MCP path with no impact on existing managed MCP or core request flows.

The forwarding logic is well-guarded: ContextVars are always reset in finally blocks preventing header leakage, static operator headers cannot be overridden by callers, and the OAuth2 M2M guard mirrors the existing managed MCP path. All 7 new tests are mock-only and cover the critical conflict-resolution and isolation scenarios. No existing tests were modified.

No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py Adds _request_extra_headers ContextVar and _merge_openapi_tool_request_headers helper; replaces inline auth override with the new merge function inside create_tool_function. Precedence logic (BYOK auth > static > forwarded) is correct, case-insensitive conflict detection is properly implemented.
litellm/proxy/_experimental/mcp_server/server.py Populates _request_extra_headers from MCPServer.extra_headers allowlist against raw_headers before dispatching to local OpenAPI tools; resets both ContextVars in a finally block. The OAuth2 M2M guard (skip_caller_authorization) matches the managed MCP path. No header leakage between requests.
litellm/proxy/_experimental/mcp_server/mcp_server_manager.py Comment-only update clarifying that extra_headers values are applied at call-time via ContextVar, not baked in at tool registration. No logic changes.
tests/test_litellm/proxy/_experimental/mcp_server/test_openapi_to_mcp_generator.py Adds 7 new mock-only tests in TestRequestExtraHeaders covering: header forwarding, no default injection, merge with statics, conflict resolution (static wins, case-insensitively), BYOK auth precedence, and no ContextVar leakage between calls. No existing tests are modified.

Reviews (1): Last reviewed commit: "fix(mcp): static headers win over forwar..." | Re-trigger Greptile

@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/proxy/_experimental/mcp_server/server.py 25.00% 12 Missing ⚠️

📢 Thoughts on this report? Let us know!

@yuneng-berri yuneng-berri merged commit 4046cb1 into BerriAI:litellm_1.84.0rc2 May 12, 2026
41 of 42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants