{"record":{"id":"c6937ab756425067","repo":"BerriAI/litellm","slug":"mcpjwtsigner-guardrail-requires-a-guardrail-name","errorCode":null,"errorMessage":"MCPJWTSigner guardrail requires a guardrail_name","messagePattern":"MCPJWTSigner guardrail requires a guardrail_name","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/__init__.py","lineNumber":18,"sourceCode":"\"\"\"MCP JWT Signer guardrail — built-in LiteLLM guardrail for zero trust MCP auth.\"\"\"\n\nfrom typing import TYPE_CHECKING, Final\n\nfrom litellm.types.guardrails import SupportedGuardrailIntegrations\n\nfrom .mcp_jwt_signer import MCPJWTSigner, get_mcp_jwt_signer\n\nif TYPE_CHECKING:\n    from litellm.types.guardrails import Guardrail, LitellmParams\n\n\ndef initialize_guardrail(litellm_params: \"LitellmParams\", guardrail: \"Guardrail\") -> MCPJWTSigner:\n    import litellm\n\n    guardrail_name: Final = guardrail.get(\"guardrail_name\")\n    if not guardrail_name:\n        raise ValueError(\"MCPJWTSigner guardrail requires a guardrail_name\")\n\n    mode: Final = litellm_params.mode\n    if mode != \"pre_mcp_call\":\n        raise ValueError(\n            f\"MCPJWTSigner guardrail '{guardrail_name}' has mode='{mode}' but must use \"\n            \"mode='pre_mcp_call'. JWT injection only fires for MCP tool calls.\"\n        )\n\n    optional_params: Final = getattr(litellm_params, \"optional_params\", None)\n\n    def _get(key):\n        if optional_params is not None:\n            v: Final = getattr(optional_params, key, None)\n            if v is not None:\n                return v\n        return getattr(litellm_params, key, None)\n\n    signer: Final = MCPJWTSigner(","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/__init__.py#L1-L36","documentation":"initialize_guardrail() for the MCP JWT signer reads guardrail_name from the guardrail entry and raises ValueError when it is missing. Like other guardrail init errors it surfaces at proxy startup, before any MCP traffic is signed.","triggerScenarios":"A guardrails entry with guardrail: mcp_jwt_signer (or its initializer path) but no guardrail_name key.","commonSituations":"Guardrail YAML assembled by hand or template where the name line was dropped; entries generated programmatically without the name; configs migrated between guardrail formats.","solutions":["Add guardrail_name: <unique-name> to the mcp_jwt_signer guardrail entry","Validate generated configs contain guardrail_name before deploying"],"exampleFix":"# before\n guardrails:\n   - guardrail: mcp_jwt_signer\n     litellm_params:\n       mode: pre_mcp_call\n\n# after\n guardrails:\n   - guardrail: mcp_jwt_signer\n     guardrail_name: mcp-jwt-signer\n     litellm_params:\n       mode: pre_mcp_call","handlingStrategy":"validation","validationCode":"assert guardrail_entry.get(\"guardrail_name\"), (  \n    \"mcp_jwt_signer entry requires guardrail_name\"  \n)","typeGuard":"def has_guardrail_name(entry: object) -> bool:  \n    return isinstance(entry, dict) and isinstance(entry.get(\"guardrail_name\"), str) and bool(entry[\"guardrail_name\"].strip())","tryCatchPattern":null,"preventionTips":["Run a config lint that asserts guardrail_name on every guardrails entry before deploy","Build guardrail entries from typed models so a missing name fails at generation time"],"tags":["mcp","jwt","guardrail","config","startup"],"backgroundTag":"config-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}