Skip to content

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Jan 14, 2026

Problem

MCP servers can define tool schemas with anyOf, oneOf, or allOf at the top level. When these schemas are passed to OpenRouter with Anthropic models, the API rejects them with:

ApiProviderError: tools.19.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level

PostHog Issue: https://us.posthog.com/error_tracking/019bb5ab-be91-7160-8060-06f185ee5fcb

Solution

Extended normalizeToolSchema() in src/utils/json-schema.ts to flatten top-level schema composition keywords before sending to providers.

Changes:

  1. Added flattenTopLevelComposition() function that:

    • Detects schemas with anyOf, oneOf, or allOf at the top level
    • Extracts the first object-type variant from the composition
    • Merges it with any top-level metadata (like description, $schema)
    • Falls back to a generic { type: "object", additionalProperties: false } if no object variant exists
  2. Updated tests in src/utils/__tests__/json-schema.spec.ts

Impact

The model sees a slightly simplified schema (just the object type, not "object OR null"). In practice, most MCP tools expect object inputs anyway, so the model's generated calls remain valid. The MCP server performs its own validation regardless of what schema we send to the LLM.

Testing

All 5242 tests pass.

Closes COM-485


Important

Flatten top-level anyOf, oneOf, allOf in MCP tool schemas for provider compatibility in normalizeToolSchema().

  • Behavior:
    • normalizeToolSchema() in json-schema.ts now flattens top-level anyOf, oneOf, allOf to a single object schema using flattenTopLevelComposition().
    • Falls back to { type: "object", additionalProperties: false } if no object variant exists.
  • Tests:
    • Added tests in json-schema.spec.ts to verify flattening of top-level schema composition keywords.
    • Ensures nested anyOf remains unchanged.
  • Misc:
    • Updated comments and documentation in json-schema.ts to reflect new functionality.

This description was created by Ellipsis for 6476e00. You can customize this summary. It will automatically update as commits are pushed.

MCP servers can define tool schemas with anyOf, oneOf, or allOf at the top level.
When passed to OpenRouter/Claude, the API rejects them with:
'input_schema does not support oneOf, allOf, or anyOf at the top level'

This extends normalizeToolSchema() to flatten top-level composition keywords:
- Extracts the first object-type variant from the composition
- Merges with top-level metadata (description, $schema)
- Falls back to generic object schema if no object variant exists

Closes COM-485
@daniel-lxs daniel-lxs requested review from cte, jr and mrubens as code owners January 14, 2026 16:52
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. bug Something isn't working labels Jan 14, 2026
@roomote
Copy link
Contributor

roomote bot commented Jan 14, 2026

Rooviewer Clock   See task on Roo Cloud

Review complete. No issues found.

The implementation correctly flattens top-level anyOf/oneOf/allOf schemas for OpenRouter/Claude provider compatibility. The code is well-tested with comprehensive coverage of edge cases.

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

2 participants