googleapis/mcp-toolbox · error
description is required for tool %q
Error message
description is required for tool %q
What it means
Initialize() for the alloydbainl (natural language) tool requires a non-empty description. The description is what the LLM sees to decide when to use the tool, so an empty one is rejected at tool construction time with this error naming the tool.
Source
Thrown at internal/tools/alloydbainl/alloydbainl.go:70
type Config struct {
tools.ConfigBase `yaml:",inline"`
Type string `yaml:"type" validate:"required"`
Source string `yaml:"source" validate:"required"`
NLConfig string `yaml:"nlConfig" validate:"required"`
NLConfigParameters parameters.Parameters `yaml:"nlConfigParameters"`
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
}
// validate interface
var _ tools.ToolConfig = Config{}
func (cfg Config) ToolConfigType() string {
return resourceType
}
func (cfg Config) Initialize(context.Context) (tools.Tool, error) {
if cfg.Description == "" {
return nil, fmt.Errorf("description is required for tool %q", cfg.Name)
}
numParams := len(cfg.NLConfigParameters)
quotedNameParts := make([]string, 0, numParams)
placeholderParts := make([]string, 0, numParams)
for i, paramDef := range cfg.NLConfigParameters {
name := paramDef.GetName()
escapedName := strings.ReplaceAll(name, "'", "''") // Escape for SQL literal
quotedNameParts = append(quotedNameParts, fmt.Sprintf("'%s'", escapedName))
placeholderParts = append(placeholderParts, fmt.Sprintf("$%d", i+3)) // $1, $2 reserved
}
var stmt string
if numParams > 0 {
paramNamesSQL := fmt.Sprintf("ARRAY[%s]", strings.Join(quotedNameParts, ", "))
paramValuesSQL := fmt.Sprintf("ARRAY[%s]", strings.Join(placeholderParts, ", "))
// execute_nl_query is the AlloyDB AI function that executes the natural language query
// The first parameter is the natural language query, which is passed as $1View on GitHub (pinned to 8cc6e09de2)
Solutions
- Add a meaningful description field to the tool config explaining what the NL tool does.
- Check for template/variable substitution producing an empty string and fix the source value.
- Trim whitespace-only values — the check tests for empty string, so provide real text.
Example fix
// before
tools:
ask-db:
kind: alloydbainl
source: my-alloydb
// after
tools:
ask-db:
kind: alloydbainl
source: my-alloydb
description: Answer natural language questions about the AlloyDB database. Defensive patterns
Strategy: validation
Validate before calling
if cfg.Description == "" {
return errors.New("alloydbainl tool requires a non-empty description")
}
tool, err := cfg.Initialize(ctx) Try / catch
tool, err := cfg.Initialize(ctx)
if err != nil {
if strings.Contains(err.Error(), "description is required") {
// add/repair description and retry init
}
return err
} Prevention
- Always author a clear, specific description for every LLM-facing tool.
- Check templated configs for substitutions that can render empty strings.
- Add a config linter/schema check that requires description on all tool blocks.
When it happens
Trigger: Creating an alloydbainl tool config (YAML or programmatically) without the description field or with description: "", then calling Initialize().
Common situations: Minimal tool definitions copied from examples that omit description; templated configs where an interpolated description resolves to empty; hand-edited YAML deleting the field.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- invalid ipType %s
- password is provided without a username. Please provide both
- description is required for tool %q
- description is required for tool %q
- description is required for tool %q
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/83d03e2eabb1a9a3.
Report an issue: GitHub.