Skip to content

fix: remove top-level anyOf/oneOf/allOf from tool input schemas for Anthropic API compatibility#558

Open
GenNetEng wants to merge 3 commits into
zereight:mainfrom
GenNetEng:main
Open

fix: remove top-level anyOf/oneOf/allOf from tool input schemas for Anthropic API compatibility#558
GenNetEng wants to merge 3 commits into
zereight:mainfrom
GenNetEng:main

Conversation

@GenNetEng

Copy link
Copy Markdown

Summary

Fixes the toJSONSchema() utility to properly flatten and remove top-level anyOf/oneOf/allOf from tool input schemas. The Anthropic API rejects tool definitions that use these JSON Schema constructs at the top level of input_schema, breaking all Anthropic-based MCP clients (Kiro IDE, Claude Code, Claude Desktop, etc.) starting from v2.1.25.

Problem

The existing flattening logic in utils/schema.ts merged anyOf variant properties into a single object but never deleted the anyOf key itself, leaving it in the final output. This caused the Anthropic API to reject the tool list with:

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

Affected tool: get_ci_catalog_resource (uses z.union() for mutually exclusive id/full_path parameters).

Fix

Replaced the incomplete flattening block with a generic handler that loops over all three combiners (anyOf, oneOf, allOf), merges variant properties into a flat object schema, and deletes the combiner key. This runs in the shared toJSONSchema() utility so any future union schemas are handled automatically.

Validation

  • All existing tests pass (including CI catalog tool tests)
  • TypeScript compiles cleanly
  • Verified all 200+ tool schemas produce clean type: "object" output with no top-level combiners

Fixes #552
Fixes #550
test-output.md

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved generated JSON schemas by flattening top-level combined object variants into a single object schema when possible.
    • Expanded compatibility for multiple schema combiners (anyOf, oneOf, and allOf) to produce cleaner, more consistent tool input schemas.
    • More accurate handling of shared required fields across variants, while preserving any existing property keys during the merge.

Walkthrough

toJSONSchema now flattens top-level anyOf, oneOf, and allOf object unions in utils/schema.ts. It merges variant properties, computes shared required fields per combiner, and removes the combiner key when the variants are all object schemas.

Changes

Anthropic-compatible schema flattening

Layer / File(s) Summary
Extend combiner flattening
utils/schema.ts
Extends the top-level schema post-processing pass to handle anyOf, oneOf, and allOf when all variants are object schemas with properties. It sets type to object, merges variant properties into fixedSchema.properties, computes combiner-specific shared required fields, merges them into fixedSchema.required, and deletes the combiner key.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the core change: removing top-level union combiners for Anthropic compatibility.
Description check ✅ Passed The description matches the code change and explains the Anthropic schema compatibility fix.
Linked Issues check ✅ Passed The PR addresses #550 and #552 by flattening top-level combiners in the shared schema utility and deleting them.
Out of Scope Changes check ✅ Passed No unrelated changes are evident; the update stays confined to the schema flattening fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@utils/schema.ts`:
- Around line 112-128: Flattening in the schema normalization logic drops
variant-level required fields because the merge in the combiner loop only copies
variant.properties from fixedSchema[combiner]. Update the flattening path in
utils/schema.ts to also collect and merge each variant’s required array into
fixedSchema.required (deduplicated), alongside the existing property merge,
before deleting the combiner. Keep the change scoped to the object-variant
handling in the combiner loop so inputSchema preserves required args after
flattening.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 366f6d39-7ae7-4ead-8b5f-02bbc0beabed

📥 Commits

Reviewing files that changed from the base of the PR and between 40db3de and 17b8a01.

📒 Files selected for processing (1)
  • utils/schema.ts

Comment thread utils/schema.ts
…e intersection of variant required arrays so only fields required in ALL variants remain globally required after flattening. This correctly handles mutually exclusive unions (e.g., id OR full_path) without erroneously requiring both.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@utils/schema.ts`:
- Around line 127-139: The required-field merge in the allOf handling inside
schema flattening is using an intersection, which is semantically wrong for
allOf. Update the logic around the variants/requiredSets/sharedRequired block in
utils/schema.ts so that fixedSchema.required is built from the union of required
fields across all variants, not the intersection, while still preserving any
existing required entries already on fixedSchema.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 64ca3712-92ef-4491-b0aa-126c73018610

📥 Commits

Reviewing files that changed from the base of the PR and between 17b8a01 and fffa6d7.

📒 Files selected for processing (1)
  • utils/schema.ts

Comment thread utils/schema.ts Outdated
…anyOf/oneOf allOf means all schemas apply simultaneously so all their requirements apply (union). anyOf/oneOf means one schema applies so only shared requirements are universal (intersection).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
utils/schema.ts (1)

121-124: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Dropping duplicate property schemas weakens flattened validation semantics.

When the same property exists in multiple variants, the current “first wins” merge discards later constraints. That is incorrect for flattened combiners: allOf should preserve all constraints, and anyOf/oneOf should preserve alternates. Otherwise the resulting tool schema can misvalidate inputs.

Suggested fix
         for (const variant of variants) {
           for (const [key, value] of Object.entries(variant.properties)) {
-            if (!fixedSchema.properties[key]) {
-              fixedSchema.properties[key] = value;
-            }
+            const existingProp = fixedSchema.properties[key];
+            if (!existingProp) {
+              fixedSchema.properties[key] = value;
+            } else {
+              const nested = combiner;
+              const current = fixedSchema.properties[key];
+              if (current?.[nested] && Array.isArray(current[nested])) {
+                current[nested].push(value);
+              } else {
+                fixedSchema.properties[key] = { [nested]: [current, value] };
+              }
+            }
           }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@utils/schema.ts` around lines 121 - 124, The merge logic in the schema
flattening path is dropping duplicate properties by keeping only the first
variant’s definition, which loses constraints for later variants. Update the
property merge in the schema combiner/flattening code (the loop over
variant.properties in the schema builder) so duplicate keys are not skipped:
preserve all constraints for allOf, and for anyOf/oneOf keep alternate schemas
rather than discarding later ones. Make sure the final fixedSchema.properties
construction reflects the full combinator semantics instead of a “first wins”
merge.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@utils/schema.ts`:
- Around line 121-124: The merge logic in the schema flattening path is dropping
duplicate properties by keeping only the first variant’s definition, which loses
constraints for later variants. Update the property merge in the schema
combiner/flattening code (the loop over variant.properties in the schema
builder) so duplicate keys are not skipped: preserve all constraints for allOf,
and for anyOf/oneOf keep alternate schemas rather than discarding later ones.
Make sure the final fixedSchema.properties construction reflects the full
combinator semantics instead of a “first wins” merge.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1936d42e-3527-47fd-b243-a0dcedf92ce3

📥 Commits

Reviewing files that changed from the base of the PR and between fffa6d7 and 7178142.

📒 Files selected for processing (1)
  • utils/schema.ts

@GenNetEng

Copy link
Copy Markdown
Author

I have also validated in kiro :)

@Duo-Huang

Copy link
Copy Markdown

👋 Any chance this could get merged soon? This is currently blocking all users of Anthropic-based MCP clients (including opencode with GitHub Copilot provider) from using the gitlab-mcp server at all on versions >= 2.1.25. Multiple users hitting this in the wild, thanks for the fix!

@awodij

awodij commented Jun 26, 2026

Copy link
Copy Markdown

@Duo-Huang / other opencode users a workaround until this is merged is to disable this specific tool in opencode.json:

"tools": {
    "gitlab_get_ci_catalog_resource": false
 }

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

Labels

None yet

Projects

None yet

3 participants