feat: add UV runtime support in manifest v0.4

Add UV as a new server type for Python extensions that use UV runtime
for dependency management instead of bundling dependencies.

Schema changes (v0.4):
- Add "uv" to server.type enum
- Make mcp_config optional (not needed for UV type)
- UV extensions rely on pyproject.toml for dependencies

Documentation:
- Add UV runtime section to MANIFEST.md explaining benefits and usage
- Update README.md to recommend UV runtime for Python
- Add complete hello-world-uv example

Benefits of UV runtime:
- Cross-platform support (Windows/macOS/Linux, Intel/ARM)
- Small bundle size (~100 KB vs 5-10 MB)
- Handles compiled dependencies portably
- No user Python installation required

Example manifest:
{
  "manifest_version": "0.4",
  "server": {
    "type": "uv",
    "entry_point": "src/server.py"
  }
}

Co-authored-by: Joan <joan@anthropic.com>
This commit is contained in:
Joan Xie 2025-11-12 20:27:24 -08:00
commit d90365e626
No known key found for this signature in database
16 changed files with 913 additions and 4 deletions

View file

@ -1,7 +1,7 @@
# MCPB Manifest.json Spec # MCPB Manifest.json Spec
Current version: `0.3` Current version: `0.3`
Last updated: 2025-10-24 Last updated: 2025-12-02
## Manifest Schema ## Manifest Schema
@ -398,6 +398,55 @@ The `server` object defines how to run the MCP server:
### Server Types ### Server Types
Four server types are supported:
- **`node`**: Node.js server with bundled dependencies
- **`python`**: Python server with bundled dependencies
- **`binary`**: Compiled executable
- **`uv`**: Python server using UV runtime (experimental, v0.4+)
### UV Runtime (Experimental, v0.4+)
> **Note:** UV runtime support is experimental and may change in future versions.
The `uv` server type enables cross-platform Python extensions without bundling dependencies. Instead, dependencies are declared in `pyproject.toml` and installed by the host application using UV.
**Benefits:**
- Cross-platform support (Windows, macOS, Linux; Intel, ARM)
- Small bundle size (~100 KB vs 5-10 MB)
- Handles compiled dependencies (pydantic, numpy, etc.)
- No user Python installation required
**Example:**
```json
{
"manifest_version": "0.4",
"server": {
"type": "uv",
"entry_point": "src/server.py"
}
}
```
**Requirements:**
- Must include `pyproject.toml` with dependencies
- Must NOT include `server/lib/` or `server/venv/`
- `mcp_config` is optional (host manages execution)
**Package structure:**
```
extension.mcpb
├── manifest.json # server.type = "uv"
├── pyproject.toml # Dependencies
├── .mcpbignore # Exclude .venv, server/lib
└── src/
└── server.py
```
See `examples/hello-world-uv` for a complete example.
### Node, Python, and Binary Types
1. **Python**: `server.type = "python"` 1. **Python**: `server.type = "python"`
- Requires `entry_point` to Python file - Requires `entry_point` to Python file
- All dependencies must be bundled in the MCPB - All dependencies must be bundled in the MCPB

View file

@ -109,12 +109,22 @@ bundle.mcpb (ZIP file)
### Bundling Dependencies ### Bundling Dependencies
**Python Bundles:** **UV Runtime (Experimental - v0.4+):**
- Use `server.type = "uv"` in manifest
- Include `pyproject.toml` with dependencies (no bundled packages needed)
- Host application manages Python and dependencies automatically
- Works cross-platform without user Python installation
- See `examples/hello-world-uv`
**Python Bundles (Traditional):**
- Use `server.type = "python"` in manifest
- Bundle all required packages in `server/lib/` directory - Bundle all required packages in `server/lib/` directory
- OR bundle a complete virtual environment in `server/venv/` - OR bundle a complete virtual environment in `server/venv/`
- Use tools like `pip-tools`, `poetry`, or `pipenv` to create reproducible bundles - Use tools like `pip-tools`, `poetry`, or `pipenv` to create reproducible bundles
- Set `PYTHONPATH` to include bundled packages via `mcp_config.env` - Set `PYTHONPATH` to include bundled packages via `mcp_config.env`
- **Limitation**: Cannot portably bundle compiled dependencies (e.g., pydantic, which the MCP Python SDK requires)
**Node.js Bundles:** **Node.js Bundles:**

View file

@ -0,0 +1,8 @@
.venv/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
*.egg-info/
server/lib/
server/venv/

View file

