diff --git a/src/browser.ts b/src/browser.ts index c4fd89a..d3f0598 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -1,4 +1,5 @@ // Browser-compatible exports -export * from "./schemas.js"; +export * from "./schemas/latest.js"; export * from "./shared/config.js"; +export * from "./shared/constants.js"; export * from "./types.js"; diff --git a/src/cli.ts b/src/cli.ts index 45780f9..5dc861c 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,8 +3,9 @@ export * from "./cli/init.js"; export * from "./cli/pack.js"; // Include all shared exports -export * from "./schemas.js"; +export * from "./schemas/latest.js"; export * from "./shared/config.js"; +export * from "./shared/constants.js"; export * from "./types.js"; // Include node exports since CLI needs them diff --git a/src/cli/init.ts b/src/cli/init.ts index 5c16885..a3ae0db 100644 --- a/src/cli/init.ts +++ b/src/cli/init.ts @@ -2,7 +2,7 @@ import { confirm, input, select } from "@inquirer/prompts"; import { existsSync, readFileSync, writeFileSync } from "fs"; import { basename, join, resolve } from "path"; -import { CURRENT_MANIFEST_VERSION } from "../schemas.js"; +import { LATEST_MANIFEST_VERSION } from "../shared/constants.js"; import type { McpbManifest } from "../types.js"; interface PackageJson { @@ -774,7 +774,7 @@ export function buildManifest( const { keywords, license, repository } = optionalFields; return { - manifest_version: CURRENT_MANIFEST_VERSION, + manifest_version: LATEST_MANIFEST_VERSION, name, ...(displayName && displayName !== name ? { display_name: displayName } diff --git a/src/cli/pack.ts b/src/cli/pack.ts index 4e3c670..58b3c1c 100644 --- a/src/cli/pack.ts +++ b/src/cli/pack.ts @@ -13,7 +13,10 @@ import { basename, join, relative, resolve, sep } from "path"; import { getAllFilesWithCount, readMcpbIgnorePatterns } from "../node/files.js"; import { validateManifest } from "../node/validate.js"; -import { CURRENT_MANIFEST_VERSION, McpbManifestSchema } from "../schemas.js"; +import { + LATEST_MANIFEST_SCHEMA, + LATEST_MANIFEST_VERSION, +} from "../shared/constants.js"; import { getLogger } from "../shared/log.js"; import { initExtension } from "./init.js"; @@ -92,7 +95,7 @@ export async function packExtension({ try { const manifestContent = readFileSync(manifestPath, "utf-8"); const manifestData = JSON.parse(manifestContent); - manifest = McpbManifestSchema.parse(manifestData); + manifest = LATEST_MANIFEST_SCHEMA.parse(manifestData); } catch (error) { logger.error("ERROR: Failed to parse manifest.json"); if (error instanceof Error) { @@ -102,12 +105,12 @@ export async function packExtension({ } const manifestVersion = manifest.manifest_version || manifest.dxt_version; - if (manifestVersion !== CURRENT_MANIFEST_VERSION) { + if (manifestVersion !== LATEST_MANIFEST_VERSION) { logger.error( - `ERROR: Manifest version mismatch. Expected "${CURRENT_MANIFEST_VERSION}", found "${manifestVersion}"`, + `ERROR: Manifest version mismatch. Expected "${LATEST_MANIFEST_VERSION}", found "${manifestVersion}"`, ); logger.error( - ` Please update the manifest_version in your manifest.json to "${CURRENT_MANIFEST_VERSION}"`, + ` Please update the manifest_version in your manifest.json to "${LATEST_MANIFEST_VERSION}"`, ); return false; } diff --git a/src/index.ts b/src/index.ts index eea22d7..62ada47 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export * from "./cli/unpack.js"; export * from "./node/files.js"; export * from "./node/sign.js"; export * from "./node/validate.js"; -export * from "./schemas.js"; +export * from "./schemas/latest.js"; export * from "./shared/config.js"; +export * from "./shared/constants.js"; export * from "./types.js"; diff --git a/src/node.ts b/src/node.ts index 3af29fb..12a7edb 100644 --- a/src/node.ts +++ b/src/node.ts @@ -4,6 +4,7 @@ export * from "./node/sign.js"; export * from "./node/validate.js"; // Include all shared exports -export * from "./schemas.js"; +export * from "./schemas/latest.js"; export * from "./shared/config.js"; +export * from "./shared/constants.js"; export * from "./types.js"; diff --git a/src/node/validate.ts b/src/node/validate.ts index 2f86e5e..7a94d53 100644 --- a/src/node/validate.ts +++ b/src/node/validate.ts @@ -6,8 +6,10 @@ import { join, resolve } from "path"; import prettyBytes from "pretty-bytes"; import { unpackExtension } from "../cli/unpack.js"; -import { McpbManifestSchema } from "../schemas.js"; -import { McpbManifestSchema as LooseMcpbManifestSchema } from "../schemas-loose.js"; +import { + LATEST_MANIFEST_SCHEMA, + LATEST_MANIFEST_SCHEMA_LOOSE, +} from "../shared/constants.js"; export function validateManifest(inputPath: string): boolean { try { @@ -22,7 +24,7 @@ export function validateManifest(inputPath: string): boolean { const manifestContent = readFileSync(manifestPath, "utf-8"); const manifestData = JSON.parse(manifestContent); - const result = McpbManifestSchema.safeParse(manifestData); + const result = LATEST_MANIFEST_SCHEMA.safeParse(manifestData); if (result.success) { console.log("Manifest schema validation passes!"); @@ -72,7 +74,7 @@ export async function cleanMcpb(inputPath: string) { const manifestPath = resolve(unpackPath, "manifest.json"); const originalManifest = await fs.readFile(manifestPath, "utf-8"); const manifestData = JSON.parse(originalManifest); - const result = LooseMcpbManifestSchema.safeParse(manifestData); + const result = LATEST_MANIFEST_SCHEMA_LOOSE.safeParse(manifestData); if (!result.success) { throw new Error( diff --git a/src/schemas.ts b/src/schemas/0.1.ts similarity index 87% rename from src/schemas.ts rename to src/schemas/0.1.ts index 50777b8..3ff5453 100644 --- a/src/schemas.ts +++ b/src/schemas/0.1.ts @@ -1,6 +1,6 @@ import * as z from "zod"; -export const CURRENT_MANIFEST_VERSION = "0.2"; +export const MANIFEST_VERSION = "0.1"; export const McpServerConfigSchema = z.strictObject({ command: z.string(), @@ -34,18 +34,16 @@ export const McpbManifestServerSchema = z.strictObject({ mcp_config: McpbManifestMcpConfigSchema, }); -export const McpbManifestCompatibilitySchema = z - .strictObject({ - claude_desktop: z.string().optional(), - platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(), - runtimes: z - .strictObject({ - python: z.string().optional(), - node: z.string().optional(), - }) - .optional(), - }) - .passthrough(); +export const McpbManifestCompatibilitySchema = z.strictObject({ + claude_desktop: z.string().optional(), + platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(), + runtimes: z + .strictObject({ + python: z.string().optional(), + node: z.string().optional(), + }) + .optional(), +}); export const McpbManifestToolSchema = z.strictObject({ name: z.string(), @@ -82,10 +80,10 @@ export const McpbManifestSchema = z .strictObject({ $schema: z.string().optional(), dxt_version: z - .string() + .literal(MANIFEST_VERSION) .optional() .describe("@deprecated Use manifest_version instead"), - manifest_version: z.string().optional(), + manifest_version: z.literal(MANIFEST_VERSION).optional(), name: z.string(), display_name: z.string().optional(), version: z.string(), @@ -105,7 +103,6 @@ export const McpbManifestSchema = z prompts_generated: z.boolean().optional(), keywords: z.array(z.string()).optional(), license: z.string().optional(), - privacy_policies: z.array(z.string()).optional(), compatibility: McpbManifestCompatibilitySchema.optional(), user_config: z .record(z.string(), McpbUserConfigurationOptionSchema) diff --git a/src/schemas/0.2.ts b/src/schemas/0.2.ts new file mode 100644 index 0000000..f5d4d03 --- /dev/null +++ b/src/schemas/0.2.ts @@ -0,0 +1,124 @@ +import * as z from "zod"; + +export const MANIFEST_VERSION = "0.2"; + +export const McpServerConfigSchema = z.strictObject({ + command: z.string(), + args: z.array(z.string()).optional(), + env: z.record(z.string(), z.string()).optional(), +}); + +export const McpbManifestAuthorSchema = z.strictObject({ + name: z.string(), + email: z.string().email().optional(), + url: z.string().url().optional(), +}); + +export const McpbManifestRepositorySchema = z.strictObject({ + type: z.string(), + url: z.string().url(), +}); + +export const McpbManifestPlatformOverrideSchema = + McpServerConfigSchema.partial(); + +export const McpbManifestMcpConfigSchema = McpServerConfigSchema.extend({ + platform_overrides: z + .record(z.string(), McpbManifestPlatformOverrideSchema) + .optional(), +}); + +export const McpbManifestServerSchema = z.strictObject({ + type: z.enum(["python", "node", "binary"]), + entry_point: z.string(), + mcp_config: McpbManifestMcpConfigSchema, +}); + +export const McpbManifestCompatibilitySchema = z.strictObject({ + claude_desktop: z.string().optional(), + platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(), + runtimes: z + .strictObject({ + python: z.string().optional(), + node: z.string().optional(), + }) + .optional(), +}); + +export const McpbManifestToolSchema = z.strictObject({ + name: z.string(), + description: z.string().optional(), +}); + +export const McpbManifestPromptSchema = z.strictObject({ + name: z.string(), + description: z.string().optional(), + arguments: z.array(z.string()).optional(), + text: z.string(), +}); + +export const McpbUserConfigurationOptionSchema = z.strictObject({ + type: z.enum(["string", "number", "boolean", "directory", "file"]), + title: z.string(), + description: z.string(), + required: z.boolean().optional(), + default: z + .union([z.string(), z.number(), z.boolean(), z.array(z.string())]) + .optional(), + multiple: z.boolean().optional(), + sensitive: z.boolean().optional(), + min: z.number().optional(), + max: z.number().optional(), +}); + +export const McpbUserConfigValuesSchema = z.record( + z.string(), + z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]), +); + +export const McpbManifestSchema = z + .strictObject({ + $schema: z.string().optional(), + dxt_version: z + .literal(MANIFEST_VERSION) + .optional() + .describe("@deprecated Use manifest_version instead"), + manifest_version: z.literal(MANIFEST_VERSION).optional(), + name: z.string(), + display_name: z.string().optional(), + version: z.string(), + description: z.string(), + long_description: z.string().optional(), + author: McpbManifestAuthorSchema, + repository: McpbManifestRepositorySchema.optional(), + homepage: z.string().url().optional(), + documentation: z.string().url().optional(), + support: z.string().url().optional(), + icon: z.string().optional(), + screenshots: z.array(z.string()).optional(), + server: McpbManifestServerSchema, + tools: z.array(McpbManifestToolSchema).optional(), + tools_generated: z.boolean().optional(), + prompts: z.array(McpbManifestPromptSchema).optional(), + prompts_generated: z.boolean().optional(), + keywords: z.array(z.string()).optional(), + license: z.string().optional(), + privacy_policies: z.array(z.string().url()).optional(), + compatibility: McpbManifestCompatibilitySchema.optional(), + user_config: z + .record(z.string(), McpbUserConfigurationOptionSchema) + .optional(), + }) + .refine((data) => !!(data.dxt_version || data.manifest_version), { + message: + "Either 'dxt_version' (deprecated) or 'manifest_version' must be provided", + }); + +export const McpbSignatureInfoSchema = z.strictObject({ + status: z.enum(["signed", "unsigned", "self-signed"]), + publisher: z.string().optional(), + issuer: z.string().optional(), + valid_from: z.string().optional(), + valid_to: z.string().optional(), + fingerprint: z.string().optional(), +}); diff --git a/src/schemas/0.3.ts b/src/schemas/0.3.ts new file mode 100644 index 0000000..3862ba4 --- /dev/null +++ b/src/schemas/0.3.ts @@ -0,0 +1,126 @@ +// WIP: This schema is under development and not yet finalized +import * as z from "zod"; + +export const MANIFEST_VERSION = "0.3"; + +export const McpServerConfigSchema = z.strictObject({ + command: z.string(), + args: z.array(z.string()).optional(), + env: z.record(z.string(), z.string()).optional(), +}); + +export const McpbManifestAuthorSchema = z.strictObject({ + name: z.string(), + email: z.string().email().optional(), + url: z.string().url().optional(), +}); + +export const McpbManifestRepositorySchema = z.strictObject({ + type: z.string(), + url: z.string().url(), +}); + +export const McpbManifestPlatformOverrideSchema = + McpServerConfigSchema.partial(); + +export const McpbManifestMcpConfigSchema = McpServerConfigSchema.extend({ + platform_overrides: z + .record(z.string(), McpbManifestPlatformOverrideSchema) + .optional(), +}); + +export const McpbManifestServerSchema = z.strictObject({ + type: z.enum(["python", "node", "binary"]), + entry_point: z.string(), + mcp_config: McpbManifestMcpConfigSchema, +}); + +export const McpbManifestCompatibilitySchema = z.strictObject({ + claude_desktop: z.string().optional(), + platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(), + runtimes: z + .strictObject({ + python: z.string().optional(), + node: z.string().optional(), + }) + .optional(), +}); + +export const McpbManifestToolSchema = z.strictObject({ + name: z.string(), + description: z.string().optional(), +}); + +export const McpbManifestPromptSchema = z.strictObject({ + name: z.string(), + description: z.string().optional(), + arguments: z.array(z.string()).optional(), + text: z.string(), +}); + +export const McpbUserConfigurationOptionSchema = z.strictObject({ + type: z.enum(["string", "number", "boolean", "directory", "file"]), + title: z.string(), + description: z.string(), + required: z.boolean().optional(), + default: z + .union([z.string(), z.number(), z.boolean(), z.array(z.string())]) + .optional(), + multiple: z.boolean().optional(), + sensitive: z.boolean().optional(), + min: z.number().optional(), + max: z.number().optional(), +}); + +export const McpbUserConfigValuesSchema = z.record( + z.string(), + z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]), +); + +export const McpbManifestSchema = z + .strictObject({ + $schema: z.string().optional(), + dxt_version: z + .literal(MANIFEST_VERSION) + .optional() + .describe("@deprecated Use manifest_version instead"), + manifest_version: z.literal(MANIFEST_VERSION).optional(), + name: z.string(), + display_name: z.string().optional(), + version: z.string(), + description: z.string(), + long_description: z.string().optional(), + author: McpbManifestAuthorSchema, + repository: McpbManifestRepositorySchema.optional(), + homepage: z.string().url().optional(), + documentation: z.string().url().optional(), + support: z.string().url().optional(), + icon: z.string().optional(), + screenshots: z.array(z.string()).optional(), + server: McpbManifestServerSchema, + tools: z.array(McpbManifestToolSchema).optional(), + tools_generated: z.boolean().optional(), + prompts: z.array(McpbManifestPromptSchema).optional(), + prompts_generated: z.boolean().optional(), + keywords: z.array(z.string()).optional(), + license: z.string().optional(), + privacy_policies: z.array(z.string().url()).optional(), + compatibility: McpbManifestCompatibilitySchema.optional(), + user_config: z + .record(z.string(), McpbUserConfigurationOptionSchema) + .optional(), + _meta: z.record(z.string(), z.record(z.string(), z.any())).optional(), + }) + .refine((data) => !!(data.dxt_version || data.manifest_version), { + message: + "Either 'dxt_version' (deprecated) or 'manifest_version' must be provided", + }); + +export const McpbSignatureInfoSchema = z.strictObject({ + status: z.enum(["signed", "unsigned", "self-signed"]), + publisher: z.string().optional(), + issuer: z.string().optional(), + valid_from: z.string().optional(), + valid_to: z.string().optional(), + fingerprint: z.string().optional(), +}); diff --git a/src/schemas/index.ts b/src/schemas/index.ts new file mode 100644 index 0000000..1b7c64b --- /dev/null +++ b/src/schemas/index.ts @@ -0,0 +1,8 @@ +export * as v0_1 from "./0.1.js"; +export * as v0_2 from "./0.2.js"; +export * as v0_3 from "./0.3.js"; +export * as latest from "./latest.js"; +export { + MANIFEST_VERSION as LATEST_MANIFEST_VERSION, + McpbManifestSchema, +} from "./latest.js"; diff --git a/src/schemas/latest.ts b/src/schemas/latest.ts new file mode 100644 index 0000000..79797d0 --- /dev/null +++ b/src/schemas/latest.ts @@ -0,0 +1 @@ +export * from "./0.2.js"; diff --git a/src/schemas-loose.ts b/src/schemas_loose/0.1.ts similarity index 96% rename from src/schemas-loose.ts rename to src/schemas_loose/0.1.ts index 7d6ca6d..2ab5e56 100644 --- a/src/schemas-loose.ts +++ b/src/schemas_loose/0.1.ts @@ -1,5 +1,7 @@ import * as z from "zod"; +export const MANIFEST_VERSION = "0.1"; + export const McpServerConfigSchema = z.object({ command: z.string(), args: z.array(z.string()).optional(), @@ -80,10 +82,10 @@ export const McpbManifestSchema = z .object({ $schema: z.string().optional(), dxt_version: z - .string() + .literal(MANIFEST_VERSION) .optional() .describe("@deprecated Use manifest_version instead"), - manifest_version: z.string().optional(), + manifest_version: z.literal(MANIFEST_VERSION).optional(), name: z.string(), display_name: z.string().optional(), version: z.string(), diff --git a/src/schemas_loose/0.2.ts b/src/schemas_loose/0.2.ts new file mode 100644 index 0000000..7cdbc1a --- /dev/null +++ b/src/schemas_loose/0.2.ts @@ -0,0 +1,127 @@ +import * as z from "zod"; + +export const MANIFEST_VERSION = "0.2"; + +export const McpServerConfigSchema = z.object({ + command: z.string(), + args: z.array(z.string()).optional(), + env: z.record(z.string(), z.string()).optional(), +}); + +export const McpbManifestAuthorSchema = z.object({ + name: z.string(), + email: z.string().email().optional(), + url: z.string().url().optional(), +}); + +export const McpbManifestRepositorySchema = z.object({ + type: z.string(), + url: z.string().url(), +}); + +export const McpbManifestPlatformOverrideSchema = + McpServerConfigSchema.partial(); + +export const McpbManifestMcpConfigSchema = McpServerConfigSchema.extend({ + platform_overrides: z + .record(z.string(), McpbManifestPlatformOverrideSchema) + .optional(), +}); + +export const McpbManifestServerSchema = z.object({ + type: z.enum(["python", "node", "binary"]), + entry_point: z.string(), + mcp_config: McpbManifestMcpConfigSchema, +}); + +export const McpbManifestCompatibilitySchema = z + .object({ + claude_desktop: z.string().optional(), + platforms: z.array(z.enum(["darwin", "win32", "linux"])).optional(), + runtimes: z + .object({ + python: z.string().optional(), + node: z.string().optional(), + }) + .optional(), + }) + .passthrough(); + +export const McpbManifestToolSchema = z.object({ + name: z.string(), + description: z.string().optional(), +}); + +export const McpbManifestPromptSchema = z.object({ + name: z.string(), + description: z.string().optional(), + arguments: z.array(z.string()).optional(), + text: z.string(), +}); + +export const McpbUserConfigurationOptionSchema = z.object({ + type: z.enum(["string", "number", "boolean", "directory", "file"]), + title: z.string(), + description: z.string(), + required: z.boolean().optional(), + default: z + .union([z.string(), z.number(), z.boolean(), z.array(z.string())]) + .optional(), + multiple: z.boolean().optional(), + sensitive: z.boolean().optional(), + min: z.number().optional(), + max: z.number().optional(), +}); + +export const McpbUserConfigValuesSchema = z.record( + z.string(), + z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]), +); + +export const McpbManifestSchema = z + .object({ + $schema: z.string().optional(), + dxt_version: z + .literal(MANIFEST_VERSION) + .optional() + .describe("@deprecated Use manifest_version instead"), + manifest_version: z.literal(MANIFEST_VERSION).optional(), + name: z.string(), + display_name: z.string().optional(), + version: z.string(), + description: z.string(), + long_description: z.string().optional(), + author: McpbManifestAuthorSchema, + repository: McpbManifestRepositorySchema.optional(), + homepage: z.string().url().optional(), + documentation: z.string().url().optional(), + support: z.string().url().optional(), + icon: z.string().optional(), + screenshots: z.array(z.string()).optional(), + server: McpbManifestServerSchema, + tools: z.array(McpbManifestToolSchema).optional(), + tools_generated: z.boolean().optional(), + prompts: z.array(McpbManifestPromptSchema).optional(), + prompts_generated: z.boolean().optional(), + keywords: z.array(z.string()).optional(), + license: z.string().optional(), + privacy_policies: z.array(z.string().url()).optional(), + compatibility: McpbManifestCompatibilitySchema.optional(), + user_config: z + .record(z.string(), McpbUserConfigurationOptionSchema) + .optional(), + }) + .passthrough() + .refine((data) => !!(data.dxt_version || data.manifest_version), { + message: + "Either 'dxt_version' (deprecated) or 'manifest_version' must be provided", + }); + +export const McpbSignatureInfoSchema = z.object({ + status: z.enum(["signed", "unsigned", "self-signed"]), + publisher: z.string().optional(), + issuer: z.string().optional(), + valid_from: z.string().optional(), + valid_to: z.string().optional(), + fingerprint: z.string().optional(), +}); diff --git a/src/schemas_loose/index.ts b/src/schemas_loose/index.ts new file mode 100644 index 0000000..b58933b --- /dev/null +++ b/src/schemas_loose/index.ts @@ -0,0 +1,3 @@ +export * as v0_1 from "./0.1.js"; +export * as v0_2 from "./0.2.js"; +export * as latest from "./latest.js"; diff --git a/src/schemas_loose/latest.ts b/src/schemas_loose/latest.ts new file mode 100644 index 0000000..79797d0 --- /dev/null +++ b/src/schemas_loose/latest.ts @@ -0,0 +1 @@ +export * from "./0.2.js"; diff --git a/src/shared/constants.ts b/src/shared/constants.ts new file mode 100644 index 0000000..1e4c2d0 --- /dev/null +++ b/src/shared/constants.ts @@ -0,0 +1,37 @@ +import { McpbManifestSchema as ManifestSchemaV0_1 } from "../schemas/0.1.js"; +import { McpbManifestSchema as ManifestSchemaV0_2 } from "../schemas/0.2.js"; +import { McpbManifestSchema as CurrentManifestSchema } from "../schemas/latest.js"; +import { McpbManifestSchema as LooseManifestSchemaV0_1 } from "../schemas_loose/0.1.js"; +import { McpbManifestSchema as LooseManifestSchemaV0_2 } from "../schemas_loose/0.2.js"; +import { McpbManifestSchema as CurrentLooseManifestSchema } from "../schemas_loose/latest.js"; + +/** + * Latest manifest version - the version that new manifests should use + */ +export const LATEST_MANIFEST_VERSION = "0.2" as const; + +/** + * Map of manifest versions to their strict schemas + */ +export const MANIFEST_SCHEMAS = { + "0.1": ManifestSchemaV0_1, + "0.2": ManifestSchemaV0_2, +} as const; + +/** + * Map of manifest versions to their loose schemas (with passthrough) + */ +export const MANIFEST_SCHEMAS_LOOSE = { + "0.1": LooseManifestSchemaV0_1, + "0.2": LooseManifestSchemaV0_2, +} as const; + +/** + * Get the latest manifest schema based on LATEST_MANIFEST_VERSION + */ +export const LATEST_MANIFEST_SCHEMA = CurrentManifestSchema; + +/** + * Get the latest loose manifest schema based on LATEST_MANIFEST_VERSION + */ +export const LATEST_MANIFEST_SCHEMA_LOOSE = CurrentLooseManifestSchema; diff --git a/src/types.ts b/src/types.ts index edd3f8c..0b6b2a3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,7 +14,7 @@ import type { McpbUserConfigurationOptionSchema, McpbUserConfigValuesSchema, McpServerConfigSchema, -} from "./schemas.js"; +} from "./schemas/latest.js"; export type McpServerConfig = z.infer; diff --git a/test/cli.test.ts b/test/cli.test.ts index dd18635..1462150 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -2,7 +2,7 @@ import { execSync } from "node:child_process"; import fs from "node:fs"; import { join } from "node:path"; -import { CURRENT_MANIFEST_VERSION } from "../src/schemas.js"; +import { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js"; interface ExecSyncError extends Error { stdout: Buffer; @@ -93,7 +93,7 @@ describe("DXT CLI", () => { fs.writeFileSync( join(tempDir, "manifest.json"), JSON.stringify({ - manifest_version: CURRENT_MANIFEST_VERSION, + manifest_version: LATEST_MANIFEST_VERSION, name: "Test Extension", version: "1.0.0", description: "A test extension", @@ -190,7 +190,7 @@ describe("DXT CLI", () => { fs.writeFileSync( join(tempExecDir, "manifest.json"), JSON.stringify({ - manifest_version: CURRENT_MANIFEST_VERSION, + manifest_version: LATEST_MANIFEST_VERSION, name: "Test Executable Extension", version: "1.0.0", description: "A test extension with executable files", diff --git a/test/config.test.ts b/test/config.test.ts index 6461c5a..062c66e 100644 --- a/test/config.test.ts +++ b/test/config.test.ts @@ -90,7 +90,7 @@ describe("getMcpConfigForManifest", () => { }; const baseManifest: McpbManifest = { - manifest_version: "1.0.0", + manifest_version: "0.2", name: "test-extension", version: "1.0.0", description: "Test extension", @@ -305,7 +305,7 @@ describe("getMcpConfigForManifest", () => { describe("hasRequiredConfigMissing", () => { const baseManifest: McpbManifest = { - manifest_version: "1.0.0", + manifest_version: "0.2", name: "test-extension", version: "1.0.0", description: "Test extension", diff --git a/test/init.test.ts b/test/init.test.ts index f79191e..3cdea0c 100644 --- a/test/init.test.ts +++ b/test/init.test.ts @@ -10,7 +10,7 @@ import { getDefaultRepositoryUrl, readPackageJson, } from "../src/cli/init.js"; -import { CURRENT_MANIFEST_VERSION } from "../src/schemas.js"; +import { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js"; // Mock the fs module jest.mock("fs", () => ({ @@ -218,7 +218,7 @@ describe("init functions", () => { ); expect(manifest).toEqual({ - manifest_version: CURRENT_MANIFEST_VERSION, + manifest_version: LATEST_MANIFEST_VERSION, name: "test-extension", version: "1.0.0", description: "Test description", @@ -304,7 +304,7 @@ describe("init functions", () => { ); expect(manifest).toEqual({ - manifest_version: CURRENT_MANIFEST_VERSION, + manifest_version: LATEST_MANIFEST_VERSION, name: "test-extension", display_name: "Test Extension", version: "1.0.0", diff --git a/test/schemas.test.ts b/test/schemas.test.ts index 86c6ffa..f88fe47 100644 --- a/test/schemas.test.ts +++ b/test/schemas.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; import { join } from "path"; -import { McpbManifestSchema } from "../src/schemas.js"; +import { McpbManifestSchema, v0_3 } from "../src/schemas/index.js"; describe("McpbManifestSchema", () => { it("should validate a valid manifest", () => { @@ -37,7 +37,7 @@ describe("McpbManifestSchema", () => { it("should validate manifest with all optional fields", () => { const fullManifest = { - manifest_version: "1.0", + manifest_version: "0.2", name: "full-extension", display_name: "Full Featured Extension", version: "2.0.0", @@ -117,7 +117,7 @@ describe("McpbManifestSchema", () => { serverTypes.forEach((type) => { const manifest = { - manifest_version: "1.0", + manifest_version: "0.2", name: "test", version: "1.0.0", description: "Test", @@ -139,7 +139,7 @@ describe("McpbManifestSchema", () => { describe("_meta", () => { const base = { - manifest_version: "0.2", + manifest_version: "0.3", name: "client-ext-test", version: "1.0.0", description: "Test manifest", @@ -155,11 +155,14 @@ describe("McpbManifestSchema", () => { const manifest = { ...base, _meta: { - "com.microsoft.windows": { package_family_name: "Pkg_123", channel: "stable" }, + "com.microsoft.windows": { + package_family_name: "Pkg_123", + channel: "stable", + }, "com.apple.darwin": { bundle_id: "com.example.app", notarized: true }, }, }; - const result = McpbManifestSchema.safeParse(manifest); + const result = v0_3.McpbManifestSchema.safeParse(manifest); expect(result.success).toBe(true); }); @@ -167,10 +170,13 @@ describe("McpbManifestSchema", () => { const manifest = { ...base, _meta: { - "com.microsoft.windows": "raw-string" as unknown as Record, + "com.microsoft.windows": "raw-string" as unknown as Record< + string, + unknown + >, }, }; - const result = McpbManifestSchema.safeParse(manifest); + const result = v0_3.McpbManifestSchema.safeParse(manifest); expect(result.success).toBe(false); if (!result.success) { const messages = result.error.issues.map((i) => i.message).join("\n"); @@ -185,7 +191,7 @@ describe("McpbManifestSchema", () => { "com.apple.darwin": [] as unknown as Record, }, }; - const result = McpbManifestSchema.safeParse(manifest); + const result = v0_3.McpbManifestSchema.safeParse(manifest); expect(result.success).toBe(false); }); @@ -196,13 +202,13 @@ describe("McpbManifestSchema", () => { custom: null as unknown as Record, }, }; - const result = McpbManifestSchema.safeParse(manifest); + const result = v0_3.McpbManifestSchema.safeParse(manifest); expect(result.success).toBe(false); }); it("allows empty object for _meta", () => { const manifest = { ...base, _meta: {} }; - const result = McpbManifestSchema.safeParse(manifest); + const result = v0_3.McpbManifestSchema.safeParse(manifest); expect(result.success).toBe(true); }); }); diff --git a/test/valid-manifest.json b/test/valid-manifest.json index a91e78f..c2d121d 100644 --- a/test/valid-manifest.json +++ b/test/valid-manifest.json @@ -1,5 +1,5 @@ { - "manifest_version": "1.0", + "manifest_version": "0.2", "name": "test-extension", "display_name": "Test Extension", "version": "1.0.0",