From 166440eeb8042215c02213f53f3a476539f2b51d Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Mon, 29 Jun 2026 11:12:33 +0300 Subject: [PATCH] Decode escaped JSON Pointer refs --- src/parse.ts | 11 +++++++++-- test/parse.test.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/parse.ts b/src/parse.ts index 2aa0406..2d5bf67 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -84,6 +84,10 @@ function dereferenceSpec(spec: McpSpec): McpSpec { const defs = spec.$defs; + function decodeJsonPointerToken(token: string): string { + return token.replace(/~1/g, "/").replace(/~0/g, "~"); + } + function resolveRefs(obj: unknown): unknown { if (typeof obj !== "object" || obj === null) return obj; if (Array.isArray(obj)) return obj.map(resolveRefs); @@ -93,8 +97,11 @@ function dereferenceSpec(spec: McpSpec): McpSpec { if (typeof record.$ref === "string") { const refPath = record.$ref; const match = refPath.match(/^#\/\$defs\/(.+)$/); - if (match && defs[match[1]]) { - return resolveRefs(structuredClone(defs[match[1]])); + if (match) { + const defName = decodeJsonPointerToken(match[1]); + if (defs[defName]) { + return resolveRefs(structuredClone(defs[defName])); + } } } diff --git a/test/parse.test.ts b/test/parse.test.ts index 4f2fc97..ff5fdb1 100644 --- a/test/parse.test.ts +++ b/test/parse.test.ts @@ -156,4 +156,35 @@ describe("$ref dereferencing", () => { const fooProp = spec.tools![0].inputSchema.properties!.foo; expect(fooProp).toHaveProperty("$ref", "#/$defs/Missing"); }); + + it("resolves escaped JSON Pointer tokens in $defs refs", () => { + const spec = parseString( + JSON.stringify({ + mcpSpec: "0.1.0", + server: { name: "test", version: "1.0.0" }, + $defs: { + "Address/Primary": { type: "string" }, + "Name~Display": { type: "string" }, + }, + tools: [ + { + name: "profile", + inputSchema: { + type: "object", + properties: { + address: { $ref: "#/$defs/Address~1Primary" }, + displayName: { $ref: "#/$defs/Name~0Display" }, + }, + }, + }, + ], + }), + ); + + const properties = spec.tools![0].inputSchema.properties!; + expect(properties.address).not.toHaveProperty("$ref"); + expect(properties.address).toHaveProperty("type", "string"); + expect(properties.displayName).not.toHaveProperty("$ref"); + expect(properties.displayName).toHaveProperty("type", "string"); + }); });