@ -0,0 +1,62 @@
# Hello World UV Runtime Example (Experimental)
> **Note:** UV runtime support is experimental and may change in future versions.
This example demonstrates a minimal MCP server using **UV runtime**.
## What is UV Runtime?
UV runtime lets Claude Desktop automatically manage Python and dependencies for your extension:
- Downloads the correct Python version for the user's platform
- Creates an isolated virtual environment
- Installs dependencies from `pyproject.toml`
- Works cross-platform (Windows, macOS, Linux) without user setup
## Structure
```
hello-world-uv/
├── manifest.json # server.type = "uv"
├── pyproject.toml # Dependencies listed here
├── .mcpbignore # Exclude build artifacts
└── src/
└── server.py # MCP server implementation
```
## Key Differences from Python Runtime
**UV Runtime** (this example):
- `server.type = "uv"`
- No bundled dependencies
- No `mcp_config` needed
- Small bundle size (~2 KB)
- Works on any platform
**Python Runtime** (traditional):
- `server.type = "python"`
- Must bundle dependencies in `server/lib/`
- Requires `mcp_config` with PYTHONPATH
- Larger bundle size
- Only works with pure Python (no compiled deps)
## Installing
```bash
mcpb pack
```
Install the generated `.mcpb` file in Claude Desktop.
## Testing Locally
```bash
# Install dependencies
uv sync
# Run server
uv run src/server.py
```
## Tools
- **say_hello** - Greets a person by name

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

View file

@ -0,0 +1,23 @@
{
"manifest_version": "0.4",
"name": "hello-world-uv",
"display_name": "Hello World (UV Runtime)",
"version": "1.0.0",
"description": "Simple MCP server using UV runtime",
"author": {
"name": "Anthropic"
},
"icon": "icon.png",
"server": {
"type": "uv",
"entry_point": "src/server.py"
},
"compatibility": {
"platforms": ["darwin", "linux", "win32"],
"runtimes": {
"python": ">=3.10"
}
},
"keywords": ["example", "hello-world", "uv"],
"license": "MIT"
}

View file

@ -0,0 +1,8 @@
[project]
name = "hello-world-uv"
version = "1.0.0"
description = "Simple MCP server using UV runtime"
requires-python = ">=3.10"
dependencies = [
"mcp>=1.0.0",
]

View file

@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""Hello World MCP server using UV runtime."""
import asyncio
from mcp.server.models import InitializationOptions
import mcp.types as types
from mcp.server import NotificationOptions, Server
import mcp.server.stdio
server = Server("hello-world-uv")
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
"""List available tools."""
return [
types.Tool(
name="say_hello",
description="Say hello to someone",
inputSchema={
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet",
}
},
"required": ["name"],
},
)
]
@server.call_tool()
async def handle_call_tool(
name: str, arguments: dict | None
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
"""Handle tool calls."""
if name == "say_hello":
person_name = arguments.get("name", "World") if arguments else "World"
return [types.TextContent(type="text", text=f"Hello, {person_name}!")]
raise ValueError(f"Unknown tool: {name}")
async def main():
"""Run the server."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="hello-world-uv",
server_version="1.0.0",
capabilities=server.get_capabilities(
notification_options=NotificationOptions(),
experimental_capabilities={},
),
),
)
if __name__ == "__main__":
asyncio.run(main())

View file

@ -0,0 +1,376 @@
{
"type": "object",
"properties": {
"$schema": {
"type": "string"
},
"dxt_version": {
"type": "string",
"const": "0.4",
"description": "@deprecated Use manifest_version instead"
},
"manifest_version": {
"type": "string",
"const": "0.4"
},
"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"
},
"size": {
"type": "string",
"pattern": "^\\d+x\\d+$"
},
"theme": {
"type": "string",
"minLength": 1
}
},
"required": [
"src",
"size"
],
"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",
"uv"
]
},
"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"
],
"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#"
}

View file

@ -1,6 +1,7 @@
import { McpbManifestSchema as McpbManifestSchema_v0_1 } from "../dist/schemas/0.1.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_2 } from "../dist/schemas/0.2.js";
import { McpbManifestSchema as McpbManifestSchema_v0_3 } from "../dist/schemas/0.3.js"; import { McpbManifestSchema as McpbManifestSchema_v0_3 } from "../dist/schemas/0.3.js";
import { McpbManifestSchema as McpbManifestSchema_v0_4 } from "../dist/schemas/0.4.js";
import { McpbSignatureInfoSchema } from "../dist/shared/common.js"; import { McpbSignatureInfoSchema } from "../dist/shared/common.js";
import { zodToJsonSchema } from "zod-to-json-schema"; import { zodToJsonSchema } from "zod-to-json-schema";
import fs from "node:fs/promises"; import fs from "node:fs/promises";
@ -14,6 +15,7 @@ const versionedManifestSchemas = {
"mcpb-manifest-v0.1": McpbManifestSchema_v0_1, "mcpb-manifest-v0.1": McpbManifestSchema_v0_1,
"mcpb-manifest-v0.2": McpbManifestSchema_v0_2, "mcpb-manifest-v0.2": McpbManifestSchema_v0_2,
"mcpb-manifest-v0.3": McpbManifestSchema_v0_3, "mcpb-manifest-v0.3": McpbManifestSchema_v0_3,
"mcpb-manifest-v0.4": McpbManifestSchema_v0_4,
}; };
// Other schemas // Other schemas

