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
- Shape the request as { name: "browser_open", arguments: { ... } } inside params.
- Use a compliant MCP client SDK rather than hand-building JSON-RPC payloads.
- 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
- Use an MCP client SDK
- Always nest arguments under 'arguments'
- Unit-test request shaping against the JSON schema
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
- MCP request failed (${this.server.name}): ${String(response.
- The CCR artifact endpoint returned a non-media content type.
- The CCR media artifact exceeds the inline preview size limit
- Compressed CCR media artifacts are not accepted for inline p
- The CCR artifact response was empty.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/bc98f33df66a38b8.
Report an issue: GitHub.