From 39fe8034799318d78cefd18e0bbe6fc76514362b Mon Sep 17 00:00:00 2001 From: guyru Date: Mon, 22 Sep 2025 17:19:05 +0300 Subject: [PATCH 1/3] The repository url should actually point to the git repo In the example, the repo URL should actually point to the git repo and not the github project. --- MANIFEST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.md b/MANIFEST.md index eb8ee46..30f41cd 100644 --- a/MANIFEST.md +++ b/MANIFEST.md @@ -84,7 +84,7 @@ A full `manifest.json` with most of the optional fields looks like this: }, "repository": { "type": "git", - "url": "https://github.com/your-username/my-mcp-extension" + "url": "https://github.com/your-username/my-mcp-extension.git" }, "homepage": "https://example.com/my-extension", "documentation": "https://docs.example.com/my-extension", From 98126b777e43c9eead035dfd5f937da988a15b6d Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Sat, 1 Nov 2025 12:31:25 -0700 Subject: [PATCH 2/3] feat: use 0.2 as the default schema (#145) --- package.json | 2 +- src/cli/init.ts | 8 ++++---- src/cli/pack.ts | 30 +++++++++++++--------------- src/node/validate.ts | 19 ++++++++++++++---- src/shared/constants.ts | 8 ++++++++ src/shared/manifestVersionResolve.ts | 24 ++++++++++++++++++++++ test/cli.test.ts | 10 +++++----- test/init.test.ts | 6 +++--- 8 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 src/shared/manifestVersionResolve.ts diff --git a/package.json b/package.json index 8749e20..77f437a 100644 --- a/package.json +++ b/package.json @@ -99,4 +99,4 @@ "@babel/parser": "7.27.3" }, "packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f" -} \ No newline at end of file +} diff --git a/src/cli/init.ts b/src/cli/init.ts index 58a7317..7682e0f 100644 --- a/src/cli/init.ts +++ b/src/cli/init.ts @@ -2,8 +2,8 @@ import { confirm, input, select } from "@inquirer/prompts"; import { existsSync, readFileSync, writeFileSync } from "fs"; import { basename, join, resolve } from "path"; -import { LATEST_MANIFEST_VERSION } from "../shared/constants.js"; -import type { McpbManifestLatest } from "../types.js"; +import { DEFAULT_MANIFEST_VERSION } from "../shared/constants.js"; +import type { McpbManifest } from "../types.js"; interface PackageJson { name?: string; @@ -878,14 +878,14 @@ export function buildManifest( resources: string; default_locale: string; }, -): McpbManifestLatest { +): McpbManifest { const { name, displayName, version, description, authorName } = basicInfo; const { authorEmail, authorUrl } = authorInfo; const { serverType, entryPoint, mcp_config } = serverConfig; const { keywords, license, repository } = optionalFields; return { - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name, ...(displayName && displayName !== name ? { display_name: displayName } diff --git a/src/cli/pack.ts b/src/cli/pack.ts index 58b3c1c..e2411bf 100644 --- a/src/cli/pack.ts +++ b/src/cli/pack.ts @@ -13,11 +13,9 @@ import { basename, join, relative, resolve, sep } from "path"; import { getAllFilesWithCount, readMcpbIgnorePatterns } from "../node/files.js"; import { validateManifest } from "../node/validate.js"; -import { - LATEST_MANIFEST_SCHEMA, - LATEST_MANIFEST_VERSION, -} from "../shared/constants.js"; +import { MANIFEST_SCHEMAS } from "../shared/constants.js"; import { getLogger } from "../shared/log.js"; +import { getManifestVersionFromRawData } from "../shared/manifestVersionResolve.js"; import { initExtension } from "./init.js"; interface PackOptions { @@ -95,7 +93,18 @@ export async function packExtension({ try { const manifestContent = readFileSync(manifestPath, "utf-8"); const manifestData = JSON.parse(manifestContent); - manifest = LATEST_MANIFEST_SCHEMA.parse(manifestData); + const manifestVersion = getManifestVersionFromRawData(manifestData); + if (!manifestVersion) { + logger.error( + `ERROR: Manifest version mismatch. Expected "${Object.keys(MANIFEST_SCHEMAS).join(" or ")}", found "${manifestVersion}"`, + ); + logger.error( + ` Please update the manifest_version in your manifest.json to a supported version`, + ); + return false; + } + + manifest = MANIFEST_SCHEMAS[manifestVersion].parse(manifestData); } catch (error) { logger.error("ERROR: Failed to parse manifest.json"); if (error instanceof Error) { @@ -104,17 +113,6 @@ export async function packExtension({ return false; } - const manifestVersion = manifest.manifest_version || manifest.dxt_version; - if (manifestVersion !== LATEST_MANIFEST_VERSION) { - logger.error( - `ERROR: Manifest version mismatch. Expected "${LATEST_MANIFEST_VERSION}", found "${manifestVersion}"`, - ); - logger.error( - ` Please update the manifest_version in your manifest.json to "${LATEST_MANIFEST_VERSION}"`, - ); - return false; - } - // Determine output path const extensionName = basename(resolvedPath); const finalOutputPath = outputPath diff --git a/src/node/validate.ts b/src/node/validate.ts index ac21747..d1ee8fd 100644 --- a/src/node/validate.ts +++ b/src/node/validate.ts @@ -7,9 +7,10 @@ import prettyBytes from "pretty-bytes"; import { unpackExtension } from "../cli/unpack.js"; import { - LATEST_MANIFEST_SCHEMA, - LATEST_MANIFEST_SCHEMA_LOOSE, + MANIFEST_SCHEMAS, + MANIFEST_SCHEMAS_LOOSE, } from "../shared/constants.js"; +import { getManifestVersionFromRawData } from "../shared/manifestVersionResolve.js"; /** * Check if a buffer contains a valid PNG file signature @@ -119,8 +120,13 @@ export function validateManifest(inputPath: string): boolean { const manifestContent = readFileSync(manifestPath, "utf-8"); const manifestData = JSON.parse(manifestContent); + const manifestVersion = getManifestVersionFromRawData(manifestData); + if (!manifestVersion) { + console.log("Unrecognized or unsupported manifest version"); + return false; + } - const result = LATEST_MANIFEST_SCHEMA.safeParse(manifestData); + const result = MANIFEST_SCHEMAS[manifestVersion].safeParse(manifestData); if (result.success) { console.log("Manifest schema validation passes!"); @@ -192,7 +198,12 @@ 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 = LATEST_MANIFEST_SCHEMA_LOOSE.safeParse(manifestData); + const manifestVersion = getManifestVersionFromRawData(manifestData); + if (!manifestVersion) { + throw new Error("Unrecognized or unsupported manifest version"); + } + const result = + MANIFEST_SCHEMAS_LOOSE[manifestVersion].safeParse(manifestData); if (!result.success) { throw new Error( diff --git a/src/shared/constants.ts b/src/shared/constants.ts index 95a5cf4..6d16f5d 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -9,9 +9,15 @@ import { McpbManifestSchema as CurrentLooseManifestSchema } from "../schemas_loo /** * Latest manifest version - the version that new manifests should use + * @deprecated */ export const LATEST_MANIFEST_VERSION = "0.3" as const; +/** + * Default manifest version for new packages + */ +export const DEFAULT_MANIFEST_VERSION = "0.2" as const; + /** * Map of manifest versions to their strict schemas */ @@ -32,10 +38,12 @@ export const MANIFEST_SCHEMAS_LOOSE = { /** * Get the latest manifest schema based on LATEST_MANIFEST_VERSION + * @deprecated */ export const LATEST_MANIFEST_SCHEMA = CurrentManifestSchema; /** * Get the latest loose manifest schema based on LATEST_MANIFEST_VERSION + * @deprecated */ export const LATEST_MANIFEST_SCHEMA_LOOSE = CurrentLooseManifestSchema; diff --git a/src/shared/manifestVersionResolve.ts b/src/shared/manifestVersionResolve.ts new file mode 100644 index 0000000..5bc6381 --- /dev/null +++ b/src/shared/manifestVersionResolve.ts @@ -0,0 +1,24 @@ +import { MANIFEST_SCHEMAS } from "./constants.js"; + +export function getManifestVersionFromRawData(manifestData: unknown) { + let manifestVersion: keyof typeof MANIFEST_SCHEMAS | null = null; + if ( + typeof manifestData === "object" && + manifestData && + "manifest_version" in manifestData && + typeof manifestData.manifest_version === "string" && + Object.keys(MANIFEST_SCHEMAS).includes(manifestData.manifest_version) + ) { + manifestVersion = + manifestData.manifest_version as keyof typeof MANIFEST_SCHEMAS; + } else if ( + typeof manifestData === "object" && + manifestData && + "dxt_version" in manifestData && + typeof manifestData.dxt_version === "string" && + Object.keys(MANIFEST_SCHEMAS).includes(manifestData.dxt_version) + ) { + manifestVersion = manifestData.dxt_version as keyof typeof MANIFEST_SCHEMAS; + } + return manifestVersion; +} diff --git a/test/cli.test.ts b/test/cli.test.ts index 9bdc1eb..e7757ac 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 { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js"; +import { DEFAULT_MANIFEST_VERSION } from "../src/shared/constants"; interface ExecSyncError extends Error { stdout: Buffer; @@ -113,7 +113,7 @@ describe("DXT CLI", () => { fs.writeFileSync( manifestWithIcon, JSON.stringify({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "test-with-icon", version: "1.0.0", description: "Test with icon", @@ -140,7 +140,7 @@ describe("DXT CLI", () => { fs.writeFileSync( manifestWithUrl, JSON.stringify({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "test-with-url", version: "1.0.0", description: "Test with URL", @@ -177,7 +177,7 @@ describe("DXT CLI", () => { fs.writeFileSync( join(tempDir, "manifest.json"), JSON.stringify({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "Test Extension", version: "1.0.0", description: "A test extension", @@ -274,7 +274,7 @@ describe("DXT CLI", () => { fs.writeFileSync( join(tempExecDir, "manifest.json"), JSON.stringify({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "Test Executable Extension", version: "1.0.0", description: "A test extension with executable files", diff --git a/test/init.test.ts b/test/init.test.ts index caf598f..a9b9bf4 100644 --- a/test/init.test.ts +++ b/test/init.test.ts @@ -10,7 +10,7 @@ import { getDefaultRepositoryUrl, readPackageJson, } from "../src/cli/init.js"; -import { LATEST_MANIFEST_VERSION } from "../src/schemas/index.js"; +import { DEFAULT_MANIFEST_VERSION } from "../src/shared/constants.js"; // Mock the fs module jest.mock("fs", () => ({ @@ -220,7 +220,7 @@ describe("init functions", () => { ); expect(manifest).toEqual({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "test-extension", version: "1.0.0", description: "Test description", @@ -322,7 +322,7 @@ describe("init functions", () => { ); expect(manifest).toEqual({ - manifest_version: LATEST_MANIFEST_VERSION, + manifest_version: DEFAULT_MANIFEST_VERSION, name: "test-extension", display_name: "Test Extension", version: "1.0.0", From b75f8a67f9bafcfac55d3ed393b8b92b14bfd7b9 Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Sat, 1 Nov 2025 12:35:45 -0700 Subject: [PATCH 3/3] chore: update version from 1.1.5 to 1.2.0 (#147) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77f437a..92a270e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@anthropic-ai/mcpb", "description": "Tools for building MCP Bundles", - "version": "1.1.5", + "version": "1.2.0", "type": "module", "main": "dist/index.js", "module": "dist/index.js",