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

  1. Call tools/list on this server and use an exact tool name from the response
  2. Update hardcoded tool names to match the server's current config (renames happen between versions)
  3. Verify the client connects to the intended server/endpoint serving that tool
  4. 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

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.