Skip to content

fix(mcp): configurable session owner fingerprint and cap for shared keys - #35498

Open
sidmhatre17 wants to merge 4 commits into
BerriAI:litellm_internal_stagingfrom
sidmhatre17:fix/mcp-stateful-session-owner-cap
Open

fix(mcp): configurable session owner fingerprint and cap for shared keys#35498
sidmhatre17 wants to merge 4 commits into
BerriAI:litellm_internal_stagingfrom
sidmhatre17:fix/mcp-stateful-session-owner-cap

Conversation

@sidmhatre17

@sidmhatre17 sidmhatre17 commented Aug 1, 2026

Copy link
Copy Markdown

TLDR

Problem this solves:

  • Shared API keys collapse all MCP callers into one 100-session bucket
  • Cap was hardcoded, so teams could not raise or tune it per deployment

How it solves it:

  • LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_OWNER makes the per-owner cap configurable
  • Optional x-litellm-mcp-session-owner (or client IP) is bound to the authenticated identity (key+hdr / key+ip), not a replacement — shared-key users get independent buckets without cross-key hijacking
  • LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_AUTH_IDENTITY hard-caps total sessions under one credential so rotating the owner header cannot bypass the per-owner limit
  • Unauthenticated callers ignore the owner header and fall back to IP / anonymous (same as pre-fix keyless behavior)

Relevant issues

Fixes #35383

Linear ticket

Pre-Submission checklist

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

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

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

Screenshots / Proof of Fix

Unit regression coverage for the session-owner fingerprint paths (no live LLM calls required — this is proxy MCP session accounting):

uv run pytest tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_session_owner.py -v
# 8 passed

Type

🐛 Bug Fix

Changes

  • Read per-owner / per-auth-identity caps from env (LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_OWNER, LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_AUTH_IDENTITY); clamp non-positive values
  • Fingerprint authenticated callers as key+hdr:… / key+ip:… when the owner header or prefer-IP is set; default remains key:…
  • Ignore client-supplied owner header when unauthenticated; fall back to IP / anonymous
  • Enforce both per-owner and per-auth-identity session ceilings on initialize
  • Add mocked unit tests in tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_session_owner.py

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Allow LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_OWNER and prefer an explicit
session-owner header or client IP over a shared API key so IDE users
behind one service-account key get independent stateful session buckets.

Co-authored-by: Cursor <cursoragent@cursor.com>
@CLAassistant

CLAassistant commented Aug 1, 2026

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.

✅ sidmhatre17
❌ siddhesh mhatre


siddhesh mhatre seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes stateful MCP session limits configurable and adds optional request-header or client-IP owner fingerprints for shared API keys.

  • Adds environment-driven session-cap and owner-selection settings.
  • Applies the selected fingerprint consistently when checking, limiting, and recording sessions.
  • Adds focused unit coverage for header, IP, API-key, and cap behavior.

Confidence Score: 4/5

This PR should not merge until session ownership remains bound to authenticated identity and invalid non-positive session caps are rejected or handled safely.

A client-controlled header can satisfy another session's ownership check independently of the authenticated key, while non-positive configured caps make every stateful initialization fail.

Files Needing Attention: litellm/proxy/_experimental/mcp_server/server.py, litellm/constants.py

Security Review

The new ownership selection weakens the existing authenticated session boundary because an untrusted request attribute can replace authenticated identity. How this was verified: The client-supplied header is copied unchanged into the fingerprint, stored on initialization, and used as the sole equality check on subsequent session requests.

Important Files Changed

Filename Overview
litellm/constants.py Adds MCP owner configuration, but the new session cap is not constrained to the positive values required by enforcement.
litellm/proxy/_experimental/mcp_server/server.py Adds header/IP fingerprint precedence at all ownership call sites, but the header can replace authenticated identity without being bound to it.
tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_session_owner.py Covers fingerprint precedence and defaults but omits cross-key owner isolation and invalid configured-cap cases.

Reviews (1): Last reviewed commit: "fix(mcp): configurable session owner fin..." | Re-trigger Greptile

Comment thread litellm/proxy/_experimental/mcp_server/server.py Outdated
Comment thread litellm/constants.py Outdated
Comment thread litellm/proxy/_experimental/mcp_server/server.py Outdated
@veria-ai

veria-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 2 · PR risk: 0/10

@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.69369% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/proxy/_experimental/mcp_server/server.py 94.25% 5 Missing ⚠️
litellm/constants.py 91.66% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Address Greptile/Veria P1 findings: combine owner header/IP with the
authenticated credential instead of replacing it, add a per-auth-identity
hard ceiling against header rotation, and reject non-positive session caps.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sidmhatre17

Copy link
Copy Markdown
Author

Addressed the Greptile / Veria P1 findings in 5253514:

  1. Owner header no longer replaces auth identity — fingerprint is now key+hdr:{sha256(api_key || header)} (and key+ip:... when prefer-IP is on). Same header under different API keys no longer collides, so cross-key session hijacking is blocked.
  2. Non-positive caps are rejected_positive_int_env falls back to the default (100) for 0 / negative / invalid values.
  3. Header-rotation cap bypass — added LITELLM_MCP_MAX_STATEFUL_SESSIONS_PER_AUTH_IDENTITY (default max(1000, 10× per-owner)) as a hard ceiling across all owner sub-buckets of one authenticated credential.

Regression coverage updated in test_mcp_session_owner.py (cross-key isolation, prefer-IP binding, env clamp, auth-identity ceiling eviction). @greptileai please re-review.

Comment thread litellm/proxy/_experimental/mcp_server/server.py Outdated
Route session-owner settings through env helpers (matching the cap
parsers), annotate the auth-identity registry as intentionally mutable,
and avoid new mutable list/dict annotations so lint/docs checks pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sidmhatre17

Copy link
Copy Markdown
Author

Pushed CI fixes in c0e49df:

  • lint / type-discipline: removed new LIT001/LIT002 deltas (Mapping params, tuple returns, intentional mutable-ok on the auth-identity session registry, shared 429 helper)
  • documentation / code-quality env-key scan: session-owner settings now go through env helpers (same pattern as the positive-int cap parsers)

Companion docs PR for the public env reference: BerriAI/litellm-docs#737

@codspeed-hq

codspeed-hq Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing sidmhatre17:fix/mcp-stateful-session-owner-cap (fe7ae51) with litellm_internal_staging (491eda3)

Open in CodSpeed

Unauthenticated clients could rotate x-litellm-mcp-session-owner to
bypass both session caps; fall back to IP/anonymous instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

[Bug]: MCP stateful session cap is bucketed by API key — shared keys collapse all users into one 100-session limit

2 participants