{"record":{"id":"16ee611ccad5dcef","repo":"googleapis/mcp-toolbox","slug":"authrequired-and-useclientoauth-are-mutually-e","errorCode":null,"errorMessage":"`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method","messagePattern":"`authRequired` and `useClientOAuth` are mutually exclusive\\. Choose only one authentication method","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/server/config.go","lineNumber":467,"sourceCode":"\tactual := gemini.Config{Name: name}\n\tif err := dec.DecodeContext(ctx, &actual); err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse as %q: %w\", name, err)\n\t}\n\treturn actual, nil\n}\n\nfunc UnmarshalYAMLToolConfig(ctx context.Context, name string, r map[string]any) (tools.ToolConfig, error) {\n\terr := NameValidation(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tresourceType, ok := r[\"type\"].(string)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"missing 'type' field or it is not a string\")\n\t}\n\t// `authRequired` and `useClientOAuth` cannot be specified together\n\tif r[\"authRequired\"] != nil && r[\"useClientOAuth\"] == true {\n\t\treturn nil, fmt.Errorf(\"`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method\")\n\t}\n\t// Make `authRequired` an empty list instead of nil for Tool manifest\n\tif r[\"authRequired\"] == nil {\n\t\tr[\"authRequired\"] = []string{}\n\t}\n\n\t// Parse scopesRequired if present\n\tif rawScopes, ok := r[\"scopesRequired\"]; ok {\n\t\tif scopesList, ok := rawScopes.([]any); ok {\n\t\t\tvar scopes []string\n\t\t\tfor _, s := range scopesList {\n\t\t\t\tif str, ok := s.(string); ok {\n\t\t\t\t\tscopes = append(scopes, str)\n\t\t\t\t}\n\t\t\t}\n\t\t\tr[\"scopesRequired\"] = scopes\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"scopesRequired must be a list of strings\")","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/config.go#L449-L485","documentation":"A tool config specified both `authRequired` and `useClientOAuth: true`. These are two different authorization models — server-enforced authorized services vs. delegating auth to the MCP client — and are mutually exclusive, so parsing is rejected.","triggerScenarios":"A tools entry contains a non-null `authRequired` value AND `useClientOAuth: true` simultaneously, e.g. after adding useClientOAuth to an existing tool that already had authRequired: [my-auth].","commonSituations":"Migrating a tool from service-level auth to client OAuth but leaving the old authRequired list in place; copy-pasting auth blocks between tool definitions; misunderstanding that an empty-but-present authRequired still counts as specified.","solutions":["Remove `authRequired` from the tool if you want client-side OAuth (keep useClientOAuth: true)","Remove `useClientOAuth: true` if you want to keep the authRequired list","Ensure only one authentication mechanism is configured per tool"],"exampleFix":"// before\nexecute-sql:\n  type: postgres-sql\n  authRequired:\n    - my-google\n  useClientOAuth: true\n// after\nexecute-sql:\n  type: postgres-sql\n  useClientOAuth: true","handlingStrategy":"validation","validationCode":"func validateToolAuth(cfg map[string]any) error {\n  _, hasAuthReq := cfg[\"authRequired\"]\n  uco, hasUco := cfg[\"useClientOAuth\"].(bool)\n  if hasAuthReq && cfg[\"authRequired\"] != nil && hasUco && uco {\n    return fmt.Errorf(\"authRequired and useClientOAuth are mutually exclusive\")\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one auth model per tool: either authRequired services or useClientOAuth","When migrating to client OAuth, delete the authRequired list in the same change","Add a config-lint rule asserting the two keys never co-occur"],"tags":["config","auth","tools","validation"],"backgroundTag":"mutually-exclusive-config-options","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"}