145
src/schemas/0.4.ts Normal file
View file

@ -0,0 +1,145 @@
// v0.4: Adds UV runtime support for Python extensions
import * as z from "zod";
export const MANIFEST_VERSION = "0.4";
const LOCALE_PLACEHOLDER_REGEX = /\$\{locale\}/i;
const BCP47_REGEX = /^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$/;
const ICON_SIZE_REGEX = /^\d+x\d+$/;
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", "uv"]),
entry_point: z.string(),
// mcp_config is optional for UV type (UV handles execution)
mcp_config: McpbManifestMcpConfigSchema.optional(),
});
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 McpbManifestLocalizationSchema = z.strictObject({
resources: z
.string()
.regex(
LOCALE_PLACEHOLDER_REGEX,
'resources must include a "${locale}" placeholder',
),
default_locale: z
.string()
.regex(
BCP47_REGEX,
"default_locale must be a valid BCP 47 locale identifier",
),
});
export const McpbManifestIconSchema = z.strictObject({
src: z.string(),
size: z
.string()
.regex(
ICON_SIZE_REGEX,
'size must be in the format "WIDTHxHEIGHT" (e.g., "16x16")',
),
theme: z.string().min(1, "theme cannot be empty when provided").optional(),
});
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(),
icons: z.array(McpbManifestIconSchema).optional(),
screenshots: z.array(z.string()).optional(),
localization: McpbManifestLocalizationSchema.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",
});

View file

@ -3,13 +3,15 @@ import * as z from "zod";
import * as v0_1 from "./0.1.js"; import * as v0_1 from "./0.1.js";
import * as v0_2 from "./0.2.js"; import * as v0_2 from "./0.2.js";
import * as v0_3 from "./0.3.js"; import * as v0_3 from "./0.3.js";
import * as v0_4 from "./0.4.js";
/** /**
* Union schema that accepts any supported manifest version (0.1, 0.2, 0.3). * Union schema that accepts any supported manifest version.
* Use this when you need to validate manifests of any version. * Use this when you need to validate manifests of any version.
*/ */
export const McpbManifestSchema = z.union([ export const McpbManifestSchema = z.union([
v0_1.McpbManifestSchema, v0_1.McpbManifestSchema,
v0_2.McpbManifestSchema, v0_2.McpbManifestSchema,
v0_3.McpbManifestSchema, v0_3.McpbManifestSchema,
v0_4.McpbManifestSchema,
]); ]);

View file

