{"record":{"id":"d466df6b081c2d5e","repo":"googleapis/mcp-toolbox","slug":"scopesrequired-is-not-allowed-when-mcpenabled","errorCode":null,"errorMessage":"`scopesRequired` is not allowed when `mcpEnabled` is false","messagePattern":"`scopesRequired` is not allowed when `mcpEnabled` is false","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/generic/generic.go","lineNumber":75,"sourceCode":"\nfunc (cfg Config) IsMCPEnabled() bool {\n\treturn cfg.McpEnabled\n}\n\n// Initialize a generic auth service\nfunc (cfg Config) Initialize() (auth.AuthService, error) {\n\tif !cfg.McpEnabled {\n\t\tif cfg.IntrospectionEndpoint != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"`introspectionEndpoint` is not allowed when `mcpEnabled` is false\")\n\t\t}\n\t\tif cfg.IntrospectionMethod != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"`introspectionMethod` is not allowed when `mcpEnabled` is false\")\n\t\t}\n\t\tif cfg.IntrospectionParamName != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"`introspectionParamName` is not allowed when `mcpEnabled` is false\")\n\t\t}\n\t\tif len(cfg.ScopesRequired) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"`scopesRequired` is not allowed when `mcpEnabled` is false\")\n\t\t}\n\t}\n\thttpClient := newSecureHTTPClient()\n\n\t// Discover OIDC endpoints\n\tjwksURL, introspectionURL, issuer, err := discoverOIDCConfig(httpClient, cfg.AuthorizationServer)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to discover OIDC config: %w\", err)\n\t}\n\n\t// Override introspection URL if configured\n\tif cfg.IntrospectionEndpoint != \"\" {\n\t\tintrospectionURL = cfg.IntrospectionEndpoint\n\t}\n\n\t// Create the keyfunc to fetch and cache the JWKS in the background\n\tkf, err := keyfunc.NewDefault([]string{jwksURL})\n\tif err != nil {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/auth/generic/generic.go#L57-L93","documentation":"scopesRequired (scopes the token must contain) is only supported in MCP mode for the generic auth service. Initialize rejects a non-empty ScopesRequired list when McpEnabled is false, since legacy-mode validation never checks scopes.","triggerScenarios":"kind: generic auth service with mcpEnabled: false and a non-empty scopesRequired list in the YAML.","commonSituations":"Hardening a legacy deployment by copying scopesRequired from an MCP config; leaving scopesRequired after disabling MCP; assuming scopes work in legacy JWT validation.","solutions":["Enable mcpEnabled: true if scope enforcement is required","Remove scopesRequired for legacy-mode deployments (legacy mode validates JWT signature/claims only)","Switch the deployment to MCP mode to get scopes + introspection support"],"exampleFix":"// before\nkind: generic\nmcpEnabled: false\nscopesRequired: [read:tools]\n// after\nkind: generic\nmcpEnabled: true\nscopesRequired: [read:tools]","handlingStrategy":"validation","validationCode":"mcp=$(yq '.authServices.my-auth.mcpEnabled' auth.yaml)\nscopes=$(yq '.authServices.my-auth.scopesRequired' auth.yaml)\nif [ \"$mcp\" != \"true\" ] && [ \"$scopes\" != \"null\" ] && [ \"$scopes\" != \"[]\" ]; then\n  echo \"scopesRequired requires mcpEnabled: true\"; exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember legacy generic auth validates JWT signature only — no scopes","Enable mcpEnabled when scope/introspection enforcement is a requirement","Add schema validation of authServices blocks to the deploy pipeline"],"tags":["configuration","auth","oidc","scopes"],"backgroundTag":"invalid-auth-config","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}