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 checks that the source wired to this alloydb-list-clusters tool satisfies the compatibleSource interface (GetDefaultProject, UseClientAuthorization, ListCluster). If the configured source does not implement that interface, the tool cannot talk to the AlloyDB Admin API and this error is returned at config-validation time. It is a wiring/compatibility guard, not a runtime failure.

Source

Thrown at internal/tools/alloydb/alloydblistclusters/alloydblistclusters.go:100

}

// Tool represents the list-clusters 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
}

// buildParams builds the tool's parameters. A non-empty project means the source has a
// configured default project, which is baked into the project param; otherwise the plain form is used.
func buildParams(project string) parameters.Parameters {
	projectParam := parameters.NewStringParameter("project", "The GCP project ID to list clusters for.")
	if project != "" {
		projectParam = parameters.NewStringParameter("project", "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", parameters.WithStringDefault(project))
	}
	return parameters.Parameters{
		projectParam,
		parameters.NewStringParameter("location", "Optional: The location to list clusters in (e.g., 'us-central1'). Use '-' to list clusters across all locations.(Default: '-')", parameters.WithStringDefault("-")),
	}
}

// resolveParams builds the tool's parameters using the source's configured

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check the tool's 'source' field in tools.yaml and point it at an alloydb source
  2. Verify the referenced source's kind is alloydb (implements GetDefaultProject/UseClientAuthorization/ListCluster)
  3. Run the toolbox config validation at startup and fix the reported tool-source pairing before deploying

Example fix

// before (tools.yaml)
tools:
  list-clusters:
    kind: alloydb-list-clusters
    source: my-postgres
// after
tools:
  list-clusters:
    kind: alloydb-list-clusters
    source: my-alloydb
Defensive patterns

Strategy: validation

Validate before calling

if _, ok := source.(alloydblistclusterscompatibleSource); !ok {
    return fmt.Errorf("tool %s requires an alloydb-compatible source; got %T", toolName, source)
}

Type guard

func isAlloyDBSource(s sources.Source) bool {
    _, ok := s.(interface {
        GetDefaultProject() string
        UseClientAuthorization() bool
        ListCluster(context.Context, string, string, string) (any, error)
    })
    return ok
}

Prevention

When it happens

Trigger: Calling ValidateSource (directly or via server startup validation) with a sources.Source that is not the alloydb source (or another type implementing compatibleSource), e.g. a postgres or http source attached to this tool in tools.yaml.

Common situations: Misconfigured tools.yaml binding the tool to the wrong source name; copy-pasting a tool block across source kinds; renaming a source so the tool falls back to an unintended one; using a source that lacks a GCP project default.

Related errors


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