googleapis/mcp-toolbox · error
scopesRequired must be a list of strings
Error message
scopesRequired must be a list of strings
What it means
The tool's `scopesRequired` field was present but is not a list of strings (r["scopesRequired"] failed the []any assertion). The parser normalizes scope lists into []string and rejects anything else so the tool manifest can advertise required scopes correctly.
Source
Thrown at internal/server/config.go:485
return nil, fmt.Errorf("`authRequired` and `useClientOAuth` are mutually exclusive. Choose only one authentication method")
}
// Make `authRequired` an empty list instead of nil for Tool manifest
if r["authRequired"] == nil {
r["authRequired"] = []string{}
}
// Parse scopesRequired if present
if rawScopes, ok := r["scopesRequired"]; ok {
if scopesList, ok := rawScopes.([]any); ok {
var scopes []string
for _, s := range scopesList {
if str, ok := s.(string); ok {
scopes = append(scopes, str)
}
}
r["scopesRequired"] = scopes
} else {
return nil, fmt.Errorf("scopesRequired must be a list of strings")
}
}
// validify parameter references
if rawParams, ok := r["parameters"]; ok {
if paramsList, ok := rawParams.([]any); ok {
// Turn params into a map
validParamNames := make(map[string]bool)
for _, rawP := range paramsList {
if pMap, ok := rawP.(map[string]any); ok {
if pName, ok := pMap["name"].(string); ok && pName != "" {
validParamNames[pName] = true
}
}
}
// Validate references
for i, rawP := range paramsList {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Wrap the value in a YAML list: scopesRequired: [scope1, scope2]
- Remove scopesRequired if the tool needs no scopes (it is optional)
- Ensure every element is a plain string
Example fix
// before
scopesRequired: https://www.googleapis.com/auth/cloud-platform
// after
scopesRequired:
- https://www.googleapis.com/auth/cloud-platform Defensive patterns
Strategy: type-guard
Validate before calling
func validateScopes(cfg map[string]any) error {
raw, ok := cfg["scopesRequired"]
if !ok { return nil }
list, ok := raw.([]any)
if !ok { return fmt.Errorf("scopesRequired must be a list") }
for _, s := range list {
if _, ok := s.(string); !ok { return fmt.Errorf("scopesRequired items must be strings") }
}
return nil
} Type guard
func isStringList(v any) bool {
list, ok := v.([]any)
if !ok { return false }
for _, s := range list { if _, ok := s.(string); !ok { return false } }
return true
} Prevention
- Always write scopesRequired as a YAML list, even for one scope
- Never write a bare string or map for scopesRequired
- Validate with a YAML schema before deploy
When it happens
Trigger: A tools entry has `scopesRequired: my-scope` (bare string instead of list), `scopesRequired: {a: b}` (map), or `scopesRequired: [1, 2]` (non-string elements still pass the []any check but non-string items are silently dropped — the error fires only when the whole value is not a list).
Common situations: Writing a single scope without brackets; YAML merging producing a map; pasting comma-separated scopes as one string; indentation errors nesting scopes under the wrong key.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- doc %d: unexpected non-string key in input: %v
- doc %d: invalid config format at key %q: %w
- doc %d: invalid config format at key %q: expected nested for
- %s missing 'kind' field or it is not a string
- missing 'kind' field or it is not a string: %v
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/4bfd4c220b48f564.
Report an issue: GitHub.