googleapis/mcp-toolbox · error

description is required for tool %q

Error message

description is required for tool %q

What it means

The postgres-list-tables Config.Initialize requires a non-empty `description`; because ConfigBase's description is not marked required elsewhere, Initialize enforces it explicitly and returns this error when the field is empty or omitted. Descriptions are what the MCP client/LLM sees for the tool, so Toolbox refuses to register undescribed tools. This fires during config parsing/initialization, before any database connection is made.

Source

Thrown at internal/tools/postgres/postgreslisttables/postgreslisttables.go:144

	RunSQL(context.Context, string, []any) (any, error)
}

type Config struct {
	tools.ConfigBase `yaml:",inline"`
	Type             string                 `yaml:"type" validate:"required"`
	Source           string                 `yaml:"source" validate:"required"`
	Annotations      *tools.ToolAnnotations `yaml:"annotations,omitempty"`
}

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)
	}
	allParameters := parameters.Parameters{
		parameters.NewStringParameter("table_names", "Optional: A comma-separated list of table names. If empty, details for all tables will be listed.", parameters.WithStringDefault("")),
		parameters.NewStringParameter("output_format", "Optional: Use 'simple' for names only or 'detailed' for full info.", parameters.WithStringDefault("detailed")),
	}

	return Tool{
		BaseTool: tools.NewBaseTool(
			cfg,
			tools.GetAnnotationsOrDefault(cfg.Annotations, tools.NewReadOnlyAnnotations),
			tools.Manifest{Description: cfg.Description, Parameters: allParameters.Manifest(), AuthRequired: cfg.AuthRequired},
			allParameters,
		),
	}, nil
}

var _ tools.Tool = Tool{}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Add a non-empty `description:` to the tool's yaml entry.
  2. If constructing Config in Go, set ConfigBase.Description before calling Initialize.
  3. Check yaml indentation so the description key actually nests under the tool.
  4. Use a prebuilt config as a template to get the required fields right.

Example fix

# before
tools:
  list-tables:
    kind: postgres-list-tables
    source: my-pg
# after
tools:
  list-tables:
    kind: postgres-list-tables
    source: my-pg
    description: Lists detailed schema information for tables in a Postgres database.
Defensive patterns

Strategy: validation

Validate before calling

# shell check before starting toolbox
python3 - <<'EOF'
import sys, yaml
cfg = yaml.safe_load(open('tools.yaml'))
for name, t in (cfg.get('tools') or {}).items():
    if not t.get('description'):
        sys.exit(f"tool {name!r} is missing a non-empty description")
EOF

Type guard

// Go-side guard before Initialize
if cfg.Description == "" {
    return fmt.Errorf("tool %q has no description; set ConfigBase.Description", cfg.Name)
}

Prevention

When it happens

Trigger: Defining a `postgres-list-tables` tool in the tools yaml without a `description:` field, or with `description: ""` — cfg.Description == "" in Initialize.

Common situations: Minimal hand-written tool configs that only set name/kind/source; YAML indentation mistakes that drop the description key; programmatically constructing Config and leaving Description unset; copying tool blocks and deleting the description.

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/91eeb0e0b682166c. Report an issue: GitHub.