{"record":{"id":"91eeb0e0b682166c","repo":"googleapis/mcp-toolbox","slug":"description-is-required-for-tool-q-91eeb0","errorCode":null,"errorMessage":"description is required for tool %q","messagePattern":"description is required for tool %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/postgres/postgreslisttables/postgreslisttables.go","lineNumber":144,"sourceCode":"\tRunSQL(context.Context, string, []any) (any, error)\n}\n\ntype Config struct {\n\ttools.ConfigBase `yaml:\",inline\"`\n\tType             string                 `yaml:\"type\" validate:\"required\"`\n\tSource           string                 `yaml:\"source\" validate:\"required\"`\n\tAnnotations      *tools.ToolAnnotations `yaml:\"annotations,omitempty\"`\n}\n\nvar _ tools.ToolConfig = Config{}\n\nfunc (cfg Config) ToolConfigType() string {\n\treturn resourceType\n}\n\nfunc (cfg Config) Initialize(context.Context) (tools.Tool, error) {\n\tif cfg.Description == \"\" {\n\t\treturn nil, fmt.Errorf(\"description is required for tool %q\", cfg.Name)\n\t}\n\tallParameters := parameters.Parameters{\n\t\tparameters.NewStringParameter(\"table_names\", \"Optional: A comma-separated list of table names. If empty, details for all tables will be listed.\", parameters.WithStringDefault(\"\")),\n\t\tparameters.NewStringParameter(\"output_format\", \"Optional: Use 'simple' for names only or 'detailed' for full info.\", parameters.WithStringDefault(\"detailed\")),\n\t}\n\n\treturn Tool{\n\t\tBaseTool: tools.NewBaseTool(\n\t\t\tcfg,\n\t\t\ttools.GetAnnotationsOrDefault(cfg.Annotations, tools.NewReadOnlyAnnotations),\n\t\t\ttools.Manifest{Description: cfg.Description, Parameters: allParameters.Manifest(), AuthRequired: cfg.AuthRequired},\n\t\t\tallParameters,\n\t\t),\n\t}, nil\n}\n\nvar _ tools.Tool = Tool{}\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/postgres/postgreslisttables/postgreslisttables.go#L126-L162","documentation":"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.","triggerScenarios":"Defining a `postgres-list-tables` tool in the tools yaml without a `description:` field, or with `description: \"\"` — cfg.Description == \"\" in Initialize.","commonSituations":"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.","solutions":["Add a non-empty `description:` to the tool's yaml entry.","If constructing Config in Go, set ConfigBase.Description before calling Initialize.","Check yaml indentation so the description key actually nests under the tool.","Use a prebuilt config as a template to get the required fields right."],"exampleFix":"# before\ntools:\n  list-tables:\n    kind: postgres-list-tables\n    source: my-pg\n# after\ntools:\n  list-tables:\n    kind: postgres-list-tables\n    source: my-pg\n    description: Lists detailed schema information for tables in a Postgres database.","handlingStrategy":"validation","validationCode":"# shell check before starting toolbox\npython3 - <<'EOF'\nimport sys, yaml\ncfg = yaml.safe_load(open('tools.yaml'))\nfor name, t in (cfg.get('tools') or {}).items():\n    if not t.get('description'):\n        sys.exit(f\"tool {name!r} is missing a non-empty description\")\nEOF","typeGuard":"// Go-side guard before Initialize\nif cfg.Description == \"\" {\n    return fmt.Errorf(\"tool %q has no description; set ConfigBase.Description\", cfg.Name)\n}","tryCatchPattern":null,"preventionTips":["Always include a meaningful `description:` for every tool in the yaml.","Copy tool definitions from prebuilt configs that already include descriptions.","Watch yaml indentation so description stays nested under the tool entry.","Lint configs in CI to reject empty description fields."],"tags":["postgres","config","validation","yaml"],"backgroundTag":"missing-required-argument","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"}