You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Anthropic rejects a tool input_schema that uses anyOf/oneOf/allOf at the root level — these combinators are only accepted nested inside properties. MCP servers commonly emit "exactly one of these fields" patterns (e.g. anyOf: [{required:["route"]}, {required:["file"]}]) as root-level combinators, which then fail Anthropic validation and take the whole tool down with a 400.
OpenCode has an existing OpenAI sanitizer (#32489) but nothing equivalent for the Anthropic family.
Use it with an Anthropic model (or Copilot proxying Claude, or Vertex Anthropic).
Expected behavior
Tool continues to work; the schema is folded into the root object so Anthropic accepts it.
Actual behavior
The request fails with an Anthropic validation error and the tool is unusable.
Fix
fix(opencode): sanitize MCP tool schemas for Anthropic root combinators (#47542) adds a targeted sanitizer that folds root-level combinators into the root object schema while preserving nested content verbatim.
This problem also occurs on OpenCode 2. I examined 2.1.3 and dev at 17b79f4e0c.
The problem is not only for MCP tools. A plugin tool that a plugin adds with ctx.tool.transform and a Zod discriminatedUnion input causes the same failure. When the tool list contains one such tool, all requests to an Anthropic model stop with this error before the model runs:
tools.26.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level
Cause on dev:
packages/core/src/tool/runtime.ts:157-172 changes a Zod input to JSON Schema with toJSONSchema(schema, { target: "draft-2020-12", io }). A discriminatedUnion gives a root anyOf and no root type.
objectRoot in packages/ai/src/protocols/utils/tool-schema.ts:57-72 adds type: "object" but keeps the root anyOf. It removes anyOf only for the empty-struct marker (lines 66-70).
modelCompatibility (lines 78-90) applies a sanitizer only for Gemini and Moonshot.
packages/ai/src/protocols/anthropic-messages.ts:550 sends input_schema: tool.inputSchema with no change.
Minimal check with the same objectRoot code as dev:
A plugin author can prevent the error with an object root. An MCP server cannot change its schema for one provider. Two possible repairs are an Anthropic sanitizer for the root, or an error at tool registration that names the tool.
Thanks for the report. I reproduced this on v2.2.0 (the latest release; the issue doesn't name a version), and it still happens on the latest dev (b6c43a5).
Steps:
A stdio MCP server exposes one tool whose inputSchema has a root-level anyOf: [{required:["route"]},{required:["file"]}]. The server is configured with codemode: false, so the tool goes on the native tool list.
anthropic is pointed at a local mock of the Messages API through settings.baseURL. The mock applies Anthropic's top-level combinator rule.
Running opencode run -m anthropic/claude-sonnet-4-5 "reply only: ok" sends the tool's schema to Anthropic unchanged, root anyOf included, and the run fails with:
tools.5.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level
The script below reproduces it end to end. I had no real Anthropic account, so the 400 comes from the mock. What I saw directly is that OpenCode forwards the root combinator as is on the Anthropic path; the error is the one reported in #46628, #37916 and #35516.
In the meantime, leaving codemode at its default (Code Mode) avoids the error. The MCP tools are then reached through execute, and their schemas aren't sent to Anthropic directly.
Activity
github-actions commentedon Sep 5, 2026
This issue might be a duplicate of existing issues. Please check:
iceteaSA commentedon Oct 24, 2026
This problem also occurs on OpenCode 2. I examined 2.1.3 and
devat17b79f4e0c.The problem is not only for MCP tools. A plugin tool that a plugin adds with
ctx.tool.transformand a ZoddiscriminatedUnioninput causes the same failure. When the tool list contains one such tool, all requests to an Anthropic model stop with this error before the model runs:Cause on
dev:packages/core/src/tool/runtime.ts:157-172changes a Zod input to JSON Schema withtoJSONSchema(schema, { target: "draft-2020-12", io }). AdiscriminatedUniongives a rootanyOfand no roottype.objectRootinpackages/ai/src/protocols/utils/tool-schema.ts:57-72addstype: "object"but keeps the rootanyOf. It removesanyOfonly for the empty-struct marker (lines 66-70).modelCompatibility(lines 78-90) applies a sanitizer only for Gemini and Moonshot.packages/ai/src/protocols/anthropic-messages.ts:550sendsinput_schema: tool.inputSchemawith no change.Minimal check with the same
objectRootcode asdev:A plugin author can prevent the error with an object root. An MCP server cannot change its schema for one provider. Two possible repairs are an Anthropic sanitizer for the root, or an error at tool registration that names the tool.
opencodejr commentedon Oct 28, 2026
Thanks for the report. I reproduced this on v2.2.0 (the latest release; the issue doesn't name a version), and it still happens on the latest
dev(b6c43a5).Steps:
inputSchemahas a root-levelanyOf: [{required:["route"]},{required:["file"]}]. The server is configured withcodemode: false, so the tool goes on the native tool list.anthropicis pointed at a local mock of the Messages API throughsettings.baseURL. The mock applies Anthropic's top-level combinator rule.opencode run -m anthropic/claude-sonnet-4-5 "reply only: ok"sends the tool's schema to Anthropic unchanged, rootanyOfincluded, and the run fails with:The script below reproduces it end to end. I had no real Anthropic account, so the 400 comes from the mock. What I saw directly is that OpenCode forwards the root combinator as is on the Anthropic path; the error is the one reported in #46628, #37916 and #35516.
In the meantime, leaving
codemodeat its default (Code Mode) avoids the error. The MCP tools are then reached throughexecute, and their schemas aren't sent to Anthropic directly.Related (all v1 and closed):
Reproduction script (repro.sh)
Run it:
bash repro.sh