From 67938cdab9206eefd75eb8a58bc0f19e38cbaa49 Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:30:32 -0700 Subject: [PATCH 01/11] feat: export versioned schemas in package.json Add exports for versioned schemas to allow consumers to import: - ./schemas: All versioned schemas (v0_1, v0_2, v0_3, latest) - ./schemas/*: Specific schema versions (./schemas/0.1, ./schemas/any, etc.) - ./schemas-loose: Loose validation schemas This enables cleaner imports like: import { McpbManifestSchema } from '@anthropic-ai/mcpb/schemas/any' import * as v0_2 from '@anthropic-ai/mcpb/schemas/0.2' import * as schemas from '@anthropic-ai/mcpb/schemas' --- package.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a01cce..ea00746 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,22 @@ "import": "./dist/cli.js", "require": "./dist/cli.js" }, - "./mcpb-manifest.schema.json": "./dist/mcpb-manifest.schema.json" + "./mcpb-manifest.schema.json": "./dist/mcpb-manifest.schema.json", + "./schemas": { + "types": "./dist/schemas/index.d.ts", + "import": "./dist/schemas/index.js", + "require": "./dist/schemas/index.js" + }, + "./schemas/*": { + "types": "./dist/schemas/*.d.ts", + "import": "./dist/schemas/*.js", + "require": "./dist/schemas/*.js" + }, + "./schemas-loose": { + "types": "./dist/schemas-loose.d.ts", + "import": "./dist/schemas-loose.js", + "require": "./dist/schemas-loose.js" + } }, "bin": "dist/cli/cli.js", "files": [ From faafd4523a23f271e489de232a2a94696141522a Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:33:23 -0700 Subject: [PATCH 02/11] feat: make McpbManifest a discriminated union of all versions Changed McpbManifest type from a single version to a discriminated union of all historical manifest versions (0.1, 0.2, 0.3). This allows the type system to properly handle manifests from any version while maintaining type safety through the manifest_version/dxt_version discriminator field. Benefits: - Type-safe handling of multiple manifest versions - TypeScript can narrow types based on version field - No need for type assertions when working with versioned manifests - Maintains backward compatibility with all historical versions --- src/types.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 0b6b2a3..23c2061 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,6 +15,9 @@ import type { McpbUserConfigValuesSchema, McpServerConfigSchema, } from "./schemas/latest.js"; +import type { McpbManifestSchema as McpbManifestSchema_v0_1 } from "./schemas/0.1.js"; +import type { McpbManifestSchema as McpbManifestSchema_v0_2 } from "./schemas/0.2.js"; +import type { McpbManifestSchema as McpbManifestSchema_v0_3 } from "./schemas/0.3.js"; export type McpServerConfig = z.infer; @@ -46,7 +49,14 @@ export type McpbUserConfigurationOption = z.infer< export type McpbUserConfigValues = z.infer; -export type McpbManifest = z.infer; +/** + * Discriminated union of all supported manifest versions. + * Discriminated by manifest_version or dxt_version field. + */ +export type McpbManifest = + | z.infer + | z.infer + | z.infer; /** * Information about a MCPB package signature From b5fa7df6eb6d4dfa468cb948b88ee4e4e07f0d25 Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:39:57 -0700 Subject: [PATCH 03/11] feat: generate JSON schemas for all manifest versions Updated build script to generate JSON schemas for all historical manifest versions (v0.1, v0.2, v0.3) in addition to the latest version. Changes: - Generate mcpb-manifest-v0.1.schema.json - Generate mcpb-manifest-v0.2.schema.json - Generate mcpb-manifest-v0.3.schema.json - Generate mcpb-manifest-latest.schema.json - Keep mcpb-manifest.schema.json as alias for latest - All schemas generated to both dist/ and schemas/ directories - Added exports in package.json for all versioned schemas Benefits: - Tools can validate against specific manifest versions - Backwards compatibility for all historical versions - Latest schema always available at predictable path - JSON schema files match the Zod schema versions Usage: import manifestSchema from '@anthropic-ai/mcpb/mcpb-manifest-v0.2.schema.json' import latestSchema from '@anthropic-ai/mcpb/mcpb-manifest-latest.schema.json' --- package.json | 4 + schemas/mcpb-manifest-latest.schema.json | 376 +++++++++++++++++++++++ schemas/mcpb-manifest-v0.1.schema.json | 327 ++++++++++++++++++++ schemas/mcpb-manifest-v0.2.schema.json | 327 ++++++++++++++++++++ schemas/mcpb-manifest-v0.3.schema.json | 376 +++++++++++++++++++++++ schemas/mcpb-manifest.schema.json | 53 +++- scripts/build-mcpb-schema.js | 44 ++- 7 files changed, 1491 insertions(+), 16 deletions(-) create mode 100644 schemas/mcpb-manifest-latest.schema.json create mode 100644 schemas/mcpb-manifest-v0.1.schema.json create mode 100644 schemas/mcpb-manifest-v0.2.schema.json create mode 100644 schemas/mcpb-manifest-v0.3.schema.json diff --git a/package.json b/package.json index ea00746..6ea9c3f 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,10 @@ "require": "./dist/cli.js" }, "./mcpb-manifest.schema.json": "./dist/mcpb-manifest.schema.json", + "./mcpb-manifest-v0.1.schema.json": "./dist/mcpb-manifest-v0.1.schema.json", + "./mcpb-manifest-v0.2.schema.json": "./dist/mcpb-manifest-v0.2.schema.json", + "./mcpb-manifest-v0.3.schema.json": "./dist/mcpb-manifest-v0.3.schema.json", + "./mcpb-manifest-latest.schema.json": "./dist/mcpb-manifest-latest.schema.json", "./schemas": { "types": "./dist/schemas/index.d.ts", "import": "./dist/schemas/index.js", diff --git a/schemas/mcpb-manifest-latest.schema.json b/schemas/mcpb-manifest-latest.schema.json new file mode 100644 index 0000000..a2dc082 --- /dev/null +++ b/schemas/mcpb-manifest-latest.schema.json @@ -0,0 +1,376 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "dxt_version": { + "type": "string", + "const": "0.3", + "description": "@deprecated Use manifest_version instead" + }, + "manifest_version": { + "type": "string", + "const": "0.3" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "long_description": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "repository": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "homepage": { + "type": "string", + "format": "uri" + }, + "documentation": { + "type": "string", + "format": "uri" + }, + "support": { + "type": "string", + "format": "uri" + }, + "icon": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "sizes": { + "type": "string", + "pattern": "^\\d+x\\d+$" + }, + "theme": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "src", + "sizes" + ], + "additionalProperties": false + } + }, + "screenshots": { + "type": "array", + "items": { + "type": "string" + } + }, + "localization": { + "type": "object", + "properties": { + "resources": { + "type": "string", + "pattern": "\\$\\{locale\\}" + }, + "default_locale": { + "type": "string", + "pattern": "^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$" + } + }, + "required": [ + "resources", + "default_locale" + ], + "additionalProperties": false + }, + "server": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "python", + "node", + "binary" + ] + }, + "entry_point": { + "type": "string" + }, + "mcp_config": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "platform_overrides": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "command": { + "$ref": "#/properties/server/properties/mcp_config/properties/command" + }, + "args": { + "$ref": "#/properties/server/properties/mcp_config/properties/args" + }, + "env": { + "$ref": "#/properties/server/properties/mcp_config/properties/env" + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "command" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "entry_point", + "mcp_config" + ], + "additionalProperties": false + }, + "tools": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "tools_generated": { + "type": "boolean" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "arguments": { + "type": "array", + "items": { + "type": "string" + } + }, + "text": { + "type": "string" + } + }, + "required": [ + "name", + "text" + ], + "additionalProperties": false + } + }, + "prompts_generated": { + "type": "boolean" + }, + "keywords": { + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "type": "string" + }, + "privacy_policies": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "compatibility": { + "type": "object", + "properties": { + "claude_desktop": { + "type": "string" + }, + "platforms": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "darwin", + "win32", + "linux" + ] + } + }, + "runtimes": { + "type": "object", + "properties": { + "python": { + "type": "string" + }, + "node": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "user_config": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "directory", + "file" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "multiple": { + "type": "boolean" + }, + "sensitive": { + "type": "boolean" + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + }, + "required": [ + "type", + "title", + "description" + ], + "additionalProperties": false + } + }, + "_meta": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } + } + }, + "required": [ + "name", + "version", + "description", + "author", + "server" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/schemas/mcpb-manifest-v0.1.schema.json b/schemas/mcpb-manifest-v0.1.schema.json new file mode 100644 index 0000000..17e6fd8 --- /dev/null +++ b/schemas/mcpb-manifest-v0.1.schema.json @@ -0,0 +1,327 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "dxt_version": { + "type": "string", + "const": "0.1", + "description": "@deprecated Use manifest_version instead" + }, + "manifest_version": { + "type": "string", + "const": "0.1" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "long_description": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "repository": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "homepage": { + "type": "string", + "format": "uri" + }, + "documentation": { + "type": "string", + "format": "uri" + }, + "support": { + "type": "string", + "format": "uri" + }, + "icon": { + "type": "string" + }, + "screenshots": { + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "python", + "node", + "binary" + ] + }, + "entry_point": { + "type": "string" + }, + "mcp_config": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "platform_overrides": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "command": { + "$ref": "#/properties/server/properties/mcp_config/properties/command" + }, + "args": { + "$ref": "#/properties/server/properties/mcp_config/properties/args" + }, + "env": { + "$ref": "#/properties/server/properties/mcp_config/properties/env" + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "command" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "entry_point", + "mcp_config" + ], + "additionalProperties": false + }, + "tools": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "tools_generated": { + "type": "boolean" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "arguments": { + "type": "array", + "items": { + "type": "string" + } + }, + "text": { + "type": "string" + } + }, + "required": [ + "name", + "text" + ], + "additionalProperties": false + } + }, + "prompts_generated": { + "type": "boolean" + }, + "keywords": { + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "type": "string" + }, + "compatibility": { + "type": "object", + "properties": { + "claude_desktop": { + "type": "string" + }, + "platforms": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "darwin", + "win32", + "linux" + ] + } + }, + "runtimes": { + "type": "object", + "properties": { + "python": { + "type": "string" + }, + "node": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "user_config": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "directory", + "file" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "multiple": { + "type": "boolean" + }, + "sensitive": { + "type": "boolean" + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + }, + "required": [ + "type", + "title", + "description" + ], + "additionalProperties": false + } + }, + "_meta": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } + } + }, + "required": [ + "name", + "version", + "description", + "author", + "server" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/schemas/mcpb-manifest-v0.2.schema.json b/schemas/mcpb-manifest-v0.2.schema.json new file mode 100644 index 0000000..fc522b9 --- /dev/null +++ b/schemas/mcpb-manifest-v0.2.schema.json @@ -0,0 +1,327 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "dxt_version": { + "type": "string", + "const": "0.2", + "description": "@deprecated Use manifest_version instead" + }, + "manifest_version": { + "type": "string", + "const": "0.2" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "long_description": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "repository": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "homepage": { + "type": "string", + "format": "uri" + }, + "documentation": { + "type": "string", + "format": "uri" + }, + "support": { + "type": "string", + "format": "uri" + }, + "icon": { + "type": "string" + }, + "screenshots": { + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "python", + "node", + "binary" + ] + }, + "entry_point": { + "type": "string" + }, + "mcp_config": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "platform_overrides": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "command": { + "$ref": "#/properties/server/properties/mcp_config/properties/command" + }, + "args": { + "$ref": "#/properties/server/properties/mcp_config/properties/args" + }, + "env": { + "$ref": "#/properties/server/properties/mcp_config/properties/env" + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "command" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "entry_point", + "mcp_config" + ], + "additionalProperties": false + }, + "tools": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "tools_generated": { + "type": "boolean" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "arguments": { + "type": "array", + "items": { + "type": "string" + } + }, + "text": { + "type": "string" + } + }, + "required": [ + "name", + "text" + ], + "additionalProperties": false + } + }, + "prompts_generated": { + "type": "boolean" + }, + "keywords": { + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "type": "string" + }, + "privacy_policies": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "compatibility": { + "type": "object", + "properties": { + "claude_desktop": { + "type": "string" + }, + "platforms": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "darwin", + "win32", + "linux" + ] + } + }, + "runtimes": { + "type": "object", + "properties": { + "python": { + "type": "string" + }, + "node": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "user_config": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "directory", + "file" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "multiple": { + "type": "boolean" + }, + "sensitive": { + "type": "boolean" + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + }, + "required": [ + "type", + "title", + "description" + ], + "additionalProperties": false + } + } + }, + "required": [ + "name", + "version", + "description", + "author", + "server" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/schemas/mcpb-manifest-v0.3.schema.json b/schemas/mcpb-manifest-v0.3.schema.json new file mode 100644 index 0000000..a2dc082 --- /dev/null +++ b/schemas/mcpb-manifest-v0.3.schema.json @@ -0,0 +1,376 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "dxt_version": { + "type": "string", + "const": "0.3", + "description": "@deprecated Use manifest_version instead" + }, + "manifest_version": { + "type": "string", + "const": "0.3" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "long_description": { + "type": "string" + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "repository": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "type", + "url" + ], + "additionalProperties": false + }, + "homepage": { + "type": "string", + "format": "uri" + }, + "documentation": { + "type": "string", + "format": "uri" + }, + "support": { + "type": "string", + "format": "uri" + }, + "icon": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "sizes": { + "type": "string", + "pattern": "^\\d+x\\d+$" + }, + "theme": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "src", + "sizes" + ], + "additionalProperties": false + } + }, + "screenshots": { + "type": "array", + "items": { + "type": "string" + } + }, + "localization": { + "type": "object", + "properties": { + "resources": { + "type": "string", + "pattern": "\\$\\{locale\\}" + }, + "default_locale": { + "type": "string", + "pattern": "^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$" + } + }, + "required": [ + "resources", + "default_locale" + ], + "additionalProperties": false + }, + "server": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "python", + "node", + "binary" + ] + }, + "entry_point": { + "type": "string" + }, + "mcp_config": { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "platform_overrides": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "command": { + "$ref": "#/properties/server/properties/mcp_config/properties/command" + }, + "args": { + "$ref": "#/properties/server/properties/mcp_config/properties/args" + }, + "env": { + "$ref": "#/properties/server/properties/mcp_config/properties/env" + } + }, + "additionalProperties": false + } + } + }, + "required": [ + "command" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "entry_point", + "mcp_config" + ], + "additionalProperties": false + }, + "tools": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "tools_generated": { + "type": "boolean" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "arguments": { + "type": "array", + "items": { + "type": "string" + } + }, + "text": { + "type": "string" + } + }, + "required": [ + "name", + "text" + ], + "additionalProperties": false + } + }, + "prompts_generated": { + "type": "boolean" + }, + "keywords": { + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "type": "string" + }, + "privacy_policies": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "compatibility": { + "type": "object", + "properties": { + "claude_desktop": { + "type": "string" + }, + "platforms": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "darwin", + "win32", + "linux" + ] + } + }, + "runtimes": { + "type": "object", + "properties": { + "python": { + "type": "string" + }, + "node": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "user_config": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "directory", + "file" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "multiple": { + "type": "boolean" + }, + "sensitive": { + "type": "boolean" + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + } + }, + "required": [ + "type", + "title", + "description" + ], + "additionalProperties": false + } + }, + "_meta": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } + } + }, + "required": [ + "name", + "version", + "description", + "author", + "server" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/schemas/mcpb-manifest.schema.json b/schemas/mcpb-manifest.schema.json index fc522b9..a2dc082 100644 --- a/schemas/mcpb-manifest.schema.json +++ b/schemas/mcpb-manifest.schema.json @@ -6,12 +6,12 @@ }, "dxt_version": { "type": "string", - "const": "0.2", + "const": "0.3", "description": "@deprecated Use manifest_version instead" }, "manifest_version": { "type": "string", - "const": "0.2" + "const": "0.3" }, "name": { "type": "string" @@ -80,12 +80,54 @@ "icon": { "type": "string" }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "sizes": { + "type": "string", + "pattern": "^\\d+x\\d+$" + }, + "theme": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "src", + "sizes" + ], + "additionalProperties": false + } + }, "screenshots": { "type": "array", "items": { "type": "string" } }, + "localization": { + "type": "object", + "properties": { + "resources": { + "type": "string", + "pattern": "\\$\\{locale\\}" + }, + "default_locale": { + "type": "string", + "pattern": "^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$" + } + }, + "required": [ + "resources", + "default_locale" + ], + "additionalProperties": false + }, "server": { "type": "object", "properties": { @@ -313,6 +355,13 @@ ], "additionalProperties": false } + }, + "_meta": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } } }, "required": [ diff --git a/scripts/build-mcpb-schema.js b/scripts/build-mcpb-schema.js index a359274..4068f91 100644 --- a/scripts/build-mcpb-schema.js +++ b/scripts/build-mcpb-schema.js @@ -1,33 +1,49 @@ import { - McpbManifestSchema, + McpbManifestSchema as McpbManifestSchemaLatest, McpbSignatureInfoSchema, } from "../dist/schemas/latest.js"; +import { McpbManifestSchema as McpbManifestSchema_v0_1 } from "../dist/schemas/0.1.js"; +import { McpbManifestSchema as McpbManifestSchema_v0_2 } from "../dist/schemas/0.2.js"; +import { McpbManifestSchema as McpbManifestSchema_v0_3 } from "../dist/schemas/0.3.js"; import { zodToJsonSchema } from "zod-to-json-schema"; import fs from "node:fs/promises"; import path from "node:path"; -const schemasToWrite = { - "mcpb-manifest": McpbManifestSchema, +const distDir = path.join(import.meta.dirname, "../dist"); +const schemasDir = path.join(import.meta.dirname, "../schemas"); + +// Versioned manifest schemas +const versionedManifestSchemas = { + "mcpb-manifest-v0.1": McpbManifestSchema_v0_1, + "mcpb-manifest-v0.2": McpbManifestSchema_v0_2, + "mcpb-manifest-v0.3": McpbManifestSchema_v0_3, + "mcpb-manifest-latest": McpbManifestSchemaLatest, + "mcpb-manifest": McpbManifestSchemaLatest, // Alias for latest +}; + +// Other schemas +const otherSchemas = { "mcpb-signature-info": McpbSignatureInfoSchema, }; -const distDir = path.join(import.meta.dirname, "../dist"); -const schemasDir = path.join(import.meta.dirname, "../schemas"); +const allSchemas = { ...versionedManifestSchemas, ...otherSchemas }; // Generate all schemas to dist/ await fs.mkdir(distDir, { recursive: true }); -for (const key in schemasToWrite) { - const schema = zodToJsonSchema(schemasToWrite[key]); +for (const [key, schema] of Object.entries(allSchemas)) { + const jsonSchema = zodToJsonSchema(schema); const filePath = path.join(distDir, `${key}.schema.json`); - await fs.writeFile(filePath, JSON.stringify(schema, null, 2), { + await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { encoding: "utf8", }); } -// Generate only manifest schema to schemas/ +// Generate all versioned manifest schemas to schemas/ await fs.mkdir(schemasDir, { recursive: true }); -const manifestSchema = zodToJsonSchema(McpbManifestSchema); -const manifestPath = path.join(schemasDir, "mcpb-manifest.schema.json"); -await fs.writeFile(manifestPath, JSON.stringify(manifestSchema, null, 2), { - encoding: "utf8", -}); +for (const [key, schema] of Object.entries(versionedManifestSchemas)) { + const jsonSchema = zodToJsonSchema(schema); + const filePath = path.join(schemasDir, `${key}.schema.json`); + await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { + encoding: "utf8", + }); +} From eeb9dca819e9364a800d8c6f16b59cd45baaca9e Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:49:41 -0700 Subject: [PATCH 04/11] refactor: remove non-versioned mcpb-manifest.schema.json export Remove the generic mcpb-manifest.schema.json export from package.json in favor of explicit versioned exports. Changes: - Removed ./mcpb-manifest.schema.json from package exports - Stop generating mcpb-manifest.schema.json in dist/ - Keep mcpb-manifest.schema.json in schemas/ for backward compatibility Consumers should now use: - mcpb-manifest-latest.schema.json (for latest version) - mcpb-manifest-v0.1.schema.json (for specific version) - etc. This makes versioning explicit and prevents ambiguity about which schema version is being used. --- package.json | 1 - scripts/build-mcpb-schema.js | 24 ++++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 6ea9c3f..68b3148 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "import": "./dist/cli.js", "require": "./dist/cli.js" }, - "./mcpb-manifest.schema.json": "./dist/mcpb-manifest.schema.json", "./mcpb-manifest-v0.1.schema.json": "./dist/mcpb-manifest-v0.1.schema.json", "./mcpb-manifest-v0.2.schema.json": "./dist/mcpb-manifest-v0.2.schema.json", "./mcpb-manifest-v0.3.schema.json": "./dist/mcpb-manifest-v0.3.schema.json", diff --git a/scripts/build-mcpb-schema.js b/scripts/build-mcpb-schema.js index 4068f91..c669528 100644 --- a/scripts/build-mcpb-schema.js +++ b/scripts/build-mcpb-schema.js @@ -12,13 +12,17 @@ import path from "node:path"; const distDir = path.join(import.meta.dirname, "../dist"); const schemasDir = path.join(import.meta.dirname, "../schemas"); -// Versioned manifest schemas +// Versioned manifest schemas (for both dist/ and schemas/) const versionedManifestSchemas = { "mcpb-manifest-v0.1": McpbManifestSchema_v0_1, "mcpb-manifest-v0.2": McpbManifestSchema_v0_2, "mcpb-manifest-v0.3": McpbManifestSchema_v0_3, "mcpb-manifest-latest": McpbManifestSchemaLatest, - "mcpb-manifest": McpbManifestSchemaLatest, // Alias for latest +}; + +// Legacy alias (only for schemas/ directory, not exported from package) +const schemasOnlyAliases = { + "mcpb-manifest": McpbManifestSchemaLatest, }; // Other schemas @@ -26,11 +30,12 @@ const otherSchemas = { "mcpb-signature-info": McpbSignatureInfoSchema, }; -const allSchemas = { ...versionedManifestSchemas, ...otherSchemas }; - -// Generate all schemas to dist/ +// Generate versioned schemas and other schemas to dist/ await fs.mkdir(distDir, { recursive: true }); -for (const [key, schema] of Object.entries(allSchemas)) { +for (const [key, schema] of Object.entries({ + ...versionedManifestSchemas, + ...otherSchemas, +})) { const jsonSchema = zodToJsonSchema(schema); const filePath = path.join(distDir, `${key}.schema.json`); await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { @@ -38,9 +43,12 @@ for (const [key, schema] of Object.entries(allSchemas)) { }); } -// Generate all versioned manifest schemas to schemas/ +// Generate all manifest schemas to schemas/ (including legacy alias) await fs.mkdir(schemasDir, { recursive: true }); -for (const [key, schema] of Object.entries(versionedManifestSchemas)) { +for (const [key, schema] of Object.entries({ + ...versionedManifestSchemas, + ...schemasOnlyAliases, +})) { const jsonSchema = zodToJsonSchema(schema); const filePath = path.join(schemasDir, `${key}.schema.json`); await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { From e7282946b67ebd8f1ecd0426d49818863d9eb701 Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:51:27 -0700 Subject: [PATCH 05/11] fix: lint errors - remove unused import and format files - Remove unused McpbManifestSchema import from types.ts - Run prettier on modified files --- CONTRIBUTING.md | 3 +++ MANIFEST.md | 22 +++++++++++----------- package.json | 2 +- src/schemas/0.1.ts | 2 +- src/types.ts | 7 +++---- test/schemas.test.ts | 1 - test/valid-manifest-0.2.json | 36 +++++++++++++++++------------------- test/valid-manifest.json | 6 ++---- 8 files changed, 38 insertions(+), 41 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf9d8e8..7b19f2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,7 @@ To set up commit signing, see [GitHub's documentation on commit signature verifi ### Bug Reports When filing a bug report, please include: + - Clear description of the issue - Steps to reproduce - Expected vs actual behavior @@ -55,6 +56,7 @@ When filing a bug report, please include: ### Feature Requests We welcome feature suggestions! Please: + - Clearly describe the feature and use case - Explain why this would be valuable to users - Consider if it aligns with the project's goals @@ -62,6 +64,7 @@ We welcome feature suggestions! Please: ### Code Contributions We especially welcome: + - Bug fixes - Documentation improvements - Test coverage improvements diff --git a/MANIFEST.md b/MANIFEST.md index 837cee8..bedc65e 100644 --- a/MANIFEST.md +++ b/MANIFEST.md @@ -17,7 +17,7 @@ A basic `manifest.json` with just the required fields looks like this: "description": "A simple MCP extension", // Brief description of what the extension does "author": { // Author information (required) - "name": "Extension Author" // Author's name (required field) + "name": "Extension Author", // Author's name (required field) }, "server": { // Server configuration (required) @@ -28,10 +28,10 @@ A basic `manifest.json` with just the required fields looks like this: "command": "node", // Command to run the server "args": [ // Arguments passed to the command - "${__dirname}/server/index.js" // ${__dirname} is replaced with the extension's directory - ] - } - } + "${__dirname}/server/index.js", // ${__dirname} is replaced with the extension's directory + ], + }, + }, } ``` @@ -212,12 +212,12 @@ A full `manifest.json` with most of the optional fields looks like this: "type": "string" } } - }, + } } } ] } - }, + } } } } @@ -254,7 +254,7 @@ A full `manifest.json` with most of the optional fields looks like this: - **privacy_policies**: Array of URLs to privacy policies for external services that handle user data. Required when the extension connects to external services (first- or third-party) that process user data. Each URL should link to the respective service's privacy policy document. - **compatibility**: Compatibility requirements (client app version, platforms, and runtime versions). - **user_config**: User-configurable options for the extension (see User Configuration section). -- **_meta**: Platform-specific client integration metadata (e.g., Windows `package_family_name`, macOS bundle identifiers) enabling tighter OS/app store integration. The keys in the `_meta` object are reverse-DNS namespaced, and the values are a dictionary of platform-specific metadata. +- **\_meta**: Platform-specific client integration metadata (e.g., Windows `package_family_name`, macOS bundle identifiers) enabling tighter OS/app store integration. The keys in the `_meta` object are reverse-DNS namespaced, and the values are a dictionary of platform-specific metadata. - **localization**: Location of translated strings for user-facing fields (`resources` path containing a `${locale}` placeholder and `default_locale`). ### Localization @@ -268,15 +268,16 @@ Provide localized strings without bloating the manifest by pointing to external } ``` -- `resources` must include a `${locale}` placeholder. Clients resolve it relative to the server install directory. +- `resources` must include a `${locale}` placeholder. Clients resolve it relative to the server install directory. - This property is optional, and its default value is **`mcpb-resources/${locale}.json`**. - `default_locale` must be a valid [BCP 47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) identifier such as `en-US` or `zh-Hans`. - This property is optional, and its default value is `en-US`. - Values for the default locale stay in the main manifest; localized files only need to contain overrides. -For tools and prompts, the descriptions are also localizable. +For tools and prompts, the descriptions are also localizable. #### Client guidelines + - if a client wants to show tool or prompt descriptions in their UI, the client should look for the locale-specific description override in the corresponding per-locale file. - clients should only look for tools/prompts present in the manifest.json, i.e. prompts and tools that only exist in the per-locale file should be ignored. - Clients should apply locale fallbacks if the client/user locale is not represented by the server. For example, if the user is in the `es-UY` locale but the server does not include that per-locale file, the client should look for an approrpiate fallback, e.g. `es-MX` or `es-ES`, or fall back to the values in the manifest. @@ -712,4 +713,3 @@ The `_generated` fields: - **prompts_generated**: Server generates additional prompts beyond those listed (default: false) This helps implementing apps understand that querying the server at runtime will reveal more capabilities than what's declared in the manifest. - diff --git a/package.json b/package.json index 68b3148..051d638 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/schemas/0.1.ts b/src/schemas/0.1.ts index 3ff5453..4d77ccc 100644 --- a/src/schemas/0.1.ts +++ b/src/schemas/0.1.ts @@ -98,7 +98,7 @@ export const McpbManifestSchema = z screenshots: z.array(z.string()).optional(), server: McpbManifestServerSchema, tools: z.array(McpbManifestToolSchema).optional(), - tools_generated: z.boolean().optional(), + tools_generated: z.boolean().optional(), prompts: z.array(McpbManifestPromptSchema).optional(), prompts_generated: z.boolean().optional(), keywords: z.array(z.string()).optional(), diff --git a/src/types.ts b/src/types.ts index 23c2061..852d52c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,8 @@ import type * as z from "zod"; +import type { McpbManifestSchema as McpbManifestSchema_v0_1 } from "./schemas/0.1.js"; +import type { McpbManifestSchema as McpbManifestSchema_v0_2 } from "./schemas/0.2.js"; +import type { McpbManifestSchema as McpbManifestSchema_v0_3 } from "./schemas/0.3.js"; import type { McpbManifestAuthorSchema, McpbManifestCompatibilitySchema, @@ -7,7 +10,6 @@ import type { McpbManifestPlatformOverrideSchema, McpbManifestPromptSchema, McpbManifestRepositorySchema, - McpbManifestSchema, McpbManifestServerSchema, McpbManifestToolSchema, McpbSignatureInfoSchema, @@ -15,9 +17,6 @@ import type { McpbUserConfigValuesSchema, McpServerConfigSchema, } from "./schemas/latest.js"; -import type { McpbManifestSchema as McpbManifestSchema_v0_1 } from "./schemas/0.1.js"; -import type { McpbManifestSchema as McpbManifestSchema_v0_2 } from "./schemas/0.2.js"; -import type { McpbManifestSchema as McpbManifestSchema_v0_3 } from "./schemas/0.3.js"; export type McpServerConfig = z.infer; diff --git a/test/schemas.test.ts b/test/schemas.test.ts index 325af17..d05551a 100644 --- a/test/schemas.test.ts +++ b/test/schemas.test.ts @@ -335,5 +335,4 @@ describe("McpbManifestSchema", () => { expect(result.success).toBe(true); }); }); - }); diff --git a/test/valid-manifest-0.2.json b/test/valid-manifest-0.2.json index c6f5fdb..51130df 100644 --- a/test/valid-manifest-0.2.json +++ b/test/valid-manifest-0.2.json @@ -1,21 +1,19 @@ { - "manifest_version": "0.2", - "name": "legacy-extension", - "display_name": "Legacy Extension", - "version": "1.0.0", - "description": "An extension that predates 0.3", - "author": { - "name": "Legacy Author", - "email": "legacy@example.com" - }, - "server": { - "type": "node", - "entry_point": "server/index.js", - "mcp_config": { - "command": "node", - "args": [ - "${__dirname}/server/index.js" - ] - } + "manifest_version": "0.2", + "name": "legacy-extension", + "display_name": "Legacy Extension", + "version": "1.0.0", + "description": "An extension that predates 0.3", + "author": { + "name": "Legacy Author", + "email": "legacy@example.com" + }, + "server": { + "type": "node", + "entry_point": "server/index.js", + "mcp_config": { + "command": "node", + "args": ["${__dirname}/server/index.js"] } -} \ No newline at end of file + } +} diff --git a/test/valid-manifest.json b/test/valid-manifest.json index c833deb..fcc9b9b 100644 --- a/test/valid-manifest.json +++ b/test/valid-manifest.json @@ -13,9 +13,7 @@ "entry_point": "server/index.js", "mcp_config": { "command": "node", - "args": [ - "${__dirname}/server/index.js" - ] + "args": ["${__dirname}/server/index.js"] } } -} \ No newline at end of file +} From 48232bf64ef5413e3dd866ecddacc2ef826c21cd Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:57:49 -0700 Subject: [PATCH 06/11] chore: bump version to 1.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 051d638..cec3546 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@anthropic-ai/mcpb", "description": "Tools for building MCP Bundles", - "version": "1.1.2", + "version": "1.1.3", "type": "module", "main": "dist/index.js", "module": "dist/index.js", From ae3d9614e23d3e07f66007054f93c3bb837ca26a Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:58:15 -0700 Subject: [PATCH 07/11] Revert "chore: bump version to 1.1.3" This reverts commit 48232bf64ef5413e3dd866ecddacc2ef826c21cd. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cec3546..051d638 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@anthropic-ai/mcpb", "description": "Tools for building MCP Bundles", - "version": "1.1.3", + "version": "1.1.2", "type": "module", "main": "dist/index.js", "module": "dist/index.js", From db5d6be33c2af89413f7b273a1e55f8caf80f793 Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:58:41 -0700 Subject: [PATCH 08/11] Reapply "chore: bump version to 1.1.3" This reverts commit ae3d9614e23d3e07f66007054f93c3bb837ca26a. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 051d638..cec3546 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@anthropic-ai/mcpb", "description": "Tools for building MCP Bundles", - "version": "1.1.2", + "version": "1.1.3", "type": "module", "main": "dist/index.js", "module": "dist/index.js", From 789b37087c01bd00f2cbf3441363776142241b3b Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 16:59:06 -0700 Subject: [PATCH 09/11] revert: restore McpbManifest type to use latest schema Reverted the discriminated union type change. McpbManifest now uses the latest schema as before. Consumers can use versioned schemas directly if they need to validate specific versions. --- src/types.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/types.ts b/src/types.ts index 852d52c..0b6b2a3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,5 @@ import type * as z from "zod"; -import type { McpbManifestSchema as McpbManifestSchema_v0_1 } from "./schemas/0.1.js"; -import type { McpbManifestSchema as McpbManifestSchema_v0_2 } from "./schemas/0.2.js"; -import type { McpbManifestSchema as McpbManifestSchema_v0_3 } from "./schemas/0.3.js"; import type { McpbManifestAuthorSchema, McpbManifestCompatibilitySchema, @@ -10,6 +7,7 @@ import type { McpbManifestPlatformOverrideSchema, McpbManifestPromptSchema, McpbManifestRepositorySchema, + McpbManifestSchema, McpbManifestServerSchema, McpbManifestToolSchema, McpbSignatureInfoSchema, @@ -48,14 +46,7 @@ export type McpbUserConfigurationOption = z.infer< export type McpbUserConfigValues = z.infer; -/** - * Discriminated union of all supported manifest versions. - * Discriminated by manifest_version or dxt_version field. - */ -export type McpbManifest = - | z.infer - | z.infer - | z.infer; +export type McpbManifest = z.infer; /** * Information about a MCPB package signature From 16606975882b548e662f775ce4811b82d217492e Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 17:01:04 -0700 Subject: [PATCH 10/11] refactor: remove legacy mcpb-manifest.schema.json Removed the non-versioned mcpb-manifest.schema.json from schemas/ directory. All schemas are now explicitly versioned. Available schemas: - mcpb-manifest-v0.1.schema.json - mcpb-manifest-v0.2.schema.json - mcpb-manifest-v0.3.schema.json - mcpb-manifest-latest.schema.json Consumers should use -latest or specific version to be explicit about which schema version they're validating against. --- schemas/mcpb-manifest.schema.json | 376 ------------------------------ scripts/build-mcpb-schema.js | 23 +- 2 files changed, 7 insertions(+), 392 deletions(-) delete mode 100644 schemas/mcpb-manifest.schema.json diff --git a/schemas/mcpb-manifest.schema.json b/schemas/mcpb-manifest.schema.json deleted file mode 100644 index a2dc082..0000000 --- a/schemas/mcpb-manifest.schema.json +++ /dev/null @@ -1,376 +0,0 @@ -{ - "type": "object", - "properties": { - "$schema": { - "type": "string" - }, - "dxt_version": { - "type": "string", - "const": "0.3", - "description": "@deprecated Use manifest_version instead" - }, - "manifest_version": { - "type": "string", - "const": "0.3" - }, - "name": { - "type": "string" - }, - "display_name": { - "type": "string" - }, - "version": { - "type": "string" - }, - "description": { - "type": "string" - }, - "long_description": { - "type": "string" - }, - "author": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "email": { - "type": "string", - "format": "email" - }, - "url": { - "type": "string", - "format": "uri" - } - }, - "required": [ - "name" - ], - "additionalProperties": false - }, - "repository": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "url": { - "type": "string", - "format": "uri" - } - }, - "required": [ - "type", - "url" - ], - "additionalProperties": false - }, - "homepage": { - "type": "string", - "format": "uri" - }, - "documentation": { - "type": "string", - "format": "uri" - }, - "support": { - "type": "string", - "format": "uri" - }, - "icon": { - "type": "string" - }, - "icons": { - "type": "array", - "items": { - "type": "object", - "properties": { - "src": { - "type": "string" - }, - "sizes": { - "type": "string", - "pattern": "^\\d+x\\d+$" - }, - "theme": { - "type": "string", - "minLength": 1 - } - }, - "required": [ - "src", - "sizes" - ], - "additionalProperties": false - } - }, - "screenshots": { - "type": "array", - "items": { - "type": "string" - } - }, - "localization": { - "type": "object", - "properties": { - "resources": { - "type": "string", - "pattern": "\\$\\{locale\\}" - }, - "default_locale": { - "type": "string", - "pattern": "^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$" - } - }, - "required": [ - "resources", - "default_locale" - ], - "additionalProperties": false - }, - "server": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "python", - "node", - "binary" - ] - }, - "entry_point": { - "type": "string" - }, - "mcp_config": { - "type": "object", - "properties": { - "command": { - "type": "string" - }, - "args": { - "type": "array", - "items": { - "type": "string" - } - }, - "env": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "platform_overrides": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "command": { - "$ref": "#/properties/server/properties/mcp_config/properties/command" - }, - "args": { - "$ref": "#/properties/server/properties/mcp_config/properties/args" - }, - "env": { - "$ref": "#/properties/server/properties/mcp_config/properties/env" - } - }, - "additionalProperties": false - } - } - }, - "required": [ - "command" - ], - "additionalProperties": false - } - }, - "required": [ - "type", - "entry_point", - "mcp_config" - ], - "additionalProperties": false - }, - "tools": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ], - "additionalProperties": false - } - }, - "tools_generated": { - "type": "boolean" - }, - "prompts": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "arguments": { - "type": "array", - "items": { - "type": "string" - } - }, - "text": { - "type": "string" - } - }, - "required": [ - "name", - "text" - ], - "additionalProperties": false - } - }, - "prompts_generated": { - "type": "boolean" - }, - "keywords": { - "type": "array", - "items": { - "type": "string" - } - }, - "license": { - "type": "string" - }, - "privacy_policies": { - "type": "array", - "items": { - "type": "string", - "format": "uri" - } - }, - "compatibility": { - "type": "object", - "properties": { - "claude_desktop": { - "type": "string" - }, - "platforms": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "darwin", - "win32", - "linux" - ] - } - }, - "runtimes": { - "type": "object", - "properties": { - "python": { - "type": "string" - }, - "node": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "user_config": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "directory", - "file" - ] - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "required": { - "type": "boolean" - }, - "default": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "multiple": { - "type": "boolean" - }, - "sensitive": { - "type": "boolean" - }, - "min": { - "type": "number" - }, - "max": { - "type": "number" - } - }, - "required": [ - "type", - "title", - "description" - ], - "additionalProperties": false - } - }, - "_meta": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": {} - } - } - }, - "required": [ - "name", - "version", - "description", - "author", - "server" - ], - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" -} \ No newline at end of file diff --git a/scripts/build-mcpb-schema.js b/scripts/build-mcpb-schema.js index c669528..a62fcdb 100644 --- a/scripts/build-mcpb-schema.js +++ b/scripts/build-mcpb-schema.js @@ -12,7 +12,7 @@ import path from "node:path"; const distDir = path.join(import.meta.dirname, "../dist"); const schemasDir = path.join(import.meta.dirname, "../schemas"); -// Versioned manifest schemas (for both dist/ and schemas/) +// Versioned manifest schemas const versionedManifestSchemas = { "mcpb-manifest-v0.1": McpbManifestSchema_v0_1, "mcpb-manifest-v0.2": McpbManifestSchema_v0_2, @@ -20,22 +20,16 @@ const versionedManifestSchemas = { "mcpb-manifest-latest": McpbManifestSchemaLatest, }; -// Legacy alias (only for schemas/ directory, not exported from package) -const schemasOnlyAliases = { - "mcpb-manifest": McpbManifestSchemaLatest, -}; - // Other schemas const otherSchemas = { "mcpb-signature-info": McpbSignatureInfoSchema, }; -// Generate versioned schemas and other schemas to dist/ +const allSchemas = { ...versionedManifestSchemas, ...otherSchemas }; + +// Generate all schemas to dist/ await fs.mkdir(distDir, { recursive: true }); -for (const [key, schema] of Object.entries({ - ...versionedManifestSchemas, - ...otherSchemas, -})) { +for (const [key, schema] of Object.entries(allSchemas)) { const jsonSchema = zodToJsonSchema(schema); const filePath = path.join(distDir, `${key}.schema.json`); await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { @@ -43,12 +37,9 @@ for (const [key, schema] of Object.entries({ }); } -// Generate all manifest schemas to schemas/ (including legacy alias) +// Generate all versioned manifest schemas to schemas/ await fs.mkdir(schemasDir, { recursive: true }); -for (const [key, schema] of Object.entries({ - ...versionedManifestSchemas, - ...schemasOnlyAliases, -})) { +for (const [key, schema] of Object.entries(versionedManifestSchemas)) { const jsonSchema = zodToJsonSchema(schema); const filePath = path.join(schemasDir, `${key}.schema.json`); await fs.writeFile(filePath, JSON.stringify(jsonSchema, null, 2), { From c29d1000f394f8c11a866e44df3f62cc180ae7b4 Mon Sep 17 00:00:00 2001 From: Joan Xie Date: Wed, 29 Oct 2025 17:06:55 -0700 Subject: [PATCH 11/11] feat: add any schema --- src/schemas/any.ts | 15 +++++++++++++++ src/schemas/index.ts | 1 + 2 files changed, 16 insertions(+) create mode 100644 src/schemas/any.ts diff --git a/src/schemas/any.ts b/src/schemas/any.ts new file mode 100644 index 0000000..bd7cec8 --- /dev/null +++ b/src/schemas/any.ts @@ -0,0 +1,15 @@ +import * as z from "zod"; + +import * as v0_1 from "./0.1.js"; +import * as v0_2 from "./0.2.js"; +import * as v0_3 from "./0.3.js"; + +/** + * Union schema that accepts any supported manifest version (0.1, 0.2, 0.3). + * Use this when you need to validate manifests of any version. + */ +export const McpbManifestSchema = z.union([ + v0_1.McpbManifestSchema, + v0_2.McpbManifestSchema, + v0_3.McpbManifestSchema, +]); diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 1b7c64b..3729f0e 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -1,6 +1,7 @@ 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 any from "./any.js"; export * as latest from "./latest.js"; export { MANIFEST_VERSION as LATEST_MANIFEST_VERSION,