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
- Check server startup logs for tool initialization failures for the named tool and fix its config (source, statement, parameters).
- Ensure every tool name in the group is registered via the PrimitiveManager before serving tools/list.
- Validate the toolbox YAML: every tool must have a valid, initialized source.
- 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
- Validate the toolbox YAML config at startup so no tool is listed without successful registration.
- Ensure every tool's source exists and initializes before serving traffic.
- Never hand-edit group.Group contents; build groups from the registered manager.
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.