musistudio/claude-code-router · error · Error

Unknown browser automation tool: ${name}

Error message

Unknown browser automation tool: ${name}

What it means

Thrown by runTool's switch default branch when the tools/call name does not match any implemented browser automation tool. The MCP server dispatches on a fixed set of tool names; anything else reaches the default case and is rejected rather than silently ignored.

Source

Thrown at packages/electron/src/main/browser-automation-mcp.ts:1094

          {
            deltaX: readNumber(args.deltaX) ?? 0,
            deltaY: readNumber(args.deltaY) ?? 700
          }
        );
      case "browser_wait_for":
        await this.ensureBrowserOpen();
        return await waitForPageCondition(
          builtInBrowserService.getAutomationWebContents(readString(args.tabId)),
          {
            selector: readString(args.selector),
            text: readString(args.text),
            timeoutMs: clampInteger(readNumber(args.timeoutMs) ?? defaultWaitTimeoutMs, 100, 120000),
            urlIncludes: readString(args.urlIncludes),
            urlMatches: readString(args.urlMatches)
          }
        );
      default:
        throw new Error(`Unknown browser automation tool: ${name}`);
    }
  }

  private async ensureBrowserOpen(): Promise<BuiltInBrowserState> {
    await builtInBrowserService.openHidden(await loadAppConfig());
    return builtInBrowserService.getAutomationState();
  }

  private async ensureBrowserVisible(): Promise<BuiltInBrowserState> {
    await builtInBrowserService.open(await loadAppConfig());
    return builtInBrowserService.getAutomationState();
  }

  private async openSession(args: Record<string, unknown>): Promise<unknown> {
    let state = await this.ensureBrowserOpen();
    const url = readString(args.url);
    const requestedTabId = readString(args.tabId);
    const previousActiveTabId = state.activeTabId;

View on GitHub (pinned to 99f24806c6)

Solutions

  1. List available tools first via the MCP tools/list method and use an exact name from the result.
  2. Check for typos and the exact tool naming (browser_ prefix, snake_case).
  3. Align client and server versions so advertised tools match implemented ones.

Example fix

// before
await call("browser_tab_activte", { tabId });

// after
const tools = await listTools();
await call("browser_tab_activate", { tabId });
Defensive patterns

Strategy: validation

Validate before calling

const { tools } = await mcp.listTools();
const known = new Set(tools.map((t) => t.name));
if (!known.has(name)) throw new Error(`Unknown tool ${name}; available: ${[...known].join(", ")}`);
await call(name, args);

Try / catch

try { await call(name, args); } catch (e) { if (e instanceof Error && e.message.includes("Unknown browser automation tool")) { /* re-list tools, correct name or skip */ } throw e; }

Prevention

When it happens

Trigger: Calling tools/call with a name like 'browser_click', 'navigate_page', or a typo such as 'browser_tab_activte'; also calling a tool that exists in a newer/older server version than the caller targets.

Common situations: Version skew between client tool list and server implementation; LLM-generated tool names that hallucinate plausible-but-nonexistent tools; typos in hand-written automation scripts.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/3de19657d001c298. Report an issue: GitHub.