googleapis/mcp-toolbox · error
INVALID_PARAMS
INVALID_PARAMS
Error message
invalid tool name: tool with name %q does not exist
What it means
toolsCallHandler first verifies that the requested tool belongs to the currently served group via g.ContainsTool(toolName). This INVALID_PARAMS error tells the client the tool name it invoked is not exposed in this server/group — the client-side equivalent of a 404 for tools.
Source
Thrown at internal/server/mcp/v20250326/method.go:171
err = fmt.Errorf("invalid mcp tools call request: %w", err)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
toolName := req.Params.Name
toolArgument := req.Params.Arguments
logger.DebugContext(ctx, fmt.Sprintf("tool name: %s", toolName))
// Update span name and set gen_ai attributes
span := trace.SpanFromContext(ctx)
span.SetName(fmt.Sprintf("%s %s", TOOLS_CALL, toolName))
span.SetAttributes(
attribute.String("gen_ai.tool.name", toolName),
attribute.String("gen_ai.operation.name", "execute_tool"),
)
// Verify tool belongs to the current group before resolving globally.
if !g.ContainsTool(toolName) {
err = fmt.Errorf("invalid tool name: tool with name %q does not exist", toolName)
return jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, err.Error(), nil), err
}
tool, ok := primitiveMgr.GetTool(toolName)
if !ok {
err = fmt.Errorf("invalid tool name: tool with name %q does not exist", toolName)
return jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, err.Error(), nil), err
}
if tool.HasSecureParams() {
err = fmt.Errorf("invalid tool name: tool with name %q does not exist", toolName)
return jsonrpc.NewError(id, jsonrpc.INVALID_PARAMS, err.Error(), nil), err
}
srcName := tool.GetSourceName()
var src sources.Source
if srcName != "" {
src, ok = primitiveMgr.GetSource(srcName)View on GitHub (pinned to 8cc6e09de2)
Solutions
- Call tools/list on this server and use an exact tool name from the response
- Update hardcoded tool names to match the server's current config (renames happen between versions)
- Verify the client connects to the intended server/endpoint serving that tool
- Handle the INVALID_PARAMS response in the client by refreshing its tool cache
Example fix
// before
client.CallTool("postgres-execute-sql", args) // renamed tool
// after: refresh from tools/list
name := "execute-sql" // exact name returned by tools/list
client.CallTool(name, args) Defensive patterns
Strategy: validation
Validate before calling
const tools = await client.listTools()
if (!tools.some(t => t.name === toolName)) {
throw new Error(`tool "${toolName}" not exposed by this server`)
} Type guard
function isKnownTool(tools: Tool[], name: string): boolean {
return tools.some(t => t.name === name)
} Try / catch
try {
return await client.callTool({ name: toolName, arguments: args })
} catch (e) {
if (e.code === -32602) { // INVALID_PARAMS: unknown tool
await refreshToolCache()
throw new Error(`tool "${toolName}" unavailable; refreshed tool list`)
}
throw e
} Prevention
- Always discover tool names via tools/list instead of hardcoding them
- Refresh the tool cache on INVALID_PARAMS and after server config changes
- Verify you are connected to the server/endpoint that serves the tool
When it happens
Trigger: A tools/call request whose params.name is not in group g's tool set (or isn't registered at all in the PrimitiveManager), while handling tools/call.
Common situations: Client caches a tools/list from a different server/config; tool renamed or removed after a config change; client hardcodes tool names; URL path/group mismatch serving a subset of tools.
Related errors
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/799dccee483d5fd3.
Report an issue: GitHub.