CLI for MCP bundles and Agent Skills.
This is a standalone CLI that uses only the public v1 API. It has no dependencies on the server or client packages and generates its TypeScript types from the server's OpenAPI spec.
| File | Purpose |
|---|---|
src/program.ts |
Commander program setup with all commands |
src/lib/api/registry-client.ts |
API client for bundle endpoints |
src/lib/api/skills-client.ts |
API client for skill endpoints |
src/lib/api/schema.d.ts |
Generated types from OpenAPI spec |
src/commands/packages/*.ts |
Bundle commands (search, show, pull, run) |
src/commands/skills/*.ts |
Skill commands (validate, pack, search, show, pull, install, list) |
src/commands/config.ts |
Config commands (set, get, list, clear) |
src/schemas/generated/skill.ts |
Skill validation schemas (Zod) |
src/utils/config-manager.ts |
Config file handling (~/.mpak/config.json) |
mpak search <query> # Unified search (bundles + skills)
mpak bundle <command> # MCP bundle operations
mpak skill <command> # Agent skill operations
mpak config <command> # Configuration management
Types are generated from the server's OpenAPI spec using openapi-typescript:
# Requires server running locally on port 3200
npm run generate:typesThis generates src/lib/api/schema.d.ts from http://localhost:3200/documentation/json.
The registry-client.ts uses helper types to extract response types:
import type { paths } from './schema.js';
type ResponseOf<T> = T extends { responses: { 200: { content: { 'application/json': infer R } } } } ? R : never;
export type BundleSearchResponse = ResponseOf<paths['/v1/bundles/search']['get']>;
export type Bundle = BundleSearchResponse['bundles'][number];| Endpoint | Description |
|---|---|
GET /v1/bundles/search |
Search bundles by query, type, sort |
GET /v1/bundles/@{scope}/{package} |
Get bundle details (metadata, readme) |
GET /v1/bundles/@{scope}/{package}/versions |
List versions with platform availability |
GET /v1/bundles/@{scope}/{package}/versions/{version}/download |
Get download URL for specific version/platform |
| Endpoint | Description |
|---|---|
GET /v1/skills/search |
Search skills by query, tags, category |
GET /v1/skills/@{scope}/{name} |
Get skill details |
GET /v1/skills/@{scope}/{name}/download |
Get download URL for latest version |
GET /v1/skills/@{scope}/{name}/versions/{version}/download |
Get download URL for specific version |
POST /v1/skills/announce |
Announce skill version (OIDC auth) |
Download endpoints accept os and arch query parameters:
os: darwin, linux, win32, anyarch: x64, arm64, any
The server returns the best matching artifact using this priority:
- Exact match (requested os + arch)
- OS match with
anyarch anyOS with exact arch- Universal (
any+any)
npm install
npm run buildThe CLI defaults to https://api.mpak.dev. For local development:
# Start the server (from ../mpak/server)
cd ../mpak/server && npm run dev
# Run CLI commands with local registry
MPAK_REGISTRY_URL=http://localhost:3200 npm run dev -- bundle search echo
MPAK_REGISTRY_URL=http://localhost:3200 node dist/index.js skill search strategynpm run build
npm run typecheck
npm run test:allPrereleases (beta):
npm version 0.0.1-beta.X
npm run build
npm publish --tag beta --otp=<code>
git push && git push --tagsStable releases:
npm version X.X.X
npm run build
npm publish --otp=<code>
git push && git push --tags| Command | Description |
|---|---|
mpak search <query> |
Search bundles and skills |
mpak search <query> --type bundle |
Search bundles only |
mpak search <query> --type skill |
Search skills only |
| Command | Description |
|---|---|
mpak run <package> |
Run an MCP server (alias for bundle run) |
This is the recommended way to integrate with Claude Code:
claude mcp add --transport stdio echo -- mpak run @nimblebraininc/echo| Command | Description |
|---|---|
mpak bundle search <query> |
Search public bundles |
mpak bundle show <package> |
Show bundle details with platforms |
mpak bundle pull <package> |
Download a bundle |
mpak bundle run <package> |
Run an MCP server (pulls, caches, executes) |
| Command | Description |
|---|---|
mpak skill validate <path> |
Validate skill directory against Agent Skills spec |
mpak skill pack <path> |
Create a .skill bundle |
mpak skill search <query> |
Search skills in registry |
mpak skill show <name> |
Show skill details |
mpak skill pull <name> |
Download a .skill bundle |
mpak skill install <name> |
Install to ~/.claude/skills/ |
mpak skill list |
List installed skills |
| Command | Description |
|---|---|
mpak config set <pkg> <k=v...> |
Store config values for a package |
mpak config get <pkg> |
Show stored config (values masked) |
mpak config list |
List packages with stored config |
mpak config clear <pkg> [key] |
Clear stored config |
Packages can declare user_config in their manifest for values like API keys:
{
"user_config": {
"api_key": {
"type": "string",
"title": "API Token",
"sensitive": true,
"required": false
}
},
"server": {
"mcp_config": {
"env": {
"API_TOKEN": "${user_config.api_key}"
}
}
}
}When mpak bundle run executes, it substitutes ${user_config.*} placeholders with actual values.
Use mpak config set with keys matching the manifest's user_config field names (not the env var names):
# Key is "api_key" (from manifest.user_config.api_key), NOT "IPINFO_API_TOKEN"
mpak config set @nimblebraininc/ipinfo api_key=your_token
# Run uses stored config automatically
mpak bundle run @nimblebraininc/ipinfo
# View stored config (values masked)
mpak config get @nimblebraininc/ipinfoSet the actual environment variable directly in your Claude Desktop config:
{
"mcpServers": {
"ipinfo": {
"command": "mpak",
"args": ["bundle", "run", "@nimblebraininc/ipinfo"],
"env": {
"IPINFO_API_TOKEN": "your_token"
}
}
}
}This bypasses user_config substitution entirely since the env var is already set.
- Process environment (highest): Env vars set by parent (e.g., Claude Desktop config)
- Stored config:
~/.mpak/config.json(set viampak config set) - Default value: From manifest's
user_config.*.default - Interactive prompt: If TTY and value is required
Claude Desktop env vars always take priority over mpak config values.
The mpak config set key must match the user_config field name in the manifest:
manifest.user_config.api_key → mpak config set ... api_key=xxx → env IPINFO_API_TOKEN
^^^^^^^ ^^^^^^^
Field name = config key (NOT the env var name)
- Standalone: No shared dependencies with server/client. Types generated from OpenAPI.
- Public API only: Uses v1 API. Publishing requires OIDC via GitHub Actions.
- Platform detection: Auto-detects OS/arch, allows explicit override for cross-platform downloads.
- Config file: Stores registry URL in
~/.mpak/config.json, overridable viaMPAK_REGISTRY_URL. - Skill schemas: Uses Zod schemas in
src/schemas/generated/skill.tsfor validation.
- No dotenv: Removed due to v17 banner output breaking Claude Desktop MCP integration
- Type generation: Requires server running locally (
npm run generate:typeshits localhost:3200) - Schema changes: May introduce breaking type changes; always run full verification after regenerating
- Env merge order: Use
{ ...substitutedEnv, ...process.env }so parent env vars (Claude Desktop) take priority over manifest substitutions - Skill endpoints: Currently implemented in server code but may not be deployed to production yet