Skip to content

MCP: tool inputSchema includes $schema field, causing Anthropic API 400 errors #40043

@xuanyunhui

Description

@xuanyunhui

Bug Description

The Playwright MCP server's toMcpTool function generates tool inputSchema that includes a top-level "$schema": "https://json-schema.org/draft/2020-12/schema" field. This causes Anthropic API to reject all tool calls with a 400 error.

Root Cause

In packages/playwright-core/src/tools/utils/mcp/tool.ts, the toMcpTool function calls zod.toJSONSchema() without stripping the $schema field:

export function toMcpTool(tool: ToolSchema<any>): mcpServer.Tool {
  return {
    name: tool.name,
    description: tool.description,
    inputSchema: zod.toJSONSchema(tool.inputSchema) as mcpServer.Tool['inputSchema'],
  };
}

Zod v4's toJSONSchema() automatically adds "$schema": "https://json-schema.org/draft/2020-12/schema" to the output. While this is valid JSON Schema, the MCP protocol's tool.inputSchema is a JSON Schema subset and should not include the top-level $schema declaration.

Impact

  • Anthropic API returns: 400 API Error: "tools.N.custom.input_schema: JSON schema is invalid"
  • One invalid tool schema breaks ALL tool calls in the session, not just the affected tool
  • Affects users connecting via mcp-remote, Claude Code, Claude Desktop, or any client that forwards schemas to Anthropic API

Suggested Fix

export function toMcpTool(tool: ToolSchema<any>): mcpServer.Tool {
  const jsonSchema = zod.toJSONSchema(tool.inputSchema);
  delete jsonSchema.$schema;
  return {
    name: tool.name,
    description: tool.description,
    inputSchema: jsonSchema as mcpServer.Tool['inputSchema'],
  };
}

Per the MCP specification, inputSchema defaults to JSON Schema 2020-12 when $schema is omitted. Removing the field is both safe and compliant.

Environment

  • Playwright version: latest (Zod v4.3.6 bundled)
  • MCP client: Claude Code / Claude Desktop via mcp-remote

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions