diff --git a/gitnexus/src/mcp/tools.ts b/gitnexus/src/mcp/tools.ts index a34587e5d7..1d634d2063 100644 --- a/gitnexus/src/mcp/tools.ts +++ b/gitnexus/src/mcp/tools.ts @@ -28,12 +28,6 @@ export interface ToolDefinition { } >; required: string[]; - /** - * JSON-Schema `anyOf` for cross-property constraints `required` cannot express - * — e.g. "at least one of route/file". Forwarded verbatim to clients by the - * server's ListTools handler, so MCP clients see the constraint. - */ - anyOf?: Array<{ required: string[] }>; }; } @@ -796,9 +790,6 @@ Response shape is keyed on how many routes match, not on the data: exactly one m repo: { type: 'string', description: 'Repository name or path.' }, }, required: [], - // Exactly one lookup key is needed, but either works (route wins if both - // are passed) — so the structural constraint is "at least one of route/file". - anyOf: [{ required: ['route'] }, { required: ['file'] }], }, }, { diff --git a/gitnexus/test/unit/tools.test.ts b/gitnexus/test/unit/tools.test.ts index 23bb79606d..3681016285 100644 --- a/gitnexus/test/unit/tools.test.ts +++ b/gitnexus/test/unit/tools.test.ts @@ -134,14 +134,15 @@ describe('GITNEXUS_TOOLS', () => { expect(contextTool.inputSchema.properties.file).toMatchObject({ type: 'string' }); }); - it('api_impact tool expresses the route-or-file requirement via anyOf (#2308)', () => { + it('api_impact tool avoids top-level schema combinators for Bedrock compatibility (#2487)', () => { const apiImpactTool = GITNEXUS_TOOLS.find((t) => t.name === 'api_impact')!; - expect(apiImpactTool.inputSchema.anyOf).toEqual([ - { required: ['route'] }, - { required: ['file'] }, - ]); - // route/file stay optional in `required` (anyOf carries the cross-field rule) + expect(apiImpactTool.inputSchema).not.toHaveProperty('anyOf'); + expect(apiImpactTool.inputSchema).not.toHaveProperty('oneOf'); + expect(apiImpactTool.inputSchema).not.toHaveProperty('allOf'); + // route/file stay optional in the transport schema; callTool keeps the + // runtime guard so providers that reject top-level combinators can load it. expect(apiImpactTool.inputSchema.required).toEqual([]); + expect(apiImpactTool.description).toContain('Requires at least "route" or "file"'); }); it('impact tool requires direction and advertises target, name, or symbol without combinators', () => {