googleapis/mcp-toolbox · error

INTERNAL_ERROR

INTERNAL_ERROR

Error message

tool does not exist: %s

What it means

GenerateListToolsResult iterates a group's tool names and looks each one up in the PrimitiveManager. If GetTool cannot find a name present in the group this INTERNAL_ERROR is thrown, meaning the group's tool list is out of sync with the registered tools.

Source

Thrown at internal/server/mcp/v20251125/manifests.go:108

		}
		if len(authParamList) > 0 {
			authParam[name] = authParamList
		}
	}
	return InputSchema{
		Type:       "object",
		Properties: properties,
		Required:   required,
	}, authParam
}

// GenerateListToolsResult generates tools/list method result according to mcp schema
func GenerateListToolsResult(pMgr *primitives.PrimitiveManager, g group.Group, urlParams map[string]string) (ListToolsResult, error) {
	mcpManifest := make([]Tool, 0, len(g.ToolNames))
	for _, toolName := range g.ToolNames {
		tool, ok := pMgr.GetTool(toolName)
		if !ok {
			return ListToolsResult{}, fmt.Errorf("tool does not exist: %s", toolName)
		}
		// Skip a Tool that requires secure params as they are not supported in this protocol version.
		if tool.HasSecureParams() {
			continue
		}
		srcName := tool.GetSourceName()
		var src sources.Source
		if srcName != "" {
			src, ok = pMgr.GetSource(srcName)
			if !ok {
				return ListToolsResult{}, fmt.Errorf("unable to retrieve %s source for tool %q", srcName, tool.GetName())
			}
		}
		params, err := tool.GetParameters(src)
		if err != nil {
			return ListToolsResult{}, fmt.Errorf("error getting parameters for tool %q: %w", toolName, err)
		}
		toolManifest := generateToolManifest(toolName, tool.GetDescription(), tool.GetAuthRequired(), params, tool.GetAnnotations(src), urlParams)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check server startup logs for tool initialization failures for the named tool and fix its config (source, statement, parameters).
  2. Ensure every tool name in the group is registered via the PrimitiveManager before serving tools/list.
  3. Validate the toolbox YAML: every tool must have a valid, initialized source.
  4. If building groups programmatically, only append names that pMgr.GetTool() can resolve.

Example fix

// before: group references a tool that failed to init
// tools.yaml references tool 'query_users' whose source 'db' does not exist
// after: fix the source so the tool registers
sources:
  db:
    kind: postgres
    uri: ${POSTGRES_URI}
tools:
  query_users:
    source: db
    description: List users
Defensive patterns

Strategy: validation

Validate before calling

// Server-side preflight: every tool name in the group must resolve
for _, name := range g.ToolNames {
    if _, ok := pMgr.GetTool(name); !ok {
        return fmt.Errorf("group references unregistered tool: %s", name)
    }
}

Try / catch

try {
  const tools = await mcp.listTools();
} catch (e) {
  if (e.code === -32603 && /tool does not exist/.test(e.message)) {
    // server config is broken; surface which tool and stop retrying
  } else throw e;
}

Prevention

When it happens

Trigger: tools/list is processed while the group.ToolNames slice contains a tool name that is not registered in the PrimitiveManager — e.g. a tool failed to initialize or was removed after the group was built.

Common situations: A tool defined in the YAML config failed initialization (bad source, bad SQL) yet its name remained in the group; custom code constructing a group.Group with hand-added tool names; race between tool deregistration and a tools/list call.

Related errors


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