@ -1,10 +1,12 @@
import { McpbManifestSchema as ManifestSchemaV0_1 } from "./0.1.js"; import { McpbManifestSchema as ManifestSchemaV0_1 } from "./0.1.js";
import { McpbManifestSchema as ManifestSchemaV0_2 } from "./0.2.js"; import { McpbManifestSchema as ManifestSchemaV0_2 } from "./0.2.js";
import { McpbManifestSchema as ManifestSchemaV0_3 } from "./0.3.js"; import { McpbManifestSchema as ManifestSchemaV0_3 } from "./0.3.js";
import { McpbManifestSchema as ManifestSchemaV0_4 } from "./0.4.js";
export * as v0_1 from "./0.1.js"; export * as v0_1 from "./0.1.js";
export * as v0_2 from "./0.2.js"; export * as v0_2 from "./0.2.js";
export * as v0_3 from "./0.3.js"; export * as v0_3 from "./0.3.js";
export * as v0_4 from "./0.4.js";
export * as vAny from "./any.js"; export * as vAny from "./any.js";
/** /**
@ -14,4 +16,5 @@ export const VERSIONED_MANIFEST_SCHEMAS = {
"0.1": ManifestSchemaV0_1, "0.1": ManifestSchemaV0_1,
"0.2": ManifestSchemaV0_2, "0.2": ManifestSchemaV0_2,
"0.3": ManifestSchemaV0_3, "0.3": ManifestSchemaV0_3,
"0.4": ManifestSchemaV0_4,
} as const; } as const;

151
src/schemas_loose/0.4.ts Normal file
View file

@ -0,0 +1,151 @@
import * as z from "zod";
export const MANIFEST_VERSION = "0.4";
const LOCALE_PLACEHOLDER_REGEX = /\$\{locale\}/i;
const BCP47_REGEX = /^[A-Za-z0-9]{2,8}(?:-[A-Za-z0-9]{1,8})*$/;
const ICON_SIZE_REGEX = /^\d+x\d+$/;
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", "uv"]),
entry_point: z.string(),
// mcp_config is optional for UV type (UV handles execution)
mcp_config: McpbManifestMcpConfigSchema.optional(),
});
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 McpbManifestLocalizationSchema = z
.object({
resources: z
.string()
.regex(
LOCALE_PLACEHOLDER_REGEX,
'resources must include a "${locale}" placeholder',
),
default_locale: z
.string()
.regex(
BCP47_REGEX,
"default_locale must be a valid BCP 47 locale identifier",
),
})
.passthrough();
export const McpbManifestIconSchema = z
.object({
src: z.string(),
size: z
.string()
.regex(
ICON_SIZE_REGEX,
'size must be in the format "WIDTHxHEIGHT" (e.g., "16x16")',
),
theme: z.string().min(1).optional(),
})
.passthrough();
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(),
icons: z.array(McpbManifestIconSchema).optional(),
screenshots: z.array(z.string()).optional(),
localization: McpbManifestLocalizationSchema.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(),
})
.passthrough()
.refine((data) => !!(data.dxt_version || data.manifest_version), {
message:
"Either 'dxt_version' (deprecated) or 'manifest_version' must be provided",
});

View file

@ -1,3 +1,4 @@
export * as v0_1 from "./0.1.js"; export * as v0_1 from "./0.1.js";
export * as v0_2 from "./0.2.js"; export * as v0_2 from "./0.2.js";
export * as v0_3 from "./0.3.js"; export * as v0_3 from "./0.3.js";
export * as v0_4 from "./0.4.js";

View file

@ -1,14 +1,16 @@
import { McpbManifestSchema as ManifestSchemaV0_1 } from "../schemas/0.1.js"; import { McpbManifestSchema as ManifestSchemaV0_1 } from "../schemas/0.1.js";
import { McpbManifestSchema as ManifestSchemaV0_2 } from "../schemas/0.2.js"; import { McpbManifestSchema as ManifestSchemaV0_2 } from "../schemas/0.2.js";
import { McpbManifestSchema as ManifestSchemaV0_3 } from "../schemas/0.3.js"; import { McpbManifestSchema as ManifestSchemaV0_3 } from "../schemas/0.3.js";
import { McpbManifestSchema as ManifestSchemaV0_4 } from "../schemas/0.4.js";
import { McpbManifestSchema as LooseManifestSchemaV0_1 } from "../schemas_loose/0.1.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 LooseManifestSchemaV0_2 } from "../schemas_loose/0.2.js";
import { McpbManifestSchema as LooseManifestSchemaV0_3 } from "../schemas_loose/0.3.js"; import { McpbManifestSchema as LooseManifestSchemaV0_3 } from "../schemas_loose/0.3.js";
import { McpbManifestSchema as LooseManifestSchemaV0_4 } from "../schemas_loose/0.4.js";
/** /**
* Latest manifest version - indicates the maximum supported version by vAny schema * Latest manifest version - indicates the maximum supported version by vAny schema
*/ */
export const LATEST_MANIFEST_VERSION = "0.3" as const; export const LATEST_MANIFEST_VERSION = "0.4" as const;
/** /**
* Default manifest version for new packages * Default manifest version for new packages
@ -22,6 +24,7 @@ export const MANIFEST_SCHEMAS = {
"0.1": ManifestSchemaV0_1, "0.1": ManifestSchemaV0_1,
"0.2": ManifestSchemaV0_2, "0.2": ManifestSchemaV0_2,
"0.3": ManifestSchemaV0_3, "0.3": ManifestSchemaV0_3,
"0.4": ManifestSchemaV0_4,
} as const; } as const;
/** /**
@ -31,4 +34,5 @@ export const MANIFEST_SCHEMAS_LOOSE = {
"0.1": LooseManifestSchemaV0_1, "0.1": LooseManifestSchemaV0_1,
"0.2": LooseManifestSchemaV0_2, "0.2": LooseManifestSchemaV0_2,
"0.3": LooseManifestSchemaV0_3, "0.3": LooseManifestSchemaV0_3,
"0.4": LooseManifestSchemaV0_4,
} as const; } as const;