@mastra/mcp 2.6.0-alpha.0 → 2.6.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { n as MAX_SCHEMA_VALUES, r as countJsonValues, t as MAX_CATALOG_VALUES } from "./json-schema-dialect-B5B7l9Po.js";
1
+ import { n as MAX_SCHEMA_VALUES, r as countJsonValues, t as MAX_CATALOG_VALUES } from "./json-schema-dialect-CdIOPBiC.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { Worker } from "node:worker_threads";
4
4
  import { randomUUID } from "node:crypto";
@@ -7,7 +7,7 @@ import { basename, dirname, join, resolve } from "node:path";
7
7
  import { pathToFileURL } from "node:url";
8
8
  import { noopLogger } from "@mastra/core/logger";
9
9
  import { MCPClient } from "@mastra/mcp";
10
- //#region src/cli/generate.ts
10
+ // src/cli/generate.ts
11
11
  /** Failure whose message is safe to print: it is built from supplied paths and server names only. */
12
12
  var GenerationError = class extends Error {
13
13
  constructor(message) {
@@ -213,7 +213,6 @@ async function generate(files, cwd = process.cwd()) {
213
213
  }
214
214
  if (failure) throw failure;
215
215
  }
216
- //#endregion
217
216
  export { generate };
218
217
 
219
- //# sourceMappingURL=generate-K-rW1Wck.js.map
218
+ //# sourceMappingURL=generate-D0K0N5WQ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-K-rW1Wck.js","names":[],"sources":["../../src/cli/generate.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { lstat, mkdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\nimport { noopLogger } from '@mastra/core/logger';\nimport { MCPClient } from '@mastra/mcp';\nimport type { SerializableMCPToolCatalog, SerializableMCPToolDefinition } from '../client/types';\nimport { countJsonValues, MAX_CATALOG_VALUES, MAX_SCHEMA_VALUES } from '../shared/json-schema-dialect';\n\n/** Failure whose message is safe to print: it is built from supplied paths and server names only. */\nexport class GenerationError extends Error {\n constructor(message: string) {\n super(message);\n // Checked by name rather than `instanceof` so the distinction survives bundling and separate\n // module registries, exactly as the CommonJS/ESM client identity does.\n this.name = 'GenerationError';\n }\n}\n\n/** A catalogue can widen thousands of schemas; report enough to act on without flooding a terminal. */\nconst MAX_REPORTED_WARNINGS = 25;\n\nlet CommonJSClient: typeof MCPClient | undefined;\nfunction isClient(value: unknown): value is MCPClient {\n if (value instanceof MCPClient) return true;\n if (!value || typeof value !== 'object') return false;\n CommonJSClient ??= createRequire(import.meta.url)('@mastra/mcp').MCPClient;\n return value instanceof CommonJSClient!;\n}\n\nfunction missing(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\n/**\n * Apply the value budget to a discovered catalogue before it crosses to the worker. The transfer\n * copies whatever is sent, so an oversized schema has to be widened while it is still only being\n * counted rather than after it has been copied in full. Widening to `true` generates `unknown`,\n * which is the same contract the worker produces for a schema it widens itself.\n */\nexport function boundTransfer(catalog: SerializableMCPToolCatalog): {\n catalog: SerializableMCPToolCatalog;\n warnings: string[];\n} {\n const bounded: SerializableMCPToolCatalog = {};\n const warnings: string[] = [];\n let values = 0;\n for (const server of Object.keys(catalog)) {\n const tools: Record<string, SerializableMCPToolDefinition> = {};\n bounded[server] = tools;\n for (const tool of Object.keys(catalog[server]!)) {\n const definition = { ...catalog[server]![tool]! };\n for (const key of ['inputSchema', 'outputSchema'] as const) {\n const schema = definition[key];\n if (schema === undefined) continue;\n const counted = countJsonValues(schema, MAX_SCHEMA_VALUES);\n values += counted;\n if (counted > MAX_SCHEMA_VALUES || values > MAX_CATALOG_VALUES) {\n definition[key] = true;\n const reason =\n counted > MAX_SCHEMA_VALUES\n ? `Schema exceeds the maximum value count of ${MAX_SCHEMA_VALUES}`\n : `Catalogue exceeds the maximum value count of ${MAX_CATALOG_VALUES}`;\n warnings.push(\n `${reason} at server ${JSON.stringify(server)} tool ${JSON.stringify(tool)} ${\n key === 'inputSchema' ? 'input' : 'output'\n }; widened to unknown`,\n );\n }\n }\n tools[tool] = definition;\n }\n }\n return { catalog: bounded, warnings };\n}\n\nasync function canonical(path: string): Promise<string> {\n try {\n return await realpath(path);\n } catch (error) {\n if (!missing(error)) throw error;\n // A dangling symlink must not become a new, unrelated output file.\n const entry = await lstat(path).catch(() => undefined);\n if (entry?.isSymbolicLink()) throw new GenerationError('Output path contains a dangling symlink');\n const parent = dirname(path);\n if (parent === path) throw error;\n return join(await canonical(parent), basename(path));\n }\n}\n\n/** Isolate the converter's environment-controlled logging from imported application code. */\nfunction convert(\n definitions: SerializableMCPToolCatalog,\n signal: AbortSignal,\n): Promise<{ source: string; warnings: string[] }> {\n return new Promise((accept, reject) => {\n const source = import.meta.url.endsWith('.ts');\n const entry = new URL(source ? './index.ts' : './index.js', import.meta.url).href;\n const bootstrap = `const { workerData } = require('node:worker_threads');\n (async () => {\n if (workerData.source) { const { register } = await import(workerData.loader); register(); }\n await import(workerData.entry);\n })().catch(() => process.exitCode = 1);`;\n const worker = new Worker(bootstrap, {\n eval: true,\n execArgv: [],\n env: { ...process.env, VERBOSE: '' },\n workerData: { typegen: true, source, loader: import.meta.resolve('tsx/esm/api'), entry, definitions },\n stdout: true,\n stderr: true,\n });\n worker.stdout.resume();\n worker.stderr.resume();\n const abort = () => {\n void worker.terminate();\n };\n signal.addEventListener('abort', abort, { once: true });\n if (signal.aborted) abort();\n worker.once('message', result => {\n if (result.ok) accept(result.value);\n // Only the generator's own `TypegenError` messages cross this boundary; converter failures\n // stay generic so their text cannot carry schema values into a diagnostic.\n else reject(new GenerationError(result.message ?? 'Schema conversion failed'));\n });\n worker.once('error', () => reject(new GenerationError('Schema conversion failed')));\n worker.once('exit', code => {\n signal.removeEventListener('abort', abort);\n if (code !== 0 || signal.aborted) reject(new GenerationError('Schema conversion interrupted'));\n });\n });\n}\n\n/** Internal command runner. Errors are deliberately independent of imported error messages. */\nexport async function generate(files: string[], cwd = process.cwd()): Promise<void> {\n const clients = new Set<MCPClient>();\n const staged: { temporary: string; output: string }[] = [];\n const abort = new AbortController();\n const cleanup = new Map<MCPClient, Promise<void>>();\n const disconnect = () => {\n for (const client of clients) {\n if (!cleanup.has(client))\n cleanup.set(\n client,\n Promise.resolve().then(() => client.disconnect()),\n );\n }\n return Promise.allSettled(cleanup.values());\n };\n const interrupt = () => {\n abort.abort();\n void disconnect();\n };\n // Loaded here rather than at module scope: a top-level `tsx/esm/api` specifier\n // sorts differently against the `@mastra/mcp` self-reference depending on how\n // that self-reference resolves, which makes the import order environment-dependent.\n const { register } = await import('tsx/esm/api');\n const unregister = register();\n process.once('SIGINT', interrupt);\n process.once('SIGTERM', interrupt);\n let failure: unknown;\n try {\n const inputs = new Set<string>();\n for (const file of files) {\n const input = await realpath(resolve(cwd, file));\n if (!(await stat(input)).isFile()) throw new GenerationError('Client input must be a file');\n inputs.add(input);\n }\n for (const input of inputs) {\n abort.signal.throwIfAborted();\n const module = await import(pathToFileURL(input).href);\n let eligible = false;\n for (const value of Object.values(module)) {\n if (isClient(value) && value.typegen) {\n eligible = true;\n clients.add(value);\n value.__setLogger(noopLogger);\n }\n }\n if (!eligible) throw new GenerationError('A supplied file has no exported typegen-enabled MCPClient');\n }\n const outputs = new Map<string, MCPClient>();\n for (const client of clients) {\n const output = await canonical(resolve(cwd, client.typegen!.outFile));\n if (inputs.has(output)) throw new GenerationError('Output overlaps a supplied client file');\n if (outputs.has(output)) throw new GenerationError('Multiple clients target the same output file');\n const existing = await stat(output).catch(error => {\n if (!missing(error)) throw error;\n return undefined;\n });\n if (existing && !existing.isFile()) throw new GenerationError('Output must be a file');\n outputs.set(output, client);\n }\n const prepared: { output: string; source: string }[] = [];\n const warnings: string[] = [];\n for (const [output, client] of outputs) {\n abort.signal.throwIfAborted();\n const result = await client.listToolDefinitionsWithErrors();\n const failed = [...new Set([...Object.keys(result.errors), ...Object.keys(result.errorDetails)])];\n if (failed.length) {\n throw new GenerationError(\n `MCP discovery failed for ${failed.map(name => JSON.stringify(name)).join(', ')}; no generated files were replaced`,\n );\n }\n const bounded = boundTransfer(result.definitions);\n warnings.push(...bounded.warnings);\n const converted = await convert(bounded.catalog, abort.signal);\n warnings.push(...converted.warnings);\n prepared.push({ output, source: converted.source });\n }\n // Disconnect before replacement so cleanup failures preserve previous output too.\n if ((await disconnect()).some(result => result.status === 'rejected'))\n throw new GenerationError('MCP cleanup failed');\n for (const { output, source } of prepared) {\n abort.signal.throwIfAborted();\n await mkdir(dirname(output), { recursive: true });\n const temporary = join(dirname(output), `.mastra-mcp-${randomUUID()}.tmp`);\n staged.push({ temporary, output });\n await writeFile(temporary, source, { flag: 'wx' });\n }\n for (const { temporary, output } of staged) {\n abort.signal.throwIfAborted();\n await rename(temporary, output);\n }\n console.log(`Generated ${prepared.length} MCP type file(s).`);\n if (warnings.length) {\n console.warn(`${warnings.length} schema portion(s) widened to unknown:`);\n for (const warning of warnings.slice(0, MAX_REPORTED_WARNINGS)) console.warn(` ${warning}`);\n if (warnings.length > MAX_REPORTED_WARNINGS)\n console.warn(` ...and ${warnings.length - MAX_REPORTED_WARNINGS} more.`);\n }\n } catch (error) {\n failure =\n error instanceof GenerationError\n ? error\n : new GenerationError('MCP generation failed; check client modules, permissions, and server availability');\n } finally {\n const results = await disconnect();\n const removed = await Promise.allSettled(staged.map(({ temporary }) => rm(temporary, { force: true })));\n process.removeListener('SIGINT', interrupt);\n process.removeListener('SIGTERM', interrupt);\n await unregister();\n if (results.some(result => result.status === 'rejected') || removed.some(result => result.status === 'rejected')) {\n failure ??= new GenerationError('MCP cleanup failed');\n }\n }\n if (failure) throw failure;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"generate-D0K0N5WQ.js","names":[],"sources":["../../src/cli/generate.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { lstat, mkdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { Worker } from 'node:worker_threads';\nimport { noopLogger } from '@mastra/core/logger';\nimport { MCPClient } from '@mastra/mcp';\nimport type { SerializableMCPToolCatalog, SerializableMCPToolDefinition } from '../client/types';\nimport { countJsonValues, MAX_CATALOG_VALUES, MAX_SCHEMA_VALUES } from '../shared/json-schema-dialect';\n\n/** Failure whose message is safe to print: it is built from supplied paths and server names only. */\nexport class GenerationError extends Error {\n constructor(message: string) {\n super(message);\n // Checked by name rather than `instanceof` so the distinction survives bundling and separate\n // module registries, exactly as the CommonJS/ESM client identity does.\n this.name = 'GenerationError';\n }\n}\n\n/** A catalogue can widen thousands of schemas; report enough to act on without flooding a terminal. */\nconst MAX_REPORTED_WARNINGS = 25;\n\nlet CommonJSClient: typeof MCPClient | undefined;\nfunction isClient(value: unknown): value is MCPClient {\n if (value instanceof MCPClient) return true;\n if (!value || typeof value !== 'object') return false;\n CommonJSClient ??= createRequire(import.meta.url)('@mastra/mcp').MCPClient;\n return value instanceof CommonJSClient!;\n}\n\nfunction missing(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\n/**\n * Apply the value budget to a discovered catalogue before it crosses to the worker. The transfer\n * copies whatever is sent, so an oversized schema has to be widened while it is still only being\n * counted rather than after it has been copied in full. Widening to `true` generates `unknown`,\n * which is the same contract the worker produces for a schema it widens itself.\n */\nexport function boundTransfer(catalog: SerializableMCPToolCatalog): {\n catalog: SerializableMCPToolCatalog;\n warnings: string[];\n} {\n const bounded: SerializableMCPToolCatalog = {};\n const warnings: string[] = [];\n let values = 0;\n for (const server of Object.keys(catalog)) {\n const tools: Record<string, SerializableMCPToolDefinition> = {};\n bounded[server] = tools;\n for (const tool of Object.keys(catalog[server]!)) {\n const definition = { ...catalog[server]![tool]! };\n for (const key of ['inputSchema', 'outputSchema'] as const) {\n const schema = definition[key];\n if (schema === undefined) continue;\n const counted = countJsonValues(schema, MAX_SCHEMA_VALUES);\n values += counted;\n if (counted > MAX_SCHEMA_VALUES || values > MAX_CATALOG_VALUES) {\n definition[key] = true;\n const reason =\n counted > MAX_SCHEMA_VALUES\n ? `Schema exceeds the maximum value count of ${MAX_SCHEMA_VALUES}`\n : `Catalogue exceeds the maximum value count of ${MAX_CATALOG_VALUES}`;\n warnings.push(\n `${reason} at server ${JSON.stringify(server)} tool ${JSON.stringify(tool)} ${\n key === 'inputSchema' ? 'input' : 'output'\n }; widened to unknown`,\n );\n }\n }\n tools[tool] = definition;\n }\n }\n return { catalog: bounded, warnings };\n}\n\nasync function canonical(path: string): Promise<string> {\n try {\n return await realpath(path);\n } catch (error) {\n if (!missing(error)) throw error;\n // A dangling symlink must not become a new, unrelated output file.\n const entry = await lstat(path).catch(() => undefined);\n if (entry?.isSymbolicLink()) throw new GenerationError('Output path contains a dangling symlink');\n const parent = dirname(path);\n if (parent === path) throw error;\n return join(await canonical(parent), basename(path));\n }\n}\n\n/** Isolate the converter's environment-controlled logging from imported application code. */\nfunction convert(\n definitions: SerializableMCPToolCatalog,\n signal: AbortSignal,\n): Promise<{ source: string; warnings: string[] }> {\n return new Promise((accept, reject) => {\n const source = import.meta.url.endsWith('.ts');\n const entry = new URL(source ? './index.ts' : './index.js', import.meta.url).href;\n const bootstrap = `const { workerData } = require('node:worker_threads');\n (async () => {\n if (workerData.source) { const { register } = await import(workerData.loader); register(); }\n await import(workerData.entry);\n })().catch(() => process.exitCode = 1);`;\n const worker = new Worker(bootstrap, {\n eval: true,\n execArgv: [],\n env: { ...process.env, VERBOSE: '' },\n workerData: { typegen: true, source, loader: import.meta.resolve('tsx/esm/api'), entry, definitions },\n stdout: true,\n stderr: true,\n });\n worker.stdout.resume();\n worker.stderr.resume();\n const abort = () => {\n void worker.terminate();\n };\n signal.addEventListener('abort', abort, { once: true });\n if (signal.aborted) abort();\n worker.once('message', result => {\n if (result.ok) accept(result.value);\n // Only the generator's own `TypegenError` messages cross this boundary; converter failures\n // stay generic so their text cannot carry schema values into a diagnostic.\n else reject(new GenerationError(result.message ?? 'Schema conversion failed'));\n });\n worker.once('error', () => reject(new GenerationError('Schema conversion failed')));\n worker.once('exit', code => {\n signal.removeEventListener('abort', abort);\n if (code !== 0 || signal.aborted) reject(new GenerationError('Schema conversion interrupted'));\n });\n });\n}\n\n/** Internal command runner. Errors are deliberately independent of imported error messages. */\nexport async function generate(files: string[], cwd = process.cwd()): Promise<void> {\n const clients = new Set<MCPClient>();\n const staged: { temporary: string; output: string }[] = [];\n const abort = new AbortController();\n const cleanup = new Map<MCPClient, Promise<void>>();\n const disconnect = () => {\n for (const client of clients) {\n if (!cleanup.has(client))\n cleanup.set(\n client,\n Promise.resolve().then(() => client.disconnect()),\n );\n }\n return Promise.allSettled(cleanup.values());\n };\n const interrupt = () => {\n abort.abort();\n void disconnect();\n };\n // Loaded here rather than at module scope: a top-level `tsx/esm/api` specifier\n // sorts differently against the `@mastra/mcp` self-reference depending on how\n // that self-reference resolves, which makes the import order environment-dependent.\n const { register } = await import('tsx/esm/api');\n const unregister = register();\n process.once('SIGINT', interrupt);\n process.once('SIGTERM', interrupt);\n let failure: unknown;\n try {\n const inputs = new Set<string>();\n for (const file of files) {\n const input = await realpath(resolve(cwd, file));\n if (!(await stat(input)).isFile()) throw new GenerationError('Client input must be a file');\n inputs.add(input);\n }\n for (const input of inputs) {\n abort.signal.throwIfAborted();\n const module = await import(pathToFileURL(input).href);\n let eligible = false;\n for (const value of Object.values(module)) {\n if (isClient(value) && value.typegen) {\n eligible = true;\n clients.add(value);\n value.__setLogger(noopLogger);\n }\n }\n if (!eligible) throw new GenerationError('A supplied file has no exported typegen-enabled MCPClient');\n }\n const outputs = new Map<string, MCPClient>();\n for (const client of clients) {\n const output = await canonical(resolve(cwd, client.typegen!.outFile));\n if (inputs.has(output)) throw new GenerationError('Output overlaps a supplied client file');\n if (outputs.has(output)) throw new GenerationError('Multiple clients target the same output file');\n const existing = await stat(output).catch(error => {\n if (!missing(error)) throw error;\n return undefined;\n });\n if (existing && !existing.isFile()) throw new GenerationError('Output must be a file');\n outputs.set(output, client);\n }\n const prepared: { output: string; source: string }[] = [];\n const warnings: string[] = [];\n for (const [output, client] of outputs) {\n abort.signal.throwIfAborted();\n const result = await client.listToolDefinitionsWithErrors();\n const failed = [...new Set([...Object.keys(result.errors), ...Object.keys(result.errorDetails)])];\n if (failed.length) {\n throw new GenerationError(\n `MCP discovery failed for ${failed.map(name => JSON.stringify(name)).join(', ')}; no generated files were replaced`,\n );\n }\n const bounded = boundTransfer(result.definitions);\n warnings.push(...bounded.warnings);\n const converted = await convert(bounded.catalog, abort.signal);\n warnings.push(...converted.warnings);\n prepared.push({ output, source: converted.source });\n }\n // Disconnect before replacement so cleanup failures preserve previous output too.\n if ((await disconnect()).some(result => result.status === 'rejected'))\n throw new GenerationError('MCP cleanup failed');\n for (const { output, source } of prepared) {\n abort.signal.throwIfAborted();\n await mkdir(dirname(output), { recursive: true });\n const temporary = join(dirname(output), `.mastra-mcp-${randomUUID()}.tmp`);\n staged.push({ temporary, output });\n await writeFile(temporary, source, { flag: 'wx' });\n }\n for (const { temporary, output } of staged) {\n abort.signal.throwIfAborted();\n await rename(temporary, output);\n }\n console.log(`Generated ${prepared.length} MCP type file(s).`);\n if (warnings.length) {\n console.warn(`${warnings.length} schema portion(s) widened to unknown:`);\n for (const warning of warnings.slice(0, MAX_REPORTED_WARNINGS)) console.warn(` ${warning}`);\n if (warnings.length > MAX_REPORTED_WARNINGS)\n console.warn(` ...and ${warnings.length - MAX_REPORTED_WARNINGS} more.`);\n }\n } catch (error) {\n failure =\n error instanceof GenerationError\n ? error\n : new GenerationError('MCP generation failed; check client modules, permissions, and server availability');\n } finally {\n const results = await disconnect();\n const removed = await Promise.allSettled(staged.map(({ temporary }) => rm(temporary, { force: true })));\n process.removeListener('SIGINT', interrupt);\n process.removeListener('SIGTERM', interrupt);\n await unregister();\n if (results.some(result => result.status === 'rejected') || removed.some(result => result.status === 'rejected')) {\n failure ??= new GenerationError('MCP cleanup failed');\n }\n }\n if (failure) throw failure;\n}\n"],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { isMainThread, parentPort, workerData } from "node:worker_threads";
3
- //#region src/cli/index.ts
3
+ // src/cli/index.ts
4
4
  if (!isMainThread && workerData?.typegen === true) {
5
- const { generateToolTypes, TypegenError } = await import("./typegen-CLDjVF16.js");
5
+ const { generateToolTypes, TypegenError } = await import("./typegen-B5dH_z0t.js");
6
6
  try {
7
7
  parentPort.postMessage({
8
8
  ok: true,
@@ -20,14 +20,13 @@ if (!isMainThread && workerData?.typegen === true) {
20
20
  console.error("Usage: npx @mastra/mcp generate <client-files...>");
21
21
  process.exitCode = 1;
22
22
  } else try {
23
- const { generate } = await import("./generate-K-rW1Wck.js");
23
+ const { generate } = await import("./generate-D0K0N5WQ.js");
24
24
  await generate(files);
25
25
  } catch (error) {
26
26
  console.error(error instanceof Error && error.name === "GenerationError" ? error.message : "MCP generation failed. Check client exports, output paths, server access, and schema validity. Files may be partially replaced only if a filesystem replacement fails.");
27
27
  process.exitCode = 1;
28
28
  }
29
29
  }
30
- //#endregion
31
30
  export {};
32
31
 
33
32
  //# sourceMappingURL=index.js.map
@@ -127,7 +127,6 @@ function* containerValues(value) {
127
127
  }
128
128
  for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) yield Reflect.get(value, key);
129
129
  }
130
- //#endregion
131
130
  export { jsonSchemaComplexity as i, MAX_SCHEMA_VALUES as n, countJsonValues as r, MAX_CATALOG_VALUES as t };
132
131
 
133
- //# sourceMappingURL=json-schema-dialect-B5B7l9Po.js.map
132
+ //# sourceMappingURL=json-schema-dialect-CdIOPBiC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema-dialect-B5B7l9Po.js","names":[],"sources":["../../src/shared/json-schema-dialect.ts"],"sourcesContent":["export const JSON_SCHEMA_2020_12 = 'https://json-schema.org/draft/2020-12/schema';\n\nconst JSON_SCHEMA_2019_09 = /^https?:\\/\\/json-schema\\.org\\/draft\\/2019-09\\/schema#?$/;\n\n/** Keywords whose value is a subschema (`items` may also be an array of subschemas). */\nconst SCHEMA_KEYWORDS = new Set([\n 'items',\n 'additionalItems',\n 'contains',\n 'additionalProperties',\n 'propertyNames',\n 'unevaluatedItems',\n 'unevaluatedProperties',\n 'if',\n 'then',\n 'else',\n 'not',\n]);\n/** Keywords whose value is an array of subschemas. */\nconst SCHEMA_ARRAY_KEYWORDS = new Set(['allOf', 'anyOf', 'oneOf']);\n/** Keywords whose values map arbitrary names to subschemas. */\nconst SCHEMA_MAP_KEYWORDS = new Set(['properties', 'patternProperties', '$defs', 'definitions', 'dependentSchemas']);\n\n/** Complexity limits for untrusted schemas; also enforced by the client before validation. */\nexport const MAX_JSON_SCHEMA_DEPTH = 128;\nexport const MAX_JSON_SCHEMA_NODES = 10_000;\n\n/**\n * Raw JSON values a single schema may contribute before generation widens it, and the total a whole\n * catalogue may contribute before generation widens the remainder. The node limit above counts only\n * schema-bearing keywords, so these bound the annotation and extension values it deliberately\n * ignores. They live here rather than with the generator so the CLI can apply them without loading\n * the converter.\n */\nexport const MAX_SCHEMA_VALUES = MAX_JSON_SCHEMA_NODES * 10;\nexport const MAX_CATALOG_VALUES = MAX_SCHEMA_VALUES * 10;\n\nclass Unconvertible extends Error {}\n\n/**\n * Bounds the work a validator or type generator can be asked to do for an untrusted schema.\n * Only schema-bearing keywords are walked, so deeply nested annotation data such as `default`\n * or `examples` does not count. The counted nodes are returned so callers can also budget\n * across a whole catalogue rather than one schema at a time.\n *\n * The keyword lists are intentionally wider than the conversion sets above: this walk has to\n * reach every position that can carry validation rules, including `dependencies`,\n * `prefixItems`, and `contentSchema`.\n */\nexport function jsonSchemaComplexity(schema: unknown): {\n error?: string;\n limit?: 'depth' | 'nodes';\n nodes: number;\n} {\n const seen = new Set<object>();\n let nodes = 0;\n const stack = [{ value: schema, depth: 0 }];\n const schemaMapKeywords = [\n '$defs',\n 'definitions',\n 'properties',\n 'patternProperties',\n 'dependentSchemas',\n 'dependencies',\n ];\n const schemaArrayKeywords = ['prefixItems', 'allOf', 'anyOf', 'oneOf', 'items'];\n const schemaKeywords = [\n 'additionalProperties',\n 'unevaluatedProperties',\n 'additionalItems',\n 'unevaluatedItems',\n 'items',\n 'contains',\n 'propertyNames',\n 'not',\n 'if',\n 'then',\n 'else',\n 'contentSchema',\n ];\n\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (value === null || typeof value !== 'object' || Array.isArray(value) || seen.has(value)) continue;\n seen.add(value);\n\n nodes += 1;\n if (depth > MAX_JSON_SCHEMA_DEPTH) {\n return {\n error: `JSON Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`,\n limit: 'depth',\n nodes,\n };\n }\n if (nodes > MAX_JSON_SCHEMA_NODES) {\n return {\n error: `JSON Schema exceeds the maximum node count of ${MAX_JSON_SCHEMA_NODES}`,\n limit: 'nodes',\n nodes,\n };\n }\n\n const record = value as Record<string, unknown>;\n for (const keyword of schemaMapKeywords) {\n const schemas = record[keyword];\n if (schemas && typeof schemas === 'object' && !Array.isArray(schemas)) {\n for (const child of Object.values(schemas)) stack.push({ value: child, depth: depth + 1 });\n }\n }\n for (const keyword of schemaArrayKeywords) {\n const schemas = record[keyword];\n if (Array.isArray(schemas)) {\n for (const child of schemas) stack.push({ value: child, depth: depth + 1 });\n }\n }\n for (const keyword of schemaKeywords) {\n if (record[keyword] !== undefined) stack.push({ value: record[keyword], depth: depth + 1 });\n }\n }\n\n return { nodes };\n}\n\n/**\n * Counts every value in a raw schema and stops once `limit` is exceeded. Unlike\n * {@link jsonSchemaComplexity}, which counts only schema-bearing keywords, this covers\n * annotation and extension data and boolean subschema entries, so callers that copy or transfer\n * the whole value can bound that work rather than the validation work a schema describes.\n *\n * Children are pulled one at a time, so a container wider than the budget is never expanded.\n * Values already seen are counted once, matching how this walk treats cycles.\n */\nexport function countJsonValues(value: unknown, limit: number): number {\n const seen = new Set<object>();\n const frames: Array<Generator<unknown>> = [];\n let nodes = 0;\n\n function count(current: unknown): boolean {\n if (++nodes > limit) return false;\n if (current === null || typeof current !== 'object' || seen.has(current)) return true;\n seen.add(current);\n frames.push(containerValues(current));\n return true;\n }\n\n if (!count(value)) return nodes;\n while (frames.length > 0) {\n const next = frames[frames.length - 1]!.next();\n if (next.done) frames.pop();\n else if (!count(next.value)) return nodes;\n }\n\n return nodes;\n}\n\n/** Yields a JSON container's children without materialising them. */\nfunction* containerValues(value: object): Generator<unknown> {\n if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index += 1) yield value[index];\n return;\n }\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key)) yield Reflect.get(value, key);\n }\n}\n\n/**\n * Converts a 2019-09 schema (e.g. from zod v3) into 2020-12 form. Tuples are the\n * only structural difference handled: array-form `items` becomes `prefixItems`,\n * and `additionalItems` becomes `items`.\n *\n * Returns `undefined` when the schema does not declare 2019-09, or relies on\n * features this conversion cannot preserve (`$recursiveRef`/`$recursiveAnchor`,\n * `$ref` pointers into tuple members, embedded `$schema` declarations,\n * `unevaluatedItems`, `prefixItems`, or `contentSchema`), or exceeds the depth/node limits.\n * Callers should then keep the original.\n */\nexport function toJsonSchema2020<T extends { $schema?: string }>(schema: T): T | undefined {\n if (!schema.$schema || !JSON_SCHEMA_2019_09.test(schema.$schema)) return undefined;\n try {\n return { ...(rewrite(schema, 0, { nodes: 0 }, true) as T), $schema: JSON_SCHEMA_2020_12 };\n } catch (error) {\n if (error instanceof Unconvertible) return undefined;\n throw error;\n }\n}\n\nfunction checkBudget(depth: number, budget: { nodes: number }) {\n if (depth > MAX_JSON_SCHEMA_DEPTH || ++budget.nodes > MAX_JSON_SCHEMA_NODES) throw new Unconvertible();\n}\n\n/** Rewrites a value in a subschema position. Only known schema keywords are walked; everything else is copied as-is. */\nfunction rewrite(schema: unknown, depth: number, budget: { nodes: number }, isRoot = false): unknown {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return schema;\n checkBudget(depth, budget);\n\n const out: Record<string, unknown> = { ...schema };\n // Embedded resources may declare their own dialect. unevaluatedItems interacts with contains (including via\n // in-place applicators) differently in 2020-12, prefixItems is an annotation in 2019-09 but an assertion in\n // 2020-12, and contentSchema is not walked. zod v3 emits none of these, so decline rather than risk a change.\n if (!isRoot && '$schema' in out) throw new Unconvertible();\n if ('$recursiveRef' in out || '$recursiveAnchor' in out) throw new Unconvertible();\n if ('unevaluatedItems' in out || 'prefixItems' in out || 'contentSchema' in out) throw new Unconvertible();\n if (typeof out.$ref === 'string' && /\\/(items\\/\\d+|additionalItems)(\\/|$)/.test(out.$ref)) {\n throw new Unconvertible();\n }\n\n for (const [key, child] of Object.entries(out)) {\n if (SCHEMA_KEYWORDS.has(key)) {\n out[key] = Array.isArray(child)\n ? (checkBudget(depth + 1, budget), child.map(item => rewrite(item, depth + 2, budget)))\n : rewrite(child, depth + 1, budget);\n } else if (SCHEMA_ARRAY_KEYWORDS.has(key) && Array.isArray(child)) {\n checkBudget(depth + 1, budget);\n out[key] = child.map(item => rewrite(item, depth + 2, budget));\n } else if (SCHEMA_MAP_KEYWORDS.has(key) && child && typeof child === 'object' && !Array.isArray(child)) {\n checkBudget(depth + 1, budget);\n out[key] = Object.fromEntries(\n Object.entries(child).map(([name, sub]) => [name, rewrite(sub, depth + 2, budget)]),\n );\n }\n }\n if (!Array.isArray(out.items)) return out;\n\n out.prefixItems = out.items;\n if ('additionalItems' in out) out.items = out.additionalItems;\n else delete out.items;\n delete out.additionalItems;\n return out;\n}\n"],"mappings":"AAyBA,MAAa,wBAAwB;;;;;;;;AASrC,MAAa,oBAAoB,wBAAwB;AACzD,MAAa,qBAAqB,oBAAoB;;;;;;;;;;;AActD,SAAgB,qBAAqB,QAInC;CACA,MAAM,uBAAO,IAAI,IAAY;CAC7B,IAAI,QAAQ;CACZ,MAAM,QAAQ,CAAC;EAAE,OAAO;EAAQ,OAAO;CAAE,CAAC;CAC1C,MAAM,oBAAoB;EACxB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,sBAAsB;EAAC;EAAe;EAAS;EAAS;EAAS;CAAO;CAC9E,MAAM,iBAAiB;EACrB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,EAAE,OAAO,UAAU,MAAM,IAAI;EACnC,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,KAAK,IAAI,KAAK,GAAG;EAC5F,KAAK,IAAI,KAAK;EAEd,SAAS;EACT,IAAI,QAAA,KACF,OAAO;GACL,OAAO;GACP,OAAO;GACP;EACF;EAEF,IAAI,QAAA,KACF,OAAO;GACL,OAAO,iDAAiD;GACxD,OAAO;GACP;EACF;EAGF,MAAM,SAAS;EACf,KAAK,MAAM,WAAW,mBAAmB;GACvC,MAAM,UAAU,OAAO;GACvB,IAAI,WAAW,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,OAAO,GAClE,KAAK,MAAM,SAAS,OAAO,OAAO,OAAO,GAAG,MAAM,KAAK;IAAE,OAAO;IAAO,OAAO,QAAQ;GAAE,CAAC;EAE7F;EACA,KAAK,MAAM,WAAW,qBAAqB;GACzC,MAAM,UAAU,OAAO;GACvB,IAAI,MAAM,QAAQ,OAAO,GACvB,KAAK,MAAM,SAAS,SAAS,MAAM,KAAK;IAAE,OAAO;IAAO,OAAO,QAAQ;GAAE,CAAC;EAE9E;EACA,KAAK,MAAM,WAAW,gBACpB,IAAI,OAAO,aAAa,KAAA,GAAW,MAAM,KAAK;GAAE,OAAO,OAAO;GAAU,OAAO,QAAQ;EAAE,CAAC;CAE9F;CAEA,OAAO,EAAE,MAAM;AACjB;;;;;;;;;;AAWA,SAAgB,gBAAgB,OAAgB,OAAuB;CACrE,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,SAAoC,CAAC;CAC3C,IAAI,QAAQ;CAEZ,SAAS,MAAM,SAA2B;EACxC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC5B,IAAI,YAAY,QAAQ,OAAO,YAAY,YAAY,KAAK,IAAI,OAAO,GAAG,OAAO;EACjF,KAAK,IAAI,OAAO;EAChB,OAAO,KAAK,gBAAgB,OAAO,CAAC;EACpC,OAAO;CACT;CAEA,IAAI,CAAC,MAAM,KAAK,GAAG,OAAO;CAC1B,OAAO,OAAO,SAAS,GAAG;EACxB,MAAM,OAAO,OAAO,OAAO,SAAS,EAAE,CAAE,KAAK;EAC7C,IAAI,KAAK,MAAM,OAAO,IAAI;OACrB,IAAI,CAAC,MAAM,KAAK,KAAK,GAAG,OAAO;CACtC;CAEA,OAAO;AACT;;AAGA,UAAU,gBAAgB,OAAmC;CAC3D,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG,MAAM,MAAM;EAClE;CACF;CACA,KAAK,MAAM,OAAO,OAChB,IAAI,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,GAAG,MAAM,QAAQ,IAAI,OAAO,GAAG;AAEtF"}
1
+ {"version":3,"file":"json-schema-dialect-CdIOPBiC.js","names":[],"sources":["../../src/shared/json-schema-dialect.ts"],"sourcesContent":["export const JSON_SCHEMA_2020_12 = 'https://json-schema.org/draft/2020-12/schema';\n\nconst JSON_SCHEMA_2019_09 = /^https?:\\/\\/json-schema\\.org\\/draft\\/2019-09\\/schema#?$/;\n\n/** Keywords whose value is a subschema (`items` may also be an array of subschemas). */\nconst SCHEMA_KEYWORDS = new Set([\n 'items',\n 'additionalItems',\n 'contains',\n 'additionalProperties',\n 'propertyNames',\n 'unevaluatedItems',\n 'unevaluatedProperties',\n 'if',\n 'then',\n 'else',\n 'not',\n]);\n/** Keywords whose value is an array of subschemas. */\nconst SCHEMA_ARRAY_KEYWORDS = new Set(['allOf', 'anyOf', 'oneOf']);\n/** Keywords whose values map arbitrary names to subschemas. */\nconst SCHEMA_MAP_KEYWORDS = new Set(['properties', 'patternProperties', '$defs', 'definitions', 'dependentSchemas']);\n\n/** Complexity limits for untrusted schemas; also enforced by the client before validation. */\nexport const MAX_JSON_SCHEMA_DEPTH = 128;\nexport const MAX_JSON_SCHEMA_NODES = 10_000;\n\n/**\n * Raw JSON values a single schema may contribute before generation widens it, and the total a whole\n * catalogue may contribute before generation widens the remainder. The node limit above counts only\n * schema-bearing keywords, so these bound the annotation and extension values it deliberately\n * ignores. They live here rather than with the generator so the CLI can apply them without loading\n * the converter.\n */\nexport const MAX_SCHEMA_VALUES = MAX_JSON_SCHEMA_NODES * 10;\nexport const MAX_CATALOG_VALUES = MAX_SCHEMA_VALUES * 10;\n\nclass Unconvertible extends Error {}\n\n/**\n * Bounds the work a validator or type generator can be asked to do for an untrusted schema.\n * Only schema-bearing keywords are walked, so deeply nested annotation data such as `default`\n * or `examples` does not count. The counted nodes are returned so callers can also budget\n * across a whole catalogue rather than one schema at a time.\n *\n * The keyword lists are intentionally wider than the conversion sets above: this walk has to\n * reach every position that can carry validation rules, including `dependencies`,\n * `prefixItems`, and `contentSchema`.\n */\nexport function jsonSchemaComplexity(schema: unknown): {\n error?: string;\n limit?: 'depth' | 'nodes';\n nodes: number;\n} {\n const seen = new Set<object>();\n let nodes = 0;\n const stack = [{ value: schema, depth: 0 }];\n const schemaMapKeywords = [\n '$defs',\n 'definitions',\n 'properties',\n 'patternProperties',\n 'dependentSchemas',\n 'dependencies',\n ];\n const schemaArrayKeywords = ['prefixItems', 'allOf', 'anyOf', 'oneOf', 'items'];\n const schemaKeywords = [\n 'additionalProperties',\n 'unevaluatedProperties',\n 'additionalItems',\n 'unevaluatedItems',\n 'items',\n 'contains',\n 'propertyNames',\n 'not',\n 'if',\n 'then',\n 'else',\n 'contentSchema',\n ];\n\n while (stack.length > 0) {\n const { value, depth } = stack.pop()!;\n if (value === null || typeof value !== 'object' || Array.isArray(value) || seen.has(value)) continue;\n seen.add(value);\n\n nodes += 1;\n if (depth > MAX_JSON_SCHEMA_DEPTH) {\n return {\n error: `JSON Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`,\n limit: 'depth',\n nodes,\n };\n }\n if (nodes > MAX_JSON_SCHEMA_NODES) {\n return {\n error: `JSON Schema exceeds the maximum node count of ${MAX_JSON_SCHEMA_NODES}`,\n limit: 'nodes',\n nodes,\n };\n }\n\n const record = value as Record<string, unknown>;\n for (const keyword of schemaMapKeywords) {\n const schemas = record[keyword];\n if (schemas && typeof schemas === 'object' && !Array.isArray(schemas)) {\n for (const child of Object.values(schemas)) stack.push({ value: child, depth: depth + 1 });\n }\n }\n for (const keyword of schemaArrayKeywords) {\n const schemas = record[keyword];\n if (Array.isArray(schemas)) {\n for (const child of schemas) stack.push({ value: child, depth: depth + 1 });\n }\n }\n for (const keyword of schemaKeywords) {\n if (record[keyword] !== undefined) stack.push({ value: record[keyword], depth: depth + 1 });\n }\n }\n\n return { nodes };\n}\n\n/**\n * Counts every value in a raw schema and stops once `limit` is exceeded. Unlike\n * {@link jsonSchemaComplexity}, which counts only schema-bearing keywords, this covers\n * annotation and extension data and boolean subschema entries, so callers that copy or transfer\n * the whole value can bound that work rather than the validation work a schema describes.\n *\n * Children are pulled one at a time, so a container wider than the budget is never expanded.\n * Values already seen are counted once, matching how this walk treats cycles.\n */\nexport function countJsonValues(value: unknown, limit: number): number {\n const seen = new Set<object>();\n const frames: Array<Generator<unknown>> = [];\n let nodes = 0;\n\n function count(current: unknown): boolean {\n if (++nodes > limit) return false;\n if (current === null || typeof current !== 'object' || seen.has(current)) return true;\n seen.add(current);\n frames.push(containerValues(current));\n return true;\n }\n\n if (!count(value)) return nodes;\n while (frames.length > 0) {\n const next = frames[frames.length - 1]!.next();\n if (next.done) frames.pop();\n else if (!count(next.value)) return nodes;\n }\n\n return nodes;\n}\n\n/** Yields a JSON container's children without materialising them. */\nfunction* containerValues(value: object): Generator<unknown> {\n if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index += 1) yield value[index];\n return;\n }\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key)) yield Reflect.get(value, key);\n }\n}\n\n/**\n * Converts a 2019-09 schema (e.g. from zod v3) into 2020-12 form. Tuples are the\n * only structural difference handled: array-form `items` becomes `prefixItems`,\n * and `additionalItems` becomes `items`.\n *\n * Returns `undefined` when the schema does not declare 2019-09, or relies on\n * features this conversion cannot preserve (`$recursiveRef`/`$recursiveAnchor`,\n * `$ref` pointers into tuple members, embedded `$schema` declarations,\n * `unevaluatedItems`, `prefixItems`, or `contentSchema`), or exceeds the depth/node limits.\n * Callers should then keep the original.\n */\nexport function toJsonSchema2020<T extends { $schema?: string }>(schema: T): T | undefined {\n if (!schema.$schema || !JSON_SCHEMA_2019_09.test(schema.$schema)) return undefined;\n try {\n return { ...(rewrite(schema, 0, { nodes: 0 }, true) as T), $schema: JSON_SCHEMA_2020_12 };\n } catch (error) {\n if (error instanceof Unconvertible) return undefined;\n throw error;\n }\n}\n\nfunction checkBudget(depth: number, budget: { nodes: number }) {\n if (depth > MAX_JSON_SCHEMA_DEPTH || ++budget.nodes > MAX_JSON_SCHEMA_NODES) throw new Unconvertible();\n}\n\n/** Rewrites a value in a subschema position. Only known schema keywords are walked; everything else is copied as-is. */\nfunction rewrite(schema: unknown, depth: number, budget: { nodes: number }, isRoot = false): unknown {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return schema;\n checkBudget(depth, budget);\n\n const out: Record<string, unknown> = { ...schema };\n // Embedded resources may declare their own dialect. unevaluatedItems interacts with contains (including via\n // in-place applicators) differently in 2020-12, prefixItems is an annotation in 2019-09 but an assertion in\n // 2020-12, and contentSchema is not walked. zod v3 emits none of these, so decline rather than risk a change.\n if (!isRoot && '$schema' in out) throw new Unconvertible();\n if ('$recursiveRef' in out || '$recursiveAnchor' in out) throw new Unconvertible();\n if ('unevaluatedItems' in out || 'prefixItems' in out || 'contentSchema' in out) throw new Unconvertible();\n if (typeof out.$ref === 'string' && /\\/(items\\/\\d+|additionalItems)(\\/|$)/.test(out.$ref)) {\n throw new Unconvertible();\n }\n\n for (const [key, child] of Object.entries(out)) {\n if (SCHEMA_KEYWORDS.has(key)) {\n out[key] = Array.isArray(child)\n ? (checkBudget(depth + 1, budget), child.map(item => rewrite(item, depth + 2, budget)))\n : rewrite(child, depth + 1, budget);\n } else if (SCHEMA_ARRAY_KEYWORDS.has(key) && Array.isArray(child)) {\n checkBudget(depth + 1, budget);\n out[key] = child.map(item => rewrite(item, depth + 2, budget));\n } else if (SCHEMA_MAP_KEYWORDS.has(key) && child && typeof child === 'object' && !Array.isArray(child)) {\n checkBudget(depth + 1, budget);\n out[key] = Object.fromEntries(\n Object.entries(child).map(([name, sub]) => [name, rewrite(sub, depth + 2, budget)]),\n );\n }\n }\n if (!Array.isArray(out.items)) return out;\n\n out.prefixItems = out.items;\n if ('additionalItems' in out) out.items = out.additionalItems;\n else delete out.items;\n delete out.additionalItems;\n return out;\n}\n"],"mappings":"AAyBA,MAAa,wBAAwB;;;;;;;;AASrC,MAAa,oBAAoB,wBAAwB;AACzD,MAAa,qBAAqB,oBAAoB;;;;;;;;;;;AActD,SAAgB,qBAAqB,QAInC;CACA,MAAM,uBAAO,IAAI,IAAY;CAC7B,IAAI,QAAQ;CACZ,MAAM,QAAQ,CAAC;EAAE,OAAO;EAAQ,OAAO;CAAE,CAAC;CAC1C,MAAM,oBAAoB;EACxB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,sBAAsB;EAAC;EAAe;EAAS;EAAS;EAAS;CAAO;CAC9E,MAAM,iBAAiB;EACrB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,EAAE,OAAO,UAAU,MAAM,IAAI;EACnC,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,KAAK,IAAI,KAAK,GAAG;EAC5F,KAAK,IAAI,KAAK;EAEd,SAAS;EACT,IAAI,QAAA,KACF,OAAO;GACL,OAAO;GACP,OAAO;GACP;EACF;EAEF,IAAI,QAAA,KACF,OAAO;GACL,OAAO,iDAAiD;GACxD,OAAO;GACP;EACF;EAGF,MAAM,SAAS;EACf,KAAK,MAAM,WAAW,mBAAmB;GACvC,MAAM,UAAU,OAAO;GACvB,IAAI,WAAW,OAAO,YAAY,YAAY,CAAC,MAAM,QAAQ,OAAO,GAClE,KAAK,MAAM,SAAS,OAAO,OAAO,OAAO,GAAG,MAAM,KAAK;IAAE,OAAO;IAAO,OAAO,QAAQ;GAAE,CAAC;EAE7F;EACA,KAAK,MAAM,WAAW,qBAAqB;GACzC,MAAM,UAAU,OAAO;GACvB,IAAI,MAAM,QAAQ,OAAO,GACvB,KAAK,MAAM,SAAS,SAAS,MAAM,KAAK;IAAE,OAAO;IAAO,OAAO,QAAQ;GAAE,CAAC;EAE9E;EACA,KAAK,MAAM,WAAW,gBACpB,IAAI,OAAO,aAAa,KAAA,GAAW,MAAM,KAAK;GAAE,OAAO,OAAO;GAAU,OAAO,QAAQ;EAAE,CAAC;CAE9F;CAEA,OAAO,EAAE,MAAM;AACjB;;;;;;;;;;AAWA,SAAgB,gBAAgB,OAAgB,OAAuB;CACrE,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,SAAoC,CAAC;CAC3C,IAAI,QAAQ;CAEZ,SAAS,MAAM,SAA2B;EACxC,IAAI,EAAE,QAAQ,OAAO,OAAO;EAC5B,IAAI,YAAY,QAAQ,OAAO,YAAY,YAAY,KAAK,IAAI,OAAO,GAAG,OAAO;EACjF,KAAK,IAAI,OAAO;EAChB,OAAO,KAAK,gBAAgB,OAAO,CAAC;EACpC,OAAO;CACT;CAEA,IAAI,CAAC,MAAM,KAAK,GAAG,OAAO;CAC1B,OAAO,OAAO,SAAS,GAAG;EACxB,MAAM,OAAO,OAAO,OAAO,SAAS,EAAE,CAAE,KAAK;EAC7C,IAAI,KAAK,MAAM,OAAO,IAAI;OACrB,IAAI,CAAC,MAAM,KAAK,KAAK,GAAG,OAAO;CACtC;CAEA,OAAO;AACT;;AAGA,UAAU,gBAAgB,OAAmC;CAC3D,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG,MAAM,MAAM;EAClE;CACF;CACA,KAAK,MAAM,OAAO,OAChB,IAAI,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,GAAG,MAAM,QAAQ,IAAI,OAAO,GAAG;AAEtF"}
@@ -1,6 +1,6 @@
1
- import { i as jsonSchemaComplexity, n as MAX_SCHEMA_VALUES, r as countJsonValues, t as MAX_CATALOG_VALUES } from "./json-schema-dialect-B5B7l9Po.js";
1
+ import { i as jsonSchemaComplexity, n as MAX_SCHEMA_VALUES, r as countJsonValues, t as MAX_CATALOG_VALUES } from "./json-schema-dialect-CdIOPBiC.js";
2
2
  import { compile } from "json-schema-to-typescript";
3
- //#region src/cli/typegen.ts
3
+ // src/cli/typegen.ts
4
4
  const maps = /* @__PURE__ */ new Set([
5
5
  "properties",
6
6
  "patternProperties",
@@ -358,7 +358,6 @@ async function generateToolTypes(catalog) {
358
358
  warnings
359
359
  };
360
360
  }
361
- //#endregion
362
361
  export { TypegenError, generateToolTypes };
363
362
 
364
- //# sourceMappingURL=typegen-CLDjVF16.js.map
363
+ //# sourceMappingURL=typegen-B5dH_z0t.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"typegen-CLDjVF16.js","names":[],"sources":["../../src/cli/typegen.ts"],"sourcesContent":["import { compile } from 'json-schema-to-typescript';\nimport type { SerializableMCPToolCatalog } from '../client/types';\nimport {\n countJsonValues,\n jsonSchemaComplexity,\n MAX_CATALOG_VALUES,\n MAX_JSON_SCHEMA_DEPTH,\n MAX_SCHEMA_VALUES,\n} from '../shared/json-schema-dialect';\n\ntype Schema = boolean | Record<string, unknown>;\n\nconst maps = new Set(['properties', 'patternProperties', 'definitions', '$defs', 'dependentSchemas']);\nconst singles = new Set([\n 'additionalProperties',\n 'additionalItems',\n 'contains',\n 'not',\n 'if',\n 'then',\n 'else',\n 'propertyNames',\n 'unevaluatedProperties',\n 'unevaluatedItems',\n]);\nconst lists = new Set(['allOf', 'anyOf', 'oneOf', 'prefixItems']);\nconst annotations = new Set([\n 'title',\n 'description',\n '$comment',\n 'default',\n 'examples',\n 'deprecated',\n 'readOnly',\n 'writeOnly',\n '$schema',\n]);\n/** Keywords whose value must be a string. */\nconst strings = new Set([\n 'title',\n 'description',\n '$comment',\n '$schema',\n '$id',\n '$anchor',\n '$dynamicRef',\n 'format',\n 'pattern',\n]);\n/** Keywords whose value must be a boolean. */\nconst booleans = new Set(['deprecated', 'readOnly', 'writeOnly', 'uniqueItems']);\n/** Keywords whose value must be a number, with `multipleOf` additionally positive. */\nconst bounds = new Set(['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'multipleOf']);\n/** Keywords whose value must be a non-negative integer. */\nconst counts = new Set(['minLength', 'maxLength', 'minProperties', 'maxProperties', 'minContains', 'maxContains']);\nconst supported = new Set([\n 'type',\n 'properties',\n 'definitions',\n '$defs',\n 'required',\n 'items',\n 'additionalItems',\n 'additionalProperties',\n 'enum',\n 'const',\n 'allOf',\n 'anyOf',\n 'oneOf',\n '$ref',\n 'minItems',\n 'maxItems',\n 'format',\n 'pattern',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'maximum',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n]);\nconst types = new Set(['object', 'array', 'string', 'number', 'integer', 'boolean', 'null']);\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction count(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n\n/**\n * Generation failure whose message is safe to surface: it is built from server and tool names,\n * keyword names, and positions, so it never carries schema values or transport details.\n */\nexport class TypegenError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TypegenError';\n }\n}\n\nfunction fail(reason: string, position: string): never {\n throw new TypegenError(`${reason} at ${position}`);\n}\n\n// JSON roundtripping is not enough: schema object insertion order affects declaration order.\nfunction canonical(value: unknown, position: string, ancestors = new Set<object>(), depth = 0): unknown {\n if (depth > MAX_JSON_SCHEMA_DEPTH) fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value !== 'object') fail('Schema contains a value that is not JSON', position);\n if (ancestors.has(value)) fail('Schema contains a circular reference', position);\n ancestors.add(value);\n const result = Array.isArray(value)\n ? value.map(item => canonical(item, position, ancestors, depth + 1))\n : Object.fromEntries(\n Object.keys(value)\n .sort()\n .map(key => [key, canonical(Reflect.get(value, key), position, ancestors, depth + 1)]),\n );\n ancestors.delete(value);\n return result;\n}\n\nfunction prepare(raw: unknown, position: string, warnings: string[]): Schema {\n const root = canonical(raw, position);\n const locations = new Map<string, Schema>();\n const references: string[] = [];\n const pointer = (part: string) => part.replace(/~/g, '~0').replace(/\\//g, '~1');\n\n function visit(value: unknown, path: string): Schema {\n if (typeof value === 'boolean') {\n locations.set(path, value);\n return value;\n }\n const schema = object(value) ? value : undefined;\n locations.set(path, schema ?? true);\n const nodePosition = `${position}/schema[${locations.size - 1}]`;\n if (!schema) {\n warnings.push(`Schema is not an object at ${nodePosition}; widened to unknown`);\n return true;\n }\n const output: Record<string, unknown> = Object.create(null);\n const reasons: string[] = [];\n const invalid = (key: string) => reasons.push(`invalid ${JSON.stringify(key)} value`);\n for (const [key, entry] of Object.entries(schema)) {\n const here = `${path}/${pointer(key)}`;\n // Annotations never reach the emitted type, so a malformed one cannot widen or fail it.\n if (annotations.has(key)) continue;\n if (!supported.has(key)) reasons.push(`unsupported keyword ${JSON.stringify(key)}`);\n // A keyword with a value outside its allowed shape widens this schema rather than failing\n // the run: one sloppy tool must not stop generation for every other server.\n if (strings.has(key) && typeof entry !== 'string') {\n invalid(key);\n continue;\n }\n if (booleans.has(key) && typeof entry !== 'boolean') {\n invalid(key);\n continue;\n }\n if (bounds.has(key) && (typeof entry !== 'number' || (key === 'multipleOf' && entry <= 0))) {\n invalid(key);\n continue;\n }\n if (counts.has(key) && !count(entry)) {\n invalid(key);\n continue;\n }\n if (maps.has(key)) {\n if (!object(entry)) {\n invalid(key);\n continue;\n }\n output[key] = Object.fromEntries(\n Object.entries(entry).map(([name, child]) => [name, visit(child, `${here}/${pointer(name)}`)]),\n );\n } else if (singles.has(key)) {\n output[key] = visit(entry, here);\n } else if (lists.has(key) || (key === 'items' && Array.isArray(entry))) {\n if (!Array.isArray(entry) || entry.length === 0) {\n invalid(key);\n continue;\n }\n output[key] = entry.map((child, index) => visit(child, `${here}/${index}`));\n } else if (key === 'items') {\n output[key] = visit(entry, here);\n } else if (key === '$ref') {\n if (typeof entry !== 'string') {\n invalid(key);\n continue;\n }\n if (entry === '#' || entry.startsWith('#/')) {\n references.push(entry);\n output[key] = entry;\n } else {\n reasons.push('external reference');\n }\n } else if (key === 'type') {\n const entries = Array.isArray(entry) ? entry : [entry];\n if (!entries.length || entries.some(type => typeof type !== 'string' || !types.has(type))) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'required') {\n if (\n !Array.isArray(entry) ||\n entry.some(name => typeof name !== 'string') ||\n new Set(entry).size !== entry.length\n ) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'enum') {\n if (!Array.isArray(entry) || entry.length === 0) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'minItems' || key === 'maxItems') {\n if (!count(entry)) {\n invalid(key);\n continue;\n }\n if (entry > 100) reasons.push(`${JSON.stringify(key)} bound above 100`);\n output[key] = entry;\n } else if (key === 'const') {\n output[key] = entry;\n }\n }\n if (reasons.length) {\n const reason = reasons.join('; ');\n warnings.push(`${reason.charAt(0).toUpperCase()}${reason.slice(1)} at ${nodePosition}; widened to unknown`);\n // Keep reference targets even when their containing schema cannot be represented.\n return { ...output, tsType: 'unknown' };\n }\n return output;\n }\n\n const result = visit(root, '');\n for (const ref of references) {\n let target: string;\n try {\n target = decodeURIComponent(ref.slice(1));\n } catch {\n fail('Local reference is not a valid URI fragment', position);\n }\n if (!locations.has(target) || /~(?![01])/u.test(target))\n fail(`Unresolved local reference ${JSON.stringify(ref)}`, position);\n }\n // Reference/combinator-only cycles emit illegal aliases such as type X = X.\n // Properties and array items guard recursion and may refer back to their container.\n const active = new Set<string>();\n const complete = new Set<string>();\n function checkCycle(path: string, depth = 0): void {\n if (depth > MAX_JSON_SCHEMA_DEPTH) fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (active.has(path)) fail('Unresolvable recursive schema', position);\n if (complete.has(path)) return;\n active.add(path);\n const schema = locations.get(path);\n if (object(schema)) {\n if (typeof schema.$ref === 'string' && (schema.$ref === '#' || schema.$ref.startsWith('#/'))) {\n checkCycle(decodeURIComponent(schema.$ref.slice(1)), depth + 1);\n }\n for (const key of ['allOf', 'anyOf', 'oneOf']) {\n const children = schema[key];\n if (Array.isArray(children)) children.forEach((_, index) => checkCycle(`${path}/${key}/${index}`, depth + 1));\n }\n }\n active.delete(path);\n complete.add(path);\n }\n for (const path of locations.keys()) checkCycle(path);\n return result;\n}\n\nfunction identifier(name: string): string {\n const normalized = name\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/ +/)\n .map(part => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n return `Server${normalized || 'Unnamed'}`;\n}\n\n/** Internal catalog-to-source boundary. No connections, loading, or filesystem writes. */\nexport async function generateToolTypes(\n catalog: SerializableMCPToolCatalog,\n): Promise<{ source: string; warnings: string[] }> {\n const declarations: string[] = [];\n const servers: string[] = [];\n const warnings: string[] = [];\n const serverNames = new Map<string, string>();\n const flatNames = new Set<string>();\n let schemaIndex = 0;\n const budget = { values: 0 };\n\n function widen(name: string, position: string, reason: string): string {\n warnings.push(`${reason} at ${position}; widened to unknown`);\n declarations.push(`export type ${name} = unknown;\\n`);\n return name;\n }\n\n async function convert(raw: unknown, position: string): Promise<string> {\n const name = `ToolSchema${++schemaIndex}`;\n // The value count comes first and gates the walk below: `jsonSchemaComplexity` expands the\n // schema-bearing containers it visits, so it must only ever see a schema already bounded by\n // value. An over-budget schema is then widened without being copied, walked, or converted.\n const values = countJsonValues(raw, MAX_SCHEMA_VALUES);\n budget.values += values;\n if (values > MAX_SCHEMA_VALUES) {\n return widen(name, position, `Schema exceeds the maximum value count of ${MAX_SCHEMA_VALUES}`);\n }\n if (budget.values > MAX_CATALOG_VALUES) {\n return widen(name, position, `Catalogue exceeds the maximum value count of ${MAX_CATALOG_VALUES}`);\n }\n const { error, limit } = jsonSchemaComplexity(raw);\n // Depth is a structural violation, not merely an expensive schema: keep failing it.\n if (limit === 'depth') fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (error) return widen(name, position, error);\n const schema = prepare(raw, position, warnings);\n if (typeof schema === 'boolean') {\n declarations.push(`export type ${name} = ${schema ? 'unknown' : 'never'};\\n`);\n } else {\n const names = new WeakMap<object, string>();\n let nested = 0;\n try {\n declarations.push(\n await compile({ ...schema, title: name }, name, {\n bannerComment: '',\n unknownAny: true,\n enableConstEnums: false,\n $refOptions: { resolve: { external: false, file: false, http: false } },\n customName: value => {\n if (value.title === name) return name;\n if (!names.has(value)) names.set(value, `${name}Value${++nested}`);\n return names.get(value);\n },\n }),\n );\n } catch {\n // The converter is a black box: anything it refuses is a portion we cannot represent, and\n // one such tool must not stop generation for every other server.\n return widen(name, position, 'Schema conversion failed');\n }\n }\n return name;\n }\n\n for (const server of Object.keys(catalog).sort()) {\n const serverName = identifier(server);\n const collision = serverNames.get(serverName);\n if (collision !== undefined)\n throw new TypegenError(\n `Server interface name collision between ${JSON.stringify(collision)} and ${JSON.stringify(server)}`,\n );\n serverNames.set(serverName, server);\n const tools: string[] = [];\n for (const tool of Object.keys(catalog[server]!).sort()) {\n const flat = `${server}_${tool}`;\n if (flatNames.has(flat)) throw new TypegenError(`Flattened tool name collision for ${JSON.stringify(flat)}`);\n flatNames.add(flat);\n const definition = catalog[server]![tool]!;\n const position = `server ${JSON.stringify(server)} tool ${JSON.stringify(tool)}`;\n const input = await convert(definition.inputSchema, `${position} input`);\n const output =\n definition.outputSchema === undefined\n ? 'unknown'\n : await convert(definition.outputSchema, `${position} output`);\n tools.push(` ${JSON.stringify(tool)}: { input: ${input}; output: ${output} };`);\n }\n declarations.push(`export interface ${serverName} {\\n tools: {\\n${tools.join('\\n')}\\n };\\n}\\n`);\n servers.push(` ${JSON.stringify(server)}: ${serverName};`);\n }\n return {\n source: `// Generated MCP tool contracts. Regenerate when server schemas change.\\n\\n${declarations.join('\\n')}\\nexport interface MCPServers {\\n${servers.join('\\n')}\\n}\\n`,\n warnings,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"typegen-B5dH_z0t.js","names":[],"sources":["../../src/cli/typegen.ts"],"sourcesContent":["import { compile } from 'json-schema-to-typescript';\nimport type { SerializableMCPToolCatalog } from '../client/types';\nimport {\n countJsonValues,\n jsonSchemaComplexity,\n MAX_CATALOG_VALUES,\n MAX_JSON_SCHEMA_DEPTH,\n MAX_SCHEMA_VALUES,\n} from '../shared/json-schema-dialect';\n\ntype Schema = boolean | Record<string, unknown>;\n\nconst maps = new Set(['properties', 'patternProperties', 'definitions', '$defs', 'dependentSchemas']);\nconst singles = new Set([\n 'additionalProperties',\n 'additionalItems',\n 'contains',\n 'not',\n 'if',\n 'then',\n 'else',\n 'propertyNames',\n 'unevaluatedProperties',\n 'unevaluatedItems',\n]);\nconst lists = new Set(['allOf', 'anyOf', 'oneOf', 'prefixItems']);\nconst annotations = new Set([\n 'title',\n 'description',\n '$comment',\n 'default',\n 'examples',\n 'deprecated',\n 'readOnly',\n 'writeOnly',\n '$schema',\n]);\n/** Keywords whose value must be a string. */\nconst strings = new Set([\n 'title',\n 'description',\n '$comment',\n '$schema',\n '$id',\n '$anchor',\n '$dynamicRef',\n 'format',\n 'pattern',\n]);\n/** Keywords whose value must be a boolean. */\nconst booleans = new Set(['deprecated', 'readOnly', 'writeOnly', 'uniqueItems']);\n/** Keywords whose value must be a number, with `multipleOf` additionally positive. */\nconst bounds = new Set(['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'multipleOf']);\n/** Keywords whose value must be a non-negative integer. */\nconst counts = new Set(['minLength', 'maxLength', 'minProperties', 'maxProperties', 'minContains', 'maxContains']);\nconst supported = new Set([\n 'type',\n 'properties',\n 'definitions',\n '$defs',\n 'required',\n 'items',\n 'additionalItems',\n 'additionalProperties',\n 'enum',\n 'const',\n 'allOf',\n 'anyOf',\n 'oneOf',\n '$ref',\n 'minItems',\n 'maxItems',\n 'format',\n 'pattern',\n 'minLength',\n 'maxLength',\n 'minimum',\n 'maximum',\n 'exclusiveMinimum',\n 'exclusiveMaximum',\n 'multipleOf',\n 'uniqueItems',\n 'minProperties',\n 'maxProperties',\n]);\nconst types = new Set(['object', 'array', 'string', 'number', 'integer', 'boolean', 'null']);\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction count(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n\n/**\n * Generation failure whose message is safe to surface: it is built from server and tool names,\n * keyword names, and positions, so it never carries schema values or transport details.\n */\nexport class TypegenError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TypegenError';\n }\n}\n\nfunction fail(reason: string, position: string): never {\n throw new TypegenError(`${reason} at ${position}`);\n}\n\n// JSON roundtripping is not enough: schema object insertion order affects declaration order.\nfunction canonical(value: unknown, position: string, ancestors = new Set<object>(), depth = 0): unknown {\n if (depth > MAX_JSON_SCHEMA_DEPTH) fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value !== 'object') fail('Schema contains a value that is not JSON', position);\n if (ancestors.has(value)) fail('Schema contains a circular reference', position);\n ancestors.add(value);\n const result = Array.isArray(value)\n ? value.map(item => canonical(item, position, ancestors, depth + 1))\n : Object.fromEntries(\n Object.keys(value)\n .sort()\n .map(key => [key, canonical(Reflect.get(value, key), position, ancestors, depth + 1)]),\n );\n ancestors.delete(value);\n return result;\n}\n\nfunction prepare(raw: unknown, position: string, warnings: string[]): Schema {\n const root = canonical(raw, position);\n const locations = new Map<string, Schema>();\n const references: string[] = [];\n const pointer = (part: string) => part.replace(/~/g, '~0').replace(/\\//g, '~1');\n\n function visit(value: unknown, path: string): Schema {\n if (typeof value === 'boolean') {\n locations.set(path, value);\n return value;\n }\n const schema = object(value) ? value : undefined;\n locations.set(path, schema ?? true);\n const nodePosition = `${position}/schema[${locations.size - 1}]`;\n if (!schema) {\n warnings.push(`Schema is not an object at ${nodePosition}; widened to unknown`);\n return true;\n }\n const output: Record<string, unknown> = Object.create(null);\n const reasons: string[] = [];\n const invalid = (key: string) => reasons.push(`invalid ${JSON.stringify(key)} value`);\n for (const [key, entry] of Object.entries(schema)) {\n const here = `${path}/${pointer(key)}`;\n // Annotations never reach the emitted type, so a malformed one cannot widen or fail it.\n if (annotations.has(key)) continue;\n if (!supported.has(key)) reasons.push(`unsupported keyword ${JSON.stringify(key)}`);\n // A keyword with a value outside its allowed shape widens this schema rather than failing\n // the run: one sloppy tool must not stop generation for every other server.\n if (strings.has(key) && typeof entry !== 'string') {\n invalid(key);\n continue;\n }\n if (booleans.has(key) && typeof entry !== 'boolean') {\n invalid(key);\n continue;\n }\n if (bounds.has(key) && (typeof entry !== 'number' || (key === 'multipleOf' && entry <= 0))) {\n invalid(key);\n continue;\n }\n if (counts.has(key) && !count(entry)) {\n invalid(key);\n continue;\n }\n if (maps.has(key)) {\n if (!object(entry)) {\n invalid(key);\n continue;\n }\n output[key] = Object.fromEntries(\n Object.entries(entry).map(([name, child]) => [name, visit(child, `${here}/${pointer(name)}`)]),\n );\n } else if (singles.has(key)) {\n output[key] = visit(entry, here);\n } else if (lists.has(key) || (key === 'items' && Array.isArray(entry))) {\n if (!Array.isArray(entry) || entry.length === 0) {\n invalid(key);\n continue;\n }\n output[key] = entry.map((child, index) => visit(child, `${here}/${index}`));\n } else if (key === 'items') {\n output[key] = visit(entry, here);\n } else if (key === '$ref') {\n if (typeof entry !== 'string') {\n invalid(key);\n continue;\n }\n if (entry === '#' || entry.startsWith('#/')) {\n references.push(entry);\n output[key] = entry;\n } else {\n reasons.push('external reference');\n }\n } else if (key === 'type') {\n const entries = Array.isArray(entry) ? entry : [entry];\n if (!entries.length || entries.some(type => typeof type !== 'string' || !types.has(type))) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'required') {\n if (\n !Array.isArray(entry) ||\n entry.some(name => typeof name !== 'string') ||\n new Set(entry).size !== entry.length\n ) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'enum') {\n if (!Array.isArray(entry) || entry.length === 0) {\n invalid(key);\n continue;\n }\n output[key] = entry;\n } else if (key === 'minItems' || key === 'maxItems') {\n if (!count(entry)) {\n invalid(key);\n continue;\n }\n if (entry > 100) reasons.push(`${JSON.stringify(key)} bound above 100`);\n output[key] = entry;\n } else if (key === 'const') {\n output[key] = entry;\n }\n }\n if (reasons.length) {\n const reason = reasons.join('; ');\n warnings.push(`${reason.charAt(0).toUpperCase()}${reason.slice(1)} at ${nodePosition}; widened to unknown`);\n // Keep reference targets even when their containing schema cannot be represented.\n return { ...output, tsType: 'unknown' };\n }\n return output;\n }\n\n const result = visit(root, '');\n for (const ref of references) {\n let target: string;\n try {\n target = decodeURIComponent(ref.slice(1));\n } catch {\n fail('Local reference is not a valid URI fragment', position);\n }\n if (!locations.has(target) || /~(?![01])/u.test(target))\n fail(`Unresolved local reference ${JSON.stringify(ref)}`, position);\n }\n // Reference/combinator-only cycles emit illegal aliases such as type X = X.\n // Properties and array items guard recursion and may refer back to their container.\n const active = new Set<string>();\n const complete = new Set<string>();\n function checkCycle(path: string, depth = 0): void {\n if (depth > MAX_JSON_SCHEMA_DEPTH) fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (active.has(path)) fail('Unresolvable recursive schema', position);\n if (complete.has(path)) return;\n active.add(path);\n const schema = locations.get(path);\n if (object(schema)) {\n if (typeof schema.$ref === 'string' && (schema.$ref === '#' || schema.$ref.startsWith('#/'))) {\n checkCycle(decodeURIComponent(schema.$ref.slice(1)), depth + 1);\n }\n for (const key of ['allOf', 'anyOf', 'oneOf']) {\n const children = schema[key];\n if (Array.isArray(children)) children.forEach((_, index) => checkCycle(`${path}/${key}/${index}`, depth + 1));\n }\n }\n active.delete(path);\n complete.add(path);\n }\n for (const path of locations.keys()) checkCycle(path);\n return result;\n}\n\nfunction identifier(name: string): string {\n const normalized = name\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/ +/)\n .map(part => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n return `Server${normalized || 'Unnamed'}`;\n}\n\n/** Internal catalog-to-source boundary. No connections, loading, or filesystem writes. */\nexport async function generateToolTypes(\n catalog: SerializableMCPToolCatalog,\n): Promise<{ source: string; warnings: string[] }> {\n const declarations: string[] = [];\n const servers: string[] = [];\n const warnings: string[] = [];\n const serverNames = new Map<string, string>();\n const flatNames = new Set<string>();\n let schemaIndex = 0;\n const budget = { values: 0 };\n\n function widen(name: string, position: string, reason: string): string {\n warnings.push(`${reason} at ${position}; widened to unknown`);\n declarations.push(`export type ${name} = unknown;\\n`);\n return name;\n }\n\n async function convert(raw: unknown, position: string): Promise<string> {\n const name = `ToolSchema${++schemaIndex}`;\n // The value count comes first and gates the walk below: `jsonSchemaComplexity` expands the\n // schema-bearing containers it visits, so it must only ever see a schema already bounded by\n // value. An over-budget schema is then widened without being copied, walked, or converted.\n const values = countJsonValues(raw, MAX_SCHEMA_VALUES);\n budget.values += values;\n if (values > MAX_SCHEMA_VALUES) {\n return widen(name, position, `Schema exceeds the maximum value count of ${MAX_SCHEMA_VALUES}`);\n }\n if (budget.values > MAX_CATALOG_VALUES) {\n return widen(name, position, `Catalogue exceeds the maximum value count of ${MAX_CATALOG_VALUES}`);\n }\n const { error, limit } = jsonSchemaComplexity(raw);\n // Depth is a structural violation, not merely an expensive schema: keep failing it.\n if (limit === 'depth') fail(`Schema exceeds the maximum depth of ${MAX_JSON_SCHEMA_DEPTH}`, position);\n if (error) return widen(name, position, error);\n const schema = prepare(raw, position, warnings);\n if (typeof schema === 'boolean') {\n declarations.push(`export type ${name} = ${schema ? 'unknown' : 'never'};\\n`);\n } else {\n const names = new WeakMap<object, string>();\n let nested = 0;\n try {\n declarations.push(\n await compile({ ...schema, title: name }, name, {\n bannerComment: '',\n unknownAny: true,\n enableConstEnums: false,\n $refOptions: { resolve: { external: false, file: false, http: false } },\n customName: value => {\n if (value.title === name) return name;\n if (!names.has(value)) names.set(value, `${name}Value${++nested}`);\n return names.get(value);\n },\n }),\n );\n } catch {\n // The converter is a black box: anything it refuses is a portion we cannot represent, and\n // one such tool must not stop generation for every other server.\n return widen(name, position, 'Schema conversion failed');\n }\n }\n return name;\n }\n\n for (const server of Object.keys(catalog).sort()) {\n const serverName = identifier(server);\n const collision = serverNames.get(serverName);\n if (collision !== undefined)\n throw new TypegenError(\n `Server interface name collision between ${JSON.stringify(collision)} and ${JSON.stringify(server)}`,\n );\n serverNames.set(serverName, server);\n const tools: string[] = [];\n for (const tool of Object.keys(catalog[server]!).sort()) {\n const flat = `${server}_${tool}`;\n if (flatNames.has(flat)) throw new TypegenError(`Flattened tool name collision for ${JSON.stringify(flat)}`);\n flatNames.add(flat);\n const definition = catalog[server]![tool]!;\n const position = `server ${JSON.stringify(server)} tool ${JSON.stringify(tool)}`;\n const input = await convert(definition.inputSchema, `${position} input`);\n const output =\n definition.outputSchema === undefined\n ? 'unknown'\n : await convert(definition.outputSchema, `${position} output`);\n tools.push(` ${JSON.stringify(tool)}: { input: ${input}; output: ${output} };`);\n }\n declarations.push(`export interface ${serverName} {\\n tools: {\\n${tools.join('\\n')}\\n };\\n}\\n`);\n servers.push(` ${JSON.stringify(server)}: ${serverName};`);\n }\n return {\n source: `// Generated MCP tool contracts. Regenerate when server schemas change.\\n\\n${declarations.join('\\n')}\\nexport interface MCPServers {\\n${servers.join('\\n')}\\n}\\n`,\n warnings,\n };\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ name: mastra-mcp
3
3
  description: Documentation for @mastra/mcp. Use when working with @mastra/mcp APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/mcp"
6
- version: "2.6.0-alpha.0"
6
+ version: "2.6.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.6.0-alpha.0",
2
+ "version": "2.6.0-alpha.1",
3
3
  "package": "@mastra/mcp",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -214,7 +214,7 @@ The client speaks the MCP `2026-07-28` revision. On connect it asks the server w
214
214
 
215
215
  **env** (`Record<string, string>`): For Stdio servers: Environment variables to set for the command.
216
216
 
217
- **inheritDefaultEnv** (`boolean`): For Stdio servers: Whether the subprocess environment starts from the MCP SDK's default inherited environment. The default is a curated whitelist, not the full process environment: on POSIX it inherits HOME, LOGNAME, PATH, SHELL, TERM, and USER; on Windows it inherits APPDATA, HOMEDRIVE, HOMEPATH, LOCALAPPDATA, PATH, PROCESSOR\_ARCHITECTURE, SYSTEMDRIVE, SYSTEMROOT, TEMP, USERNAME, and USERPROFILE. When set to false, only the variables explicitly listed in env are passed to the subprocess. Note that a subprocess without PATH may fail to spawn commands that are not absolute paths. (Default: `true`)
217
+ **inheritDefaultEnv** (`boolean`): For Stdio servers: Whether the subprocess environment starts from the MCP SDK's default inherited environment. The default is a curated whitelist, not the full process environment: on POSIX it inherits HOME, LOGNAME, PATH, SHELL, TERM, and USER; on Windows it inherits APPDATA, HOMEDRIVE, HOMEPATH, LOCALAPPDATA, PATH, PROCESSOR_ARCHITECTURE, SYSTEMDRIVE, SYSTEMROOT, TEMP, USERNAME, and USERPROFILE. When set to false, only the variables explicitly listed in env are passed to the subprocess. Note that a subprocess without PATH may fail to spawn commands that are not absolute paths. (Default: `true`)
218
218
 
219
219
  **url** (`URL`): For HTTP servers: The URL of the server.
220
220
 
@@ -234,7 +234,7 @@ The client speaks the MCP `2026-07-28` revision. On connect it asks the server w
234
234
 
235
235
  **capabilities** (`MCPClientCapabilities`): Client capabilities to advertise: elicitation and extensions. elicitation is only accepted together with an inputRequests handler and defaults to form support when a handler is configured. Roots and sampling are not supported.
236
236
 
237
- **inputRequests** (`MCPInputRequestHandler`): Answers input requests from this server. When a tool, resource or prompt call ends as input\_required, the handler is called with each embedded request and the client retries the call with the answers. Without a handler an input\_required result surfaces as an error. See Answering input requests below.
237
+ **inputRequests** (`MCPInputRequestHandler`): Answers input requests from this server. When a tool, resource or prompt call ends as input_required, the handler is called with each embedded request and the client retries the call with the answers. Without a handler an input_required result surfaces as an error. See Answering input requests below.
238
238
 
239
239
  **authProvider** (`OAuthClientProvider`): For HTTP servers: OAuth authentication provider for automatic token refresh and OAuth flow management. Use MCPOAuthClientProvider for a ready-to-use implementation.
240
240
 
@@ -968,7 +968,7 @@ The client doesn't receive notifications when the server's event list changes ye
968
968
 
969
969
  #### `events.subscribe(serverName, eventName, args?, options?)`
970
970
 
971
- Starts a subscription and resolves once the server confirms it. Errors such as an unknown event, invalid arguments, or a forbidden subscription reject the returned promise. A new subscription starts at the point the server accepts it, so occurrences from before that point are not delivered unless `options.cursor` resumes from an earlier position. Under webhook delivery the promise can resolve after that point: the client answers `503` for a delivery it can't route yet, and the server retries it.
971
+ Starts a subscription and resolves once the server confirms it. Errors such as an unknown event, invalid arguments, or a forbidden subscription reject the returned promise. A new subscription starts at the point the server accepts it, so occurrences from before that point aren't delivered unless `options.cursor` resumes from an earlier position. Under webhook delivery the promise can resolve after that point: the client answers `503` for a delivery it can't route yet, and the server retries it.
972
972
 
973
973
  ```typescript
974
974
  async subscribe(
@@ -981,7 +981,7 @@ async subscribe(
981
981
 
982
982
  The client picks the first mode the event offers in this order: `webhook` (only when the client has [`webhook` settings](#webhook-delivery)), `push` (a long-lived `events/stream` request), then `poll` (repeated `events/poll` requests). Pass `options.delivery` to force a mode.
983
983
 
984
- **delivery** (`'webhook' | 'push' | 'poll'`): Forces a delivery mode. When the event doesn't offer it, or for webhook without client webhook settings, subscribe() rejects with MCP\_CLIENT\_SUBSCRIBE\_EVENT\_FAILED and error.cause.id is MCP\_EVENTS\_NO\_COMPATIBLE\_DELIVERY\_MODE or MCP\_EVENTS\_WEBHOOK\_NOT\_CONFIGURED.
984
+ **delivery** (`'webhook' | 'push' | 'poll'`): Forces a delivery mode. When the event doesn't offer it, or for webhook without client webhook settings, subscribe() rejects with MCP_CLIENT_SUBSCRIBE_EVENT_FAILED and error.cause.id is MCP_EVENTS_NO_COMPATIBLE_DELIVERY_MODE or MCP_EVENTS_WEBHOOK_NOT_CONFIGURED.
985
985
 
986
986
  **cursor** (`string | null`): Resumes from a cursor saved earlier. Omit or pass null to start from now.
987
987
 
@@ -997,7 +997,7 @@ The client picks the first mode the event offers in this order: `webhook` (only
997
997
 
998
998
  **dedupWindow** (`number`): Number of recent event ids remembered to drop duplicate occurrences. (Default: `1000`)
999
999
 
1000
- **maxBufferedEvents** (`number`): Most occurrences held while your loop isn't reading. When full, the oldest unread occurrence is dropped, the next one has truncated set, and onError receives MCP\_EVENTS\_BUFFER\_OVERFLOW. (Default: `1000`)
1000
+ **maxBufferedEvents** (`number`): Most occurrences held while your loop isn't reading. When full, the oldest unread occurrence is dropped, the next one has truncated set, and onError receives MCP_EVENTS_BUFFER_OVERFLOW. (Default: `1000`)
1001
1001
 
1002
1002
  **retry** (`{ initialDelayMs?: number; maxDelayMs?: number; factor?: number; maxAttempts?: number }`): Backoff with full jitter for transient failures. Defaults to 1000 ms initial delay, 30000 ms maximum, factor 2, unlimited retries.
1003
1003
 
@@ -1131,7 +1131,7 @@ If the subscription ends, for example because the server terminates it, each sub
1131
1131
 
1132
1132
  **coalesce** (`boolean`): Sets coalesceKey: 'mcp-events:\<key>' on event notifications, whatever the provider id. Pending notifications from one subscription then merge, so a burst that arrives before the agent reads its inbox keeps only the latest occurrence. When off, every occurrence is its own notification. (Default: `false`)
1133
1133
 
1134
- **tools** (`boolean | { servers: string[] }`): Gives the agent the mcp\_events\_list, mcp\_events\_subscribe and mcp\_events\_unsubscribe tools, which act on the current thread and require memory. Event descriptions and error messages from the server reach the model inside the same untrusted-data block as event data. Subscriptions made through the tools are lost on restart. Pass servers to limit them to those servers. (Default: `false`)
1134
+ **tools** (`boolean | { servers: string[] }`): Gives the agent the mcp_events_list, mcp_events_subscribe and mcp_events_unsubscribe tools, which act on the current thread and require memory. Event descriptions and error messages from the server reach the model inside the same untrusted-data block as event data. Subscriptions made through the tools are lost on restart. Pass servers to limit them to those servers. (Default: `false`)
1135
1135
 
1136
1136
  **onError** (`(error: unknown, info: { server: string; event: string; key: string }) => void`): Receives delivery, cursor store and subscription errors.
1137
1137
 
@@ -73,7 +73,7 @@ The constructor accepts an `MCPServerConfig` object with the following propertie
73
73
 
74
74
  **agents** (`Record<string, Agent>`): An object where keys are agent identifiers and values are Mastra Agent instances. Each agent will be automatically converted into a tool named ask\_\<agentIdentifier>. The agent \*\*must\*\* have a non-empty description string property defined in its constructor configuration. This description will be used in the tool's description. If an agent's description is missing or empty, an error will be thrown during MCPServer initialization.
75
75
 
76
- **workflows** (`Record<string, Workflow>`): An object where keys are workflow identifiers and values are Mastra Workflow instances. Each workflow is converted into a tool named run\_\<workflowKey>. The workflow's inputSchema becomes the tool's input schema. The workflow \*\*must\*\* have a non-empty description string property, which is used for the tool's description. If a workflow's description is missing or empty, an error will be thrown. The tool executes the workflow by calling workflow\.createRun() followed by run.start({ inputData: \<tool\_input> }). If a tool name derived from an agent or workflow (e.g., ask\_myAgent or run\_myWorkflow) collides with an explicitly defined tool name or another derived name, the explicitly defined tool takes precedence, and a warning is logged. Agents/workflows leading to subsequent collisions are skipped.
76
+ **workflows** (`Record<string, Workflow>`): An object where keys are workflow identifiers and values are Mastra Workflow instances. Each workflow is converted into a tool named run\_\<workflowKey>. The workflow's inputSchema becomes the tool's input schema. The workflow \*\*must\*\* have a non-empty description string property, which is used for the tool's description. If a workflow's description is missing or empty, an error will be thrown. The tool executes the workflow by calling workflow\.createRun() followed by run.start({ inputData: \<tool_input> }). If a tool name derived from an agent or workflow (e.g., ask_myAgent or run_myWorkflow) collides with an explicitly defined tool name or another derived name, the explicitly defined tool takes precedence, and a warning is logged. Agents/workflows leading to subsequent collisions are skipped.
77
77
 
78
78
  **description** (`string`): Optional description of what the MCP server does. Announced to MCP clients as part of the server's identity and returned in the registry server info.
79
79
 
@@ -89,7 +89,7 @@ The constructor accepts an `MCPServerConfig` object with the following propertie
89
89
 
90
90
  **fga** (`{ resourceMapping?: Partial<Record<'tool' | 'tools', { fgaResourceType: string; deriveId?: ({ user, resourceId, requestContext }) => string | undefined }>>; permissionMapping?: Record<string, string> }`): Overrides resource and permission mappings for this MCP server's tools/list and tools/call FGA checks. Use this when MCP authorization should be scoped differently from internal agent or workflow tool execution.
91
91
 
92
- **requestState** (`{ key?: string | Uint8Array; ttlSeconds?: number }`): Integrity protection for input\_required continuation state. key is an HMAC key of at least 32 bytes that every instance able to answer a continuation must share; ttlSeconds (default 600) is how long a suspended round stays answerable. Without a key the server generates one per process. See the Asking the caller for input section.
92
+ **requestState** (`{ key?: string | Uint8Array; ttlSeconds?: number }`): Integrity protection for input_required continuation state. key is an HMAC key of at least 32 bytes that every instance able to answer a continuation must share; ttlSeconds (default 600) is how long a suspended round stays answerable. Without a key the server generates one per process. See the Asking the caller for input section.
93
93
 
94
94
  **cacheHints** (`MCPServerCacheHints`): Cache hints (ttlMs / cacheScope) advertised on cacheable results, keyed by operation: 'tools/list', 'prompts/list', 'resources/list', 'resources/templates/list', 'resources/read' and 'server/discover'.
95
95
 
@@ -1464,7 +1464,7 @@ const ticketCreated = defineEvent({
1464
1464
  })
1465
1465
  ```
1466
1466
 
1467
- `authorize` runs on every `events/poll`, every `events/stream` open, and every webhook `events/subscribe`, including refreshes. An open stream isn't checked again until it reconnects, and a webhook subscription until its next refresh. A caller who loses access keeps receiving occurrences until then. FGA isn't applied to events; use `authorize` to restrict them.
1467
+ `authorize` runs on every `events/poll`, every `events/stream` open, and every webhook `events/subscribe`, including refreshes. An open stream isn't checked again until it reconnects, and a webhook subscription until its next refresh. A caller who loses access keeps receiving occurrences until then. Use `authorize` to restrict events because FGA doesn't apply to them.
1468
1468
 
1469
1469
  ### `defineEvent()` options
1470
1470
 
@@ -1584,7 +1584,7 @@ Records an occurrence, delivers it to matching push streams and webhook subscrip
1584
1584
  - Emitted events stay in the process that emitted them. Push streams, webhook subscriptions, and buffered polls only see events emitted by the same `MCPServer` instance, so a serverless or multi-instance deployment needs a `poll` source backed by shared storage.
1585
1585
  - The buffer is in memory. A restarted server treats earlier cursors as a gap and reports `truncated: true`.
1586
1586
  - Webhook delivery state (pending retries, suspension, verification results) is in memory and rebuilt when clients refresh.
1587
- - Changes to the list of event types aren't announced yet. The server doesn't advertise `listChanged` or send `notifications/events/list_changed`, because the MCP TypeScript SDK 2.2.0 doesn't carry the `eventsListChanged` filter on `subscriptions/listen`. Clients should re-run `events/list` to see changed event types.
1587
+ - Event-list change announcements require the `eventsListChanged` filter on `subscriptions/listen`, which the MCP TypeScript SDK version used by `@mastra/mcp` doesn't carry. Until that support is available, the server neither advertises `listChanged` nor sends `notifications/events/list_changed`. Clients should re-run `events/list` to see changed event types.
1588
1588
 
1589
1589
  ## Related information
1590
1590