googleapis/mcp-toolbox · error

invalid source for %q tool: source %q is not a compatible ty

Error message

invalid source for %q tool: source %q is not a compatible type

What it means

ValidateSource of looker-get-dashboard fails when the supplied sources.Source does not implement the tool's compatibleSource interface (UseClientAuthorization, GetAuthTokenHeaderName, LookerApiSettings). Only Looker sources do, so the error indicates the tool is bound to an incompatible source type.

Source

Thrown at internal/tools/looker/lookergetdashboard/lookergetdashboard.go:107

// validate interface
var _ tools.Tool = Tool{}

type Tool struct {
	tools.BaseTool[Config]
}

func (t Tool) GetSourceName() string {
	return t.Cfg.Source
}

func (t Tool) ToConfig() tools.ToolConfig {
	return t.Cfg
}

func (t Tool) ValidateSource(source sources.Source) error {
	_, ok := source.(compatibleSource)
	if !ok {
		return fmt.Errorf("invalid source for %q tool: source %q is not a compatible type", t.Cfg.Type, t.Cfg.Source)
	}
	return nil
}

func (t Tool) Invoke(ctx context.Context, s sources.Source, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
	source, ok := s.(compatibleSource)
	if !ok {
		return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, nil)
	}

	logger, err := util.LoggerFromContext(ctx)
	if err != nil {
		return nil, util.NewClientServerError("unable to get logger from ctx", http.StatusInternalServerError, err)
	}
	logger.DebugContext(ctx, "params = ", params)
	paramsMap := params.AsMap()

	dashboardId, ok := paramsMap["dashboard_id"].(string)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Bind looker-get-dashboard to a Looker source (kind: looker).
  2. Implement the complete compatibleSource interface on any custom source.
  3. Adopt the prebuilt Looker config to avoid tool/source mismatches.
  4. After upgrades, satisfy any newly added interface methods (the compiler reports them).

Example fix

# before
tools:
  dashboard:
    kind: looker-get-dashboard
    source: alloydb-src
# after
sources:
  looker-src: { kind: looker, ... }
tools:
  dashboard:
    kind: looker-get-dashboard
    source: looker-src
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := src.(lookergetdashboard.CompatibleSource); !ok {
    return fmt.Errorf("looker-get-dashboard requires a looker source; got %T", src)
}

Type guard

func isCompatibleLooker(s sources.Source) bool {
    _, ok := s.(interface {
        UseClientAuthorization() bool
        GetAuthTokenHeaderName() string
        LookerApiSettings() *rtl.ApiSettings
    })
    return ok
}

Try / catch

if err := tool.ValidateSource(src); err != nil {
    log.Fatalf("tool/source mismatch at startup: %v", err)
}

Prevention

When it happens

Trigger: Server startup/registration calls ValidateSource with a non-Looker source attached to looker-get-dashboard; a test stub implementing only sources.Source is passed in.

Common situations: tools.yaml wiring the dashboard tool to a database source; copy-paste or renamed source entries; custom sources lacking the Looker methods; interface changes after upgrading the toolbox.

Related errors


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