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 $1

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Add a meaningful description field to the tool config explaining what the NL tool does.
  2. Check for template/variable substitution producing an empty string and fix the source value.
  3. 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

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


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/83d03e2eabb1a9a3. Report an issue: GitHub.