-
Notifications
You must be signed in to change notification settings - Fork 5.4k
MCP: tool inputSchema includes $schema field, causing Anthropic API 400 errors #40043
Description
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