googleapis/mcp-toolbox · error
unable to parse tool %q as type %q: %w
Error message
unable to parse tool %q as type %q: %w
What it means
After DecodeConfig finds the factory for the tool type, it invokes the factory to parse the tool's YAML block. If that factory returns an error, it is wrapped with this message naming the tool and the type. This means the tool's kind was valid but the tool-specific configuration could not be parsed or initialized.
Source
Thrown at internal/tools/tools.go:63
// Tool with this type already exists, do not overwrite.
return false
}
toolRegistry[resourceType] = factory
return true
}
var ErrUnknownToolType = fmt.Errorf("unknown tool type")
// DecodeConfig looks up the registered factory for the given type and uses it
// to decode the tool configuration.
func DecodeConfig(ctx context.Context, resourceType string, name string, decoder *yaml.Decoder) (ToolConfig, error) {
factory, found := toolRegistry[resourceType]
if !found {
return nil, fmt.Errorf("%w: %q", ErrUnknownToolType, resourceType)
}
toolConfig, err := factory(ctx, name, decoder)
if err != nil {
return nil, fmt.Errorf("unable to parse tool %q as type %q: %w", name, resourceType, err)
}
return toolConfig, nil
}
type ToolConfig interface {
ToolConfigType() string
Initialize(context.Context) (Tool, error)
}
// https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations
type ToolAnnotations struct {
DestructiveHint *bool `json:"destructiveHint,omitempty" yaml:"destructiveHint,omitempty"`
IdempotentHint *bool `json:"idempotentHint,omitempty" yaml:"idempotentHint,omitempty"`
OpenWorldHint *bool `json:"openWorldHint,omitempty" yaml:"openWorldHint,omitempty"`
ReadOnlyHint *bool `json:"readOnlyHint,omitempty" yaml:"readOnlyHint,omitempty"`
}
// NewReadOnlyAnnotations creates default annotations for a read-only tool.View on GitHub (pinned to 8cc6e09de2)
Solutions
- Read the wrapped cause at the end of the error chain for the underlying problem (e.g. "description is required for tool \"x\"")
- Fix the offending field in the named tool's YAML block
- Validate required fields for the tool type per its documentation
- Run the config through a YAML linter to catch structural issues
Example fix
// before (tools.yaml) my-tool: kind: trino-execute-sql source: my-trino // after my-tool: kind: trino-execute-sql source: my-trino description: Runs a SQL query against Trino
Defensive patterns
Strategy: validation
Validate before calling
// Before parsing, check required fields for each tool block
for name, t := range toolsRaw {
if t["description"] == "" {
return fmt.Errorf("tool %q: description is required", name)
}
} Try / catch
toolConfig, err := tools.DecodeConfig(ctx, kind, name, dec)
if err != nil {
var pe *fmt.WrapError // or inspect the chain
log.Printf("tool %q (kind %q) rejected: %v", name, kind, err)
return fmt.Errorf("config error in tool %q: %w", name, err)
} Prevention
- Always include description for every tool in tools.yaml
- Validate the full config with a dry-run/decode before deploying
- Keep tool YAML blocks minimal and copied from docs
- Read the whole error chain, not just the wrapper message
When it happens
Trigger: Any registered factory (e.g. trinoexecutesql's Config.Initialize reached through the YAML decoder) returns an error — bad fields, missing required values like description, invalid parameter definitions — while decoding a tool named <name> as type <resourceType>.
Common situations: Missing required fields (e.g. `description`), malformed parameter definitions, invalid YAML structure inside the tool block, source names that fail validation during Initialize.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- description is required for tool %q
- description is required for tool %q
- description is required for tool %q
- unknown tool type
- %w: %q
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/9bd1da9eee13d8d5.
Report an issue: GitHub.