fix(ci): avoid top-level oneOf in get_ci_catalog_resource input_schema (Fixes #550)#551
Open
zch0227 wants to merge 1 commit into
Open
fix(ci): avoid top-level oneOf in get_ci_catalog_resource input_schema (Fixes #550)#551zch0227 wants to merge 1 commit into
zch0227 wants to merge 1 commit into
Conversation
GetCiCatalogResourceSchema was a z.union([...]), which zod-to-json-schema serializes into JSON Schema with `oneOf` at the root of the tool's input_schema. The Anthropic Messages API (used by Claude Code, Kiro, and other MCP clients) rejects any tool whose input_schema has oneOf/allOf/anyOf at the top level: input_schema does not support oneOf, allOf, or anyOf at the top level Because every enabled tool is sent on every request, this single tool breaks the whole MCP server for affected clients once it appears in the tool list (the reported index moves around as users toggle other tools). Flatten the union into a single z.object(...).refine(...): id and full_path are both optional at the schema level, and the "exactly one of" constraint is enforced at runtime via .refine(). The generated input_schema now has `type: "object"` at the root with no oneOf, while keeping identical runtime validation. Fixes zereight#550
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📜 Recent review details🔇 Additional comments (1)
📝 WalkthroughSummary by CodeRabbit
Walkthrough
ChangesGetCiCatalogResourceSchema: remove top-level oneOf
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
get_ci_catalog_resource'sinput_schemahasoneOfat the top level, which the Anthropic Messages API (Claude Code, Kiro, and other MCP clients) rejects:This is reported in #550. Because every enabled tool is serialized on every request, this single tool breaks the entire MCP server for affected clients once it appears in the tool list — the reported tool index (
tools.78,tools.62, …) just moves around as users toggle other tools. Current workaround is pinning to2.1.25(before #537 added the CI catalog tools).Root cause
GetCiCatalogResourceSchemais az.union([...]):zod-to-json-schemaserializes a top-level union into{ "oneOf": [...] }at the root ofinput_schema— exactly what Anthropic forbids.Fix
Flatten the union into a single
z.object(...).refine(...).idandfull_pathare both optional at the schema level; the "exactly one of" constraint is still enforced at runtime via.refine():Generated
input_schemanow hastype: "object"at the root with nooneOf, while runtime validation is unchanged.Verification
tsccompiles clean.['type', 'properties', 'additionalProperties'],type: "object",oneOf/anyOf/allOfallundefined..refine()behavior unchanged:{ id }→ valid ✅{ full_path }→ valid ✅{}(neither) → rejected ✅{ id, full_path }(both) → rejected ✅Fixes #550