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

Tool.ValidateSource checks that the configured source implements the lookerlistagents compatibleSource interface before the tool runs. If the sources.Source value passed in does not satisfy the interface (it is not the looker source), validation fails with this error and the tool refuses to execute. It is an upfront guard so Invoke never operates on an incompatible backend.

Source

Thrown at internal/tools/looker/lookerlistagents/lookerlistagents.go:111

// 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)
	}

	sdk, err := source.GetLookerSDK(ctx, string(accessToken))
	if err != nil {
		return nil, util.NewClientServerError(fmt.Sprintf("error getting sdk: %v", err), http.StatusInternalServerError, err)
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Bind the tool to a source whose kind is 'looker' in the YAML config.
  2. Check startup logs that the named source initialized as a looker source.
  3. For custom sources, implement the compatibleSource methods.
  4. Compare the source name in the tool config against the sources section for typos.

Example fix

// before (tools.yaml)
sources:
  pg: { kind: postgres, ... }
tools:
  list-agents: { kind: looker-list-agents, source: pg }

// after
sources:
  looker-prod: { kind: looker, baseUrl: https://looker.example.com, ... }
tools:
  list-agents: { kind: looker-list-agents, source: looker-prod }
Defensive patterns

Strategy: type-guard

Validate before calling

if err := tool.ValidateSource(src); err != nil {
    return fmt.Errorf("startup validation failed: %w", err)
}

Type guard

func validateLookerSource(s sources.Source) error {
    if _, ok := s.(*lookersrc.Source); !ok {
        return fmt.Errorf("expected looker source, got %T", s)
    }
    return nil
}

Try / catch

if err := tool.ValidateSource(src); err != nil {
    log.Fatalf("looker-list-agents bound to incompatible source: %v", err)
}

Prevention

When it happens

Trigger: The server validates the tool's source binding at startup or per-request and finds a concrete source type that is not *sources/looker.Source — e.g. tools.yaml binds looker-list-agents to a postgres/http source, or a custom source lacks the compatibleSource methods.

Common situations: Wrong source name in tools.yaml after refactoring; multiple environments (dev/prod) with different source sets; registering a custom source that implements sources.Source but not UseClientAuthorization/GetAuthTokenHeaderName.

Related errors


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