BerriAI/litellm · error · HTTPException

MCPJWTSigner: incoming token is missing required claims: {mi

Error message

MCPJWTSigner: incoming token is missing required claims: {missing}. Configure the IdP to include these claims.

What it means

After successfully verifying an incoming token, MCPJWTSigner checks that every entry in required_claims is present and truthy in the verified claims; any missing claim yields HTTPException 403 naming the missing claims. This is an authorization policy check - the token is authentic but lacks required identity attributes.

Source

Thrown at litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/mcp_jwt_signer.py:527

    # FR-15: Incoming claim validation
    # ------------------------------------------------------------------

    def _validate_required_claims(
        self,
        jwt_claims: Mapping[str, object] | None,
    ) -> None:
        """
        Raise HTTP 403 if any required_claims are absent from the verified
        incoming token claims.
        """
        if not self.required_claims:
            return

        from fastapi import HTTPException

        missing: Final = [c for c in self.required_claims if not (jwt_claims or {}).get(c)]
        if missing:
            raise HTTPException(
                status_code=403,
                detail={
                    "error": (
                        f"MCPJWTSigner: incoming token is missing required claims: "
                        f"{missing}. Configure the IdP to include these claims."
                    )
                },
            )

    # ------------------------------------------------------------------
    # FR-12: End-user identity mapping
    # ------------------------------------------------------------------

    def _resolve_end_user_identity(
        self,
        user_api_key_dict: UserAPIKeyAuth,
        jwt_claims: Mapping[str, object] | None,
    ) -> str:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Configure the IdP to include the required claims in access tokens (add claim to token via custom claims/scope mapping)
  2. Align required_claims with names the IdP actually emits - check casing and spelling against a decoded token
  3. Trim required_claims to what the token realistically contains, moving strict requirements elsewhere (e.g. scopes)

Example fix

# before - requires a claim the IdP never emits
litellm_params:
  required_claims: [email, org_id]

# after - matches the IdP's emitted claims
litellm_params:
  required_claims: [sub, email]
Defensive patterns

Strategy: try-catch

Validate before calling

import jwt as pyjwt  
  
def claims_cover_required(token: str, required: list[str]) -> bool:  
    claims = pyjwt.decode(token, options={"verify_signature": False})  
    return all(claims.get(c) for c in required)  
  
assert claims_cover_required(sample_token, required_claims)  # validate config against a real token before rollout

Try / catch

import openai  
  
try:  
    resp = client.responses.create(model=deployment, tools=mcp_tools, input=prompt)  
except openai.PermissionDeniedError as e:  
    msg = getattr(e, "body", {}).get("error", "") if isinstance(getattr(e, "body", None), dict) else str(e)  
    if "missing required claims" in msg:  
        return guide_user_to_token_with_full_claims()  
    raise

Prevention

When it happens

Trigger: An MCP request whose verified JWT/opaque-token claims omit one of the configured required_claims - e.g. required_claims: [email, org_id] but the IdP-issued token only contains sub and scope.

Common situations: IdP access tokens that carry only standard claims while the policy expects custom ones (org_id, team); claim names cased differently (OrgID vs org_id); scope-only machine tokens with no user identity claims; required_claims copied from another IdP's claim vocabulary.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/8592503257bc72a4. Report an issue: GitHub.