googleapis/mcp-toolbox · error

unable to initialize tool %q: %w

Error message

unable to initialize tool %q: %w

What it means

initializeTools iterates cfg.ToolConfigs and calls each tool's ToolConfig.Initialize(ctx). Any failure inside a tool's own initialization (invalid parameters schema, unsupported tool type, source client construction, statement parsing) is wrapped with the tool's config name so the developer knows which tool entry broke server startup.

Source

Thrown at internal/server/server.go:288

	return toolsMap, groupsMap, nil
}

// initializeTools initializes and validates the tools from the config.
func initializeTools(ctx context.Context, cfg ServerConfig, sourcesMap map[string]sources.Source, instrumentation *telemetry.Instrumentation, l log.Logger) (map[string]tools.Tool, error) {
	toolsMap := make(map[string]tools.Tool)
	for name, tc := range cfg.ToolConfigs {
		var src sources.Source
		t, err := func() (tools.Tool, error) {
			_, span := instrumentation.Tracer.Start(
				ctx,
				"toolbox/server/tool/init",
				trace.WithAttributes(attribute.String("tool_type", tc.ToolConfigType())),
				trace.WithAttributes(attribute.String("tool_name", name)),
			)
			defer span.End()
			t, err := tc.Initialize(ctx)
			if err != nil {
				return nil, fmt.Errorf("unable to initialize tool %q: %w", name, err)
			}

			if srcName := t.GetSourceName(); srcName != "" && sourcesMap != nil {
				var ok bool
				src, ok = sourcesMap[srcName]
				if !ok && !cfg.SkipSourceValidation {
					return nil, fmt.Errorf("unable to retrieve source %q for tool %q", srcName, name)
				}
			}

			if !cfg.SkipSourceValidation {
				err = t.ValidateSource(src)
				if err != nil {
					return nil, err
				}
			}
			return t, nil
		}()

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the wrapped cause: it names the failing tool and the underlying reason; fix that tool's config.
  2. Validate the tool's YAML against the docs for its kind (field names and required fields change between versions).
  3. Run `toolbox` in dev mode or a unit test with only that one tool defined to isolate the failure.
  4. Check the release notes if the config was working before an upgrade — tool kinds/fields may have changed.

Example fix

// before
my_tool:
  kind: postgres-sql
  source: my-db
  statment: "SELECT 1"

// after (typo fixed)
my_tool:
  kind: postgres-sql
  source: my-db
  statement: "SELECT 1"
Defensive patterns

Strategy: validation

Validate before calling

// Dry-run each tool config before serving
for name, tc := range cfg.ToolConfigs {
    if _, err := tc.Initialize(ctx); err != nil {
        return fmt.Errorf("tool %q fails init: %w", name, err)
    }
}

Try / catch

if _, err := server.NewServer(ctx, cfg); err != nil {
    var toolName string
    if n, e := fmt.Sscanf(err.Error(), "unable to initialize tool %q", &toolName); n == 1 && e == nil {
        log.Printf("offending tool: %s, cause: %v", toolName, errors.Unwrap(err))
    }
    return err
}

Prevention

When it happens

Trigger: Server startup (InitializeConfigs/NewServer) or InitializeOfflineConfigs where any entry in cfg.ToolConfigs fails tc.Initialize(ctx) — e.g. a bad SQL statement template, missing required tool field, or a tool referencing an auth service that fails to build.

Common situations: Typos in tool config fields after upgrading toolbox versions (schema changes), invalid statement templates with mismatched parameters, or a tool kind whose Initialize requires network/resources unavailable at startup.

Related errors


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