Problem
The MCPB manifest type/schema is defined independently in 4 places with divergent shapes. There is no single source of truth, and the definitions disagree on required vs optional fields, nesting structure, and which spec version they represent.
1. Registry — apps/registry/src/types.ts:16 (v0.2)
export interface MCPBManifest {
name : string ;
version : string ;
display_name ?: string ;
description ?: string ;
author ?: { name : string ; email ?: string ; url ?: string } ;
homepage ?: string ;
license ?: string ;
icon ?: string ;
repository ?: { type ?: string ; url ?: string } ;
server_type : 'node' | 'python' | 'binary' ; // flat, top-level
platforms ?: { [ platform : string ] : { command ?: string ; args ?: string [ ] ; env ?: Record < string , string > } } ;
tools ?: Array < { name : string ; description ?: string } > ;
prompts ?: Array < { name : string ; description ?: string } > ;
resources ?: Array < { name : string ; description ?: string } > ;
}
No manifest_version, no server object, no user_config, no entry_point
server_type is flat at the top level
platforms map instead of server.mcp_config
2. Registry validator — apps/registry/src/services/manifest-validator.ts
// Imperative validator, accepts BOTH v0.2 and v0.3 shapes:
const serverObj = manifest [ 'server' ] as Record < string , unknown > | undefined ;
const serverType = ( serverObj ?. [ 'type' ] as string ) ?? ( manifest [ 'server_type' ] as string ) ;
Accepts server.type (v0.3) or server_type (v0.2) — loose duck-typing
No Zod, no shared schema — hand-rolled instanceof-style checks
Validates a different field set than the MCPBManifest interface it type-guards
3. SDK — packages/sdk-typescript/src/cache.ts:37 (v0.3, Zod)
const McpbManifestSchema = z . object ( {
manifest_version : z . string ( ) ,
name : z . string ( ) ,
version : z . string ( ) ,
description : z . string ( ) , // required (not optional)
user_config : z . record ( z . string ( ) , UserConfigFieldSchema ) . optional ( ) ,
server : z . object ( {
type : z . enum ( [ "node" , "python" , "binary" ] ) ,
entry_point : z . string ( ) ,
mcp_config : z . object ( {
command : z . string ( ) ,
args : z . array ( z . string ( ) ) ,
env : z . record ( z . string ( ) , z . string ( ) ) . optional ( ) ,
} ) ,
} ) ,
} ) ;
description is required here, optional in all other definitions
Has manifest_version, user_config, nested server.mcp_config
Only Zod schema — not shared via packages/schemas
4. Web app — apps/web/src/lib/manifest.ts:40 (v0.3-ish, TypeScript)
export interface MCPBManifest {
manifest_version : string ;
name : string ;
version : string ;
description ?: string ; // optional here
author ?: { name : string ; email ?: string ; url ?: string } ;
homepage ?: string ;
license ?: string ;
icon ?: string ;
user_config ?: Record < string , UserConfigField > ;
server ?: ManifestServer ; // optional here
tools ?: Array < { name : string ; description ?: string } > ;
prompts ?: Array < { name : string ; description ?: string } > ;
resources ?: Array < { name : string ; description ?: string } > ;
}
v0.3 shape but server and description are optional (SDK requires both)
mcp_config and args are optional inside ManifestServer (SDK requires them)
No Zod, just TypeScript interfaces
5. CLI — packages/cli/src/commands/packages/run.ts:50 (v0.3, local)
interface McpbManifest {
manifest_version : string ;
name : string ;
version : string ;
description : string ;
user_config ?: Record < string , UserConfigField > ;
server : { type : "node" | "python" | "binary" ; entry_point : string ; mcp_config : McpConfig } ;
}
Divergence summary
Field
Registry v0.2
Validator
SDK v0.3
Web v0.3
CLI v0.3
manifest_version
✗
✗
required
required
required
description
optional
optional
required
optional
required
server (nested)
✗
accepts both
required
optional
required
server_type (flat)
required
accepts both
✗
✗
✗
user_config
✗
✗
optional
optional
optional
entry_point
✗
✗
required
optional
required
mcp_config
✗
✗
required
optional
required
author
optional
optional
✗
optional
✗
tools/prompts/resources
optional
validated
✗
optional
✗
platforms
optional
optional
✗
✗
✗
Proposed fix
Create McpbManifestSchema (Zod) in packages/schemas/src/manifest.ts — single source of truth for the v0.3 spec
Export McpbManifest type from packages/schemas — all consumers import from here
Update SDK cache.ts — delete local schema, import from @nimblebrain/mpak-schemas
Update web app manifest.ts — delete local interfaces, import from @nimblebrain/mpak-schemas
Update registry types.ts — either migrate to v0.3 or keep v0.2 as MCPBManifestV2 alongside v0.3
Update registry validator — rewrite using Zod .safeParse() from the shared schema (or keep imperative for backward compat with v0.2 uploads)
CLI local copy — already being removed in Move bundle runtime, config, and cache functions from CLI to SDK #59
Related
Problem
The MCPB manifest type/schema is defined independently in 4 places with divergent shapes. There is no single source of truth, and the definitions disagree on required vs optional fields, nesting structure, and which spec version they represent.
1. Registry —
apps/registry/src/types.ts:16(v0.2)manifest_version, noserverobject, nouser_config, noentry_pointserver_typeis flat at the top levelplatformsmap instead ofserver.mcp_config2. Registry validator —
apps/registry/src/services/manifest-validator.tsserver.type(v0.3) orserver_type(v0.2) — loose duck-typinginstanceof-style checksMCPBManifestinterface it type-guards3. SDK —
packages/sdk-typescript/src/cache.ts:37(v0.3, Zod)descriptionis required here, optional in all other definitionsmanifest_version,user_config, nestedserver.mcp_configpackages/schemas4. Web app —
apps/web/src/lib/manifest.ts:40(v0.3-ish, TypeScript)serveranddescriptionare optional (SDK requires both)mcp_configandargsare optional insideManifestServer(SDK requires them)5. CLI —
packages/cli/src/commands/packages/run.ts:50(v0.3, local)Divergence summary
manifest_versiondescriptionserver(nested)server_type(flat)user_configentry_pointmcp_configauthortools/prompts/resourcesplatformsProposed fix
McpbManifestSchema(Zod) inpackages/schemas/src/manifest.ts— single source of truth for the v0.3 specMcpbManifesttype frompackages/schemas— all consumers import from herecache.ts— delete local schema, import from@nimblebrain/mpak-schemasmanifest.ts— delete local interfaces, import from@nimblebrain/mpak-schemastypes.ts— either migrate to v0.3 or keep v0.2 asMCPBManifestV2alongside v0.3.safeParse()from the shared schema (or keep imperative for backward compat with v0.2 uploads)Related