Files
reverse-engineering-anything/src/domain/jsonValue.test.ts
T
7425f70fd0 fix(mcp): advertise JSON values without recursive schemas (#995)
`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>
Co-authored-by: N0zoM1z0 <1705004398@qq.com>
2026-10-08 11:48:57 +08:00

38 lines
1.1 KiB
TypeScript

import { Ajv2020 } from "ajv/dist/2020.js";
import { expect, it } from "vitest";
import { z } from "zod";
import { jsonObjectSchema, jsonValueSchema } from "./jsonValue.js";
const values = [
"text",
0,
false,
null,
[],
{},
{ nested: [{ deeper: [1, "two", null, { three: true }] }] },
];
it("projects JSON values without recursive definitions", () => {
for (const io of ["input", "output"] as const) {
const schema = z.toJSONSchema(
z.object({ value: jsonValueSchema, map: jsonObjectSchema }),
{ io },
);
expect(JSON.stringify(schema)).not.toContain("$ref");
expect(schema).not.toHaveProperty("$defs");
const validate = new Ajv2020({ strict: false }).compile(schema);
for (const value of values)
expect(validate({ value, map: { value } })).toBe(true);
expect(validate({ value: 1, map: [] })).toBe(false);
}
});
it("still parses only JSON values at runtime", () => {
for (const value of values)
expect(jsonValueSchema.safeParse(value).success).toBe(true);
for (const value of [undefined, Number.NaN, Infinity, () => 0, [undefined]])
expect(jsonValueSchema.safeParse(value).success).toBe(false);
});