Files
reverse-engineering-anything/src/contracts/browserCaptureToolInputSchema.ts
T
6b55de017b fix(mcp): bound capture comparison input schema depth (#1005)
* fix(mcp): advertise JSON values without recursive schemas

`z.json()` projects a self-referential `$defs/__schema0` entry. Twenty
tool input schemas and 123 output schemas carried it, and clients or
model APIs that reject recursive JSON Schemas refuse the whole tool
list. Every JSON value satisfies `{}`, so the shared JSON value schema
now advertises that. Runtime parsing still admits only JSON values.

Refs #919

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mcp): keep advertised input schemas within model function-calling limits

Some model providers reject the whole tool list when any input schema
contains a recursive $ref or nests deeper than 10 levels (fixes #919).
Sanitize the advertised wire projection: break cyclic $refs, bound nesting
depth, and drop unreachable $defs. Canonical Zod contracts are untouched.

---------

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: sx4im <sx4im@users.noreply.github.com>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-08 12:26:00 +08:00

63 lines
2.6 KiB
TypeScript

import { browserCaptureComparisonInputSchema } from "../domain/browserCaptureComparison.js";
import { browserScenarioCaptureSchema } from "../domain/browserScenarioCapture.js";
import { captureSnapshotSchema } from "../domain/webCaptureDiffSchemas.js";
// Captures are complete producer results to pass back unchanged, rather than
// analyst-authored options. Describe that boundary without embedding the entire
// inspection result schema in every comparison input. The cloned parser still
// validates every nested field using the canonical domain schemas.
const passiveCaptureInputSchema = captureSnapshotSchema.clone(
captureSnapshotSchema.def,
);
passiveCaptureInputSchema._zod.toJSONSchema = () => ({
type: "object",
properties: {
inspection: {
type: "object",
description:
"Complete result object returned by inspect_web_page. Pass the entire result unchanged, including capture identity, observations, completeness, and limitations. Every nested field is validated by REA.",
},
webmcp: {
anyOf: [{ type: "object" }, { type: "null" }],
default: null,
description:
"Complete result object returned by discover_webmcp_tools for this capture, or null when it was not recorded. Pass the entire result unchanged. Every nested field is validated by REA.",
},
},
required: ["inspection"],
});
const scenarioCaptureInputSchema = browserScenarioCaptureSchema.clone(
browserScenarioCaptureSchema.def,
);
scenarioCaptureInputSchema._zod.toJSONSchema = () => ({
type: "object",
description:
"Complete result object returned by capture_browser_scenario. Pass the entire result unchanged, including browser and scenario identity, steps, events, artifact contents and digests, completeness, and limitations. Every nested field is validated by REA.",
});
/** Advertise capture round trips while retaining full runtime validation. */
export const browserCaptureToolInputSchema =
browserCaptureComparisonInputSchema.safeExtend({
before: passiveCaptureInputSchema
.optional()
.describe(
"Earlier passive web-page capture with complete producer results.",
),
after: passiveCaptureInputSchema
.optional()
.describe(
"Later passive web-page capture with complete producer results.",
),
before_scenario: scenarioCaptureInputSchema
.optional()
.describe(
"Earlier complete result object returned by capture_browser_scenario.",
),
after_scenario: scenarioCaptureInputSchema
.optional()
.describe(
"Later complete result object returned by capture_browser_scenario.",
),
});