{"record":{"id":"5696323dfdb6d1e2","repo":"BerriAI/litellm","slug":"mcpjwtsigner-token-introspection-endpoint-is-requ","errorCode":null,"errorMessage":"MCPJWTSigner: token_introspection_endpoint is required for opaque token verification but is not configured.","messagePattern":"MCPJWTSigner: token_introspection_endpoint is required for opaque token verification but is not configured\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/mcp_jwt_signer.py","lineNumber":484,"sourceCode":"            decode_kwargs[\"audience\"] = self.verify_audience\n        else:\n            decode_options[\"verify_aud\"] = False\n\n        if self.verify_issuer:\n            decode_kwargs[\"issuer\"] = self.verify_issuer\n\n        payload: Final[dict[str, object]] = jwt.decode(raw_token, signing_jwk.key, **decode_kwargs)\n        return payload\n\n    async def _introspect_opaque_token(self, token: str) -> dict[str, object]:\n        \"\"\"\n        Perform RFC 7662 token introspection for opaque (non-JWT) tokens.\n\n        Returns the introspection response dict.  Raises on HTTP error or\n        inactive token.\n        \"\"\"\n        if not self.token_introspection_endpoint:\n            raise ValueError(\n                \"MCPJWTSigner: token_introspection_endpoint is required for \"\n                \"opaque token verification but is not configured.\"\n            )\n\n        from litellm.llms.custom_httpx.http_handler import (\n            get_async_httpx_client,\n            httpxSpecialProvider,\n        )\n\n        client: Final = get_async_httpx_client(llm_provider=httpxSpecialProvider.Oauth2Check)\n        resp: Final = await client.post(\n            self.token_introspection_endpoint,\n            data={\"token\": token},\n            headers={\"Accept\": \"application/json\"},\n        )\n        resp.raise_for_status()\n        result: Final[dict[str, object]] = resp.json()\n        if not result.get(\"active\", False):","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/mcp_jwt_signer.py#L466-L502","documentation":"Opaque (non-JWT) bearer tokens cannot be verified against a JWKS, so MCPJWTSigner verifies them via RFC 7662 token introspection. _introspect_opaque_token raises ValueError when it is reached but token_introspection_endpoint was never configured - the verification path is impossible to complete.","triggerScenarios":"access_token_discovery_uri is set, an incoming request carries an opaque bearer token (not three dot-separated base64 segments), and the guardrail's litellm_params lack token_introspection_endpoint.","commonSituations":"Mixing JWT and opaque-token clients (legacy API keys, reference tokens from IdentityServer); enabling incoming verification for JWTs and then an opaque-token client arrives; introspection endpoint configured under a typo'd key so it reads as None.","solutions":["Configure token_introspection_endpoint in the guardrail litellm_params, pointing at the IdP's RFC 7662 introspection endpoint","Alternatively send JWT access tokens from clients so the JWKS path is used","If opaque tokens need not be verified, remove access_token_discovery_uri - the signer then logs a warning and proceeds without verification"],"exampleFix":"# before - opaque tokens arrive but no introspection endpoint\nlitellm_params:\n  access_token_discovery_uri: https://idp.example.com/.well-known/openid-configuration\n\n# after - RFC 7662 introspection configured\nlitellm_params:\n  access_token_discovery_uri: https://idp.example.com/.well-known/openid-configuration\n  token_introspection_endpoint: https://idp.example.com/oauth2/introspect","handlingStrategy":"validation","validationCode":"lp = guardrail_entry[\"litellm_params\"]  \nif lp.get(\"access_token_discovery_uri\"):  \n    # opaque bearer tokens will need RFC 7662 introspection  \n    assert lp.get(\"token_introspection_endpoint\") or clients_send_jwt_only, (  \n        \"token_introspection_endpoint required when opaque tokens may arrive\"  \n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide up front whether clients send JWTs or opaque tokens; if opaque, configure token_introspection_endpoint with the IdP","Decode a sample client token (count the dot-separated segments) to confirm which verification path you need"],"tags":["mcp","jwt","token-introspection","oauth","guardrail"],"backgroundTag":"token-introspection-misconfigured","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}