musistudio/claude-code-router · error · Error

tools/call params must include a tool name.

Error message

tools/call params must include a tool name.

What it means

A JSON-RPC parameter-validation error from the browser automation MCP server's tools/call handler. The MCP spec requires params to be an object with a string 'name' field; this guard fires when params is not a record or name is missing/non-string before any tool dispatch happens.

Source

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

            }
          });
        case "ping":
          return jsonRpcResult(id, {});
        case "tools/list":
          return jsonRpcResult(id, { tools: browserAutomationTools as unknown as JsonValue });
        case "tools/call":
          return jsonRpcResult(id, await this.callTool(request.params) as unknown as JsonValue);
        default:
          return jsonRpcError(id, -32601, `Unsupported MCP method: ${request.method}`);
      }
    } catch (error) {
      return jsonRpcError(id, -32603, formatError(error));
    }
  }

  private async callTool(params: unknown): Promise<ToolCallResult> {
    if (!isRecord(params) || typeof params.name !== "string") {
      throw new Error("tools/call params must include a tool name.");
    }
    const args = isRecord(params.arguments) ? params.arguments : {};
    try {
      const result = await this.runTool(params.name, args);
      return textResult(formatToolResult(params.name, result));
    } catch (error) {
      return {
        ...textResult(formatError(error)),
        isError: true
      };
    }
  }

  private async runTool(name: string, args: Record<string, unknown>): Promise<unknown> {
    switch (name) {
      case "browser_session_open":
        return await this.openSession(args);
      case "browser_session_close":

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Shape the request as { name: "browser_open", arguments: { ... } } inside params.
  2. Use a compliant MCP client SDK rather than hand-building JSON-RPC payloads.
  3. Log the outgoing params object to confirm name is a non-empty string.

Example fix

// before
await mcp.request("tools/call", { tool: "browser_open", args: {} });

// after
await mcp.request("tools/call", { name: "browser_open", arguments: {} });
Defensive patterns

Strategy: validation

Validate before calling

if (!params || typeof params !== "object" || typeof params.name !== "string") throw new Error("Invalid tools/call params");
await transport.send({ jsonrpc: "2.0", id, method: "tools/call", params: { name: params.name, arguments: params.arguments ?? {} } });

Type guard

function isToolsCallParams(p: unknown): p is { name: string; arguments?: Record<string, unknown> } { return typeof p === "object" && p !== null && typeof (p as any).name === "string"; }

Try / catch

try { await mcp.callTool(name, args); } catch (e) { if (e instanceof Error && e.message.includes("must include a tool name")) { /* reshape params to { name, arguments } */ } throw e; }

Prevention

When it happens

Trigger: Sending a JSON-RPC tools/call request where params is null, an array, or an object lacking a string 'name' property — e.g. { method: 'tools/call', params: { arguments: {...} } }.

Common situations: An MCP client sends tool arguments at the top level instead of nested under name/arguments; a hand-rolled JSON-RPC client omits the name field; a serialization bug turns the params object into an array.

Related errors


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