| layout | title | nav_order | parent |
|---|---|---|---|
default |
Chapter 5: CLI Workflows: Init, Validate, and Pack |
5 |
MCPB Tutorial |
Welcome to Chapter 5: CLI Workflows: Init, Validate, and Pack. In this part of MCPB Tutorial: Packaging and Distributing Local MCP Servers as Bundles, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
This chapter standardizes practical CLI workflows for bundle creation.
- use
mcpb initto bootstrap valid manifests quickly - validate manifests before packaging and distribution
- pack deterministic
.mcpbarchives with appropriate exclusions - integrate
.mcpbignoreinto repeatable build pipelines
mcpb initto scaffold manifestmcpb validateagainst schemamcpb packfor distributable archivemcpb infofor metadata inspection
You now have a repeatable packaging workflow for MCPB bundle production.
Next: Chapter 6: Signing, Verification, and Trust Controls
The buildManifest function in src/cli/init.ts handles a key part of this chapter's functionality:
}
export function buildManifest(
basicInfo: {
name: string;
displayName: string;
version: string;
description: string;
authorName: string;
},
longDescription: string | undefined,
authorInfo: {
authorEmail: string;
authorUrl: string;
},
urls: {
homepage: string;
documentation: string;
support: string;
},
visualAssets: {
icon: string;
icons: Array<{
src: string;
size: string;
theme?: string;
}>;
screenshots: string[];
},
serverConfig: {
serverType: "node" | "python" | "binary";
entryPoint: string;This function is important because it defines how MCPB Tutorial: Packaging and Distributing Local MCP Servers as Bundles implements the patterns covered in this chapter.
The printNextSteps function in src/cli/init.ts handles a key part of this chapter's functionality:
}
export function printNextSteps() {
console.log("\nNext steps:");
console.log(
`1. Ensure all your production dependencies are in this directory`,
);
console.log(`2. Run 'mcpb pack' to create your .mcpb file`);
}
export async function initExtension(
targetPath: string = process.cwd(),
nonInteractive = false,
manifestVersion?: string,
): Promise<boolean> {
const resolvedPath = resolve(targetPath);
const manifestPath = join(resolvedPath, "manifest.json");
// Validate manifest version if provided
if (manifestVersion && !(manifestVersion in MANIFEST_SCHEMAS)) {
console.error(
`ERROR: Invalid manifest version "${manifestVersion}". Supported versions: ${Object.keys(MANIFEST_SCHEMAS).join(", ")}`,
);
return false;
}
const effectiveManifestVersion = (manifestVersion ||
DEFAULT_MANIFEST_VERSION) as keyof typeof MANIFEST_SCHEMAS;
if (existsSync(manifestPath)) {
if (nonInteractive) {
console.log(
"manifest.json already exists. Use --force to overwrite in non-interactive mode.",This function is important because it defines how MCPB Tutorial: Packaging and Distributing Local MCP Servers as Bundles implements the patterns covered in this chapter.
The initExtension function in src/cli/init.ts handles a key part of this chapter's functionality:
}
export async function initExtension(
targetPath: string = process.cwd(),
nonInteractive = false,
manifestVersion?: string,
): Promise<boolean> {
const resolvedPath = resolve(targetPath);
const manifestPath = join(resolvedPath, "manifest.json");
// Validate manifest version if provided
if (manifestVersion && !(manifestVersion in MANIFEST_SCHEMAS)) {
console.error(
`ERROR: Invalid manifest version "${manifestVersion}". Supported versions: ${Object.keys(MANIFEST_SCHEMAS).join(", ")}`,
);
return false;
}
const effectiveManifestVersion = (manifestVersion ||
DEFAULT_MANIFEST_VERSION) as keyof typeof MANIFEST_SCHEMAS;
if (existsSync(manifestPath)) {
if (nonInteractive) {
console.log(
"manifest.json already exists. Use --force to overwrite in non-interactive mode.",
);
return false;
}
const overwrite = await confirm({
message: "manifest.json already exists. Overwrite?",
default: false,
});
if (!overwrite) {This function is important because it defines how MCPB Tutorial: Packaging and Distributing Local MCP Servers as Bundles implements the patterns covered in this chapter.
The PackageJson interface in src/cli/init.ts handles a key part of this chapter's functionality:
import type { McpbManifestAny } from "../types.js";
interface PackageJson {
name?: string;
version?: string;
description?: string;
main?: string;
author?: string | { name?: string; email?: string; url?: string };
repository?: string | { type?: string; url?: string };
license?: string;
}
export function readPackageJson(dirPath: string): PackageJson {
const packageJsonPath = join(dirPath, "package.json");
if (existsSync(packageJsonPath)) {
try {
return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
} catch (e) {
// Ignore package.json parsing errors
}
}
return {};
}
export function getDefaultAuthorName(packageData: PackageJson): string {
if (typeof packageData.author === "string") {
return packageData.author;
}
return packageData.author?.name || "";
}
export function getDefaultAuthorEmail(packageData: PackageJson): string {This interface is important because it defines how MCPB Tutorial: Packaging and Distributing Local MCP Servers as Bundles implements the patterns covered in this chapter.
flowchart TD
A[buildManifest]
B[printNextSteps]
C[initExtension]
D[PackageJson]
E[signMcpbFile]
A --> B
B --> C
C --> D
D --> E