Files
reverse-engineering-anything/src/server/JavaScriptRouteAdvertisedSchema.test.ts
T
morluto d0fee4e58e fix(mcp): re-emit advertised patterns in a portable regex grammar (#10582)
* test(mcp): check advertised schemas against a portable dialect in every profile

* fix(mcp): re-emit advertised patterns in a portable regex grammar

* fix(mcp): validate advertised dialect by selected profile

* fix(mcp): preserve schema widening through references

* fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns

* fix(mcp): keep references valid when presentation widens their targets

* fix(mcp): relax references into negations and conditionals presentation may remove

* fix(mcp): keep astral literals and dynamic references widening in every mode

* fix(mcp): omit astral literals and relax untracked references when presentation widens

* fix(mcp): read reference pointers by schema position, not segment spelling

* fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse

* fix(mcp): omit patterns whose classes name astral characters

* fix(mcp): decide union collapse and pointer protection from canonical branches

* docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes

* test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe

* fix(mcp): protect references into unevaluated keywords lost evaluation removes

* fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings

* fix(mcp): protect references into literal siblings of relaxed draft-07 references
2026-11-15 17:06:43 +08:00

98 lines
3.7 KiB
TypeScript

import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
import { Ajv2020 } from "ajv/dist/2020.js";
import type { AnySchema } from "ajv";
import { createRequire } from "node:module";
import { expect, it } from "vitest";
import { toolContract } from "../contracts/toolContracts.js";
import { projectPortablePattern } from "../contracts/portablePattern.js";
import { toolOutputSchemaWithMetadata } from "../contracts/toolSchemaMetadata.js";
import { javaScriptRouteCandidateSchema } from "../domain/javascript/javascriptRouteFacts.js";
import { javaScriptInventoryRouteSchema } from "../domain/javascript/javascriptRouteInventory.js";
import { RequestTrackingMcpServer } from "./RequestTrackingMcpServer.js";
it("advertises JavaScript route outputs with standard JSON Schema path constraints", async () => {
const server = new RequestTrackingMcpServer({
name: "route-schema",
version: "1",
});
const contract = toolContract("analyze_javascript_application");
server.registerTool(
contract.name,
{
outputSchema: toolOutputSchemaWithMetadata(contract),
},
() => ({ content: [] }),
);
const client = new Client({ name: "route-schema-client", version: "1" });
const [clientTransport, serverTransport] =
InMemoryTransport.createLinkedPair();
try {
await server.connect(serverTransport);
await client.connect(clientTransport);
const advertised = (await client.listTools()).tools.find(
(tool) => tool.name === contract.name,
)?.outputSchema;
expect(advertised).toBeDefined();
if (advertised === undefined)
throw new Error("Missing advertised route schema");
const ajv = new Ajv2020({
strictSchema: true,
strictTypes: false,
code: { optimize: false },
});
const require = createRequire(import.meta.url);
const addFormats: unknown = require("ajv-formats");
if (typeof addFormats !== "function")
throw new Error("Pinned AJV formats plugin is unavailable");
addFormats(ajv);
expect(() => ajv.compile(advertised as AnySchema)).not.toThrow();
// The inventory path is nested inside the advertised complete Evidence
// branch, re-emitted as a portable anchored pattern.
const portable = projectPortablePattern("^\\/");
expect(portable.kind).toBe("exact");
const patterns: Record<string, unknown>[] = [];
const visit = (value: unknown): void => {
if (value === null || typeof value !== "object") return;
if (Array.isArray(value)) {
value.forEach(visit);
return;
}
const record = value as Record<string, unknown>;
if (
portable.kind !== "unexpressible" &&
record.pattern === portable.pattern
)
patterns.push(record);
Object.values(record).forEach(visit);
};
visit(advertised);
expect(patterns.length).toBeGreaterThan(0);
for (const schema of patterns) {
const validate = ajv.compile(schema);
for (const path of ["/", "/users", "/users\nsettings", "/\r\n"]) {
expect(validate(path), path).toBe(true);
expect(
javaScriptRouteCandidateSchema.shape.path.safeParse(path).success,
).toBe(true);
expect(
javaScriptInventoryRouteSchema.shape.path.safeParse(path).success,
).toBe(true);
}
for (const path of ["", "users", "\n/users", "https://example.test/"]) {
expect(validate(path), path).toBe(false);
expect(
javaScriptRouteCandidateSchema.shape.path.safeParse(path).success,
).toBe(false);
expect(
javaScriptInventoryRouteSchema.shape.path.safeParse(path).success,
).toBe(false);
}
}
} finally {
await client.close();
await server.close();
}
});