@nimblebrain/mpak 0.0.1-beta.1 → 0.0.1-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(node dist/index.js:*)",
5
+ "Bash(npm test:*)",
6
+ "Bash(npm run build:*)",
7
+ "Bash(npm run test:all:*)",
8
+ "Bash(git add:*)",
9
+ "Bash(git commit:*)",
10
+ "Bash(npm version:*)",
11
+ "Bash(npm publish:*)",
12
+ "Bash(git push)",
13
+ "Bash(git tag:*)",
14
+ "Bash(git push:*)"
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,27 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: '20'
19
+ cache: 'npm'
20
+
21
+ - run: npm ci
22
+
23
+ - run: npm run build
24
+
25
+ - run: npm run typecheck
26
+
27
+ - run: npm run test:all
package/CLAUDE.md CHANGED
@@ -16,6 +16,7 @@ This is a standalone CLI that uses only the public v1 API. It has no dependencie
16
16
  | `src/commands/packages/search.ts` | Search command implementation |
17
17
  | `src/commands/packages/show.ts` | Show/info command implementation |
18
18
  | `src/commands/packages/pull.ts` | Pull/install command implementation |
19
+ | `src/commands/packages/run.ts` | Run command implementation (caching, extraction, execution) |
19
20
  | `src/utils/config-manager.ts` | Config file handling (~/.mpak/config.json) |
20
21
 
21
22
  ### Type Generation
@@ -102,6 +103,7 @@ npm run typecheck
102
103
  | `info <package>` | Alias for show |
103
104
  | `pull <package>` | Download a bundle |
104
105
  | `install <package>` | Alias for pull |
106
+ | `run <package>` | Run an MCP server (pulls, caches, executes) |
105
107
 
106
108
  ## Design Decisions
107
109
 
package/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # mpak CLI
2
2
 
3
+ [![CI](https://github.com/NimbleBrainInc/mpak-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/NimbleBrainInc/mpak-cli/actions/workflows/ci.yml)
4
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+ [![npm](https://img.shields.io/npm/v/@nimblebrain/mpak)](https://www.npmjs.com/package/@nimblebrain/mpak)
6
+ [![node](https://img.shields.io/node/v/@nimblebrain/mpak)](https://nodejs.org)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+ [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://www.nimblebrain.ai/discord?utm_source=github&utm_medium=readme&utm_campaign=mpak-cli&utm_content=discord-badge)
9
+
3
10
  CLI for discovering and downloading MCPB bundles from the mpak registry.
4
11
 
5
12
  ## Installation
@@ -31,6 +38,7 @@ mpak pull @owner/my-server@1.0.0 # specific version
31
38
  | `info <package>` | Alias for show |
32
39
  | `pull <package>` | Download a bundle |
33
40
  | `install <package>` | Alias for pull |
41
+ | `run <package>` | Run an MCP server from the registry |
34
42
 
35
43
  ### search
36
44
 
@@ -92,6 +100,39 @@ Options:
92
100
  - `--arch <arch>` - Target architecture: x64, arm64
93
101
  - `--json` - Output download info as JSON (doesn't download)
94
102
 
103
+ ### run
104
+
105
+ Run an MCP server directly from the registry. Bundles are cached locally for fast subsequent runs.
106
+
107
+ ```bash
108
+ # Run latest version
109
+ mpak run @nimblebraininc/echo
110
+
111
+ # Run specific version
112
+ mpak run @nimblebraininc/echo@1.0.0
113
+
114
+ # Force re-download (update cache)
115
+ mpak run @nimblebraininc/echo --update
116
+ ```
117
+
118
+ Options:
119
+ - `--update` - Force re-download even if cached
120
+
121
+ **Claude Desktop Integration:**
122
+
123
+ ```json
124
+ {
125
+ "mcpServers": {
126
+ "echo": {
127
+ "command": "mpak",
128
+ "args": ["run", "@nimblebraininc/echo"]
129
+ }
130
+ }
131
+ }
132
+ ```
133
+
134
+ Bundles are cached in `~/.mpak/cache/` and automatically extracted on first run.
135
+
95
136
  ## Configuration
96
137
 
97
138
  Configuration is stored in `~/.mpak/config.json`:
@@ -0,0 +1,8 @@
1
+ export interface RunOptions {
2
+ update?: boolean;
3
+ }
4
+ /**
5
+ * Run a package from the registry
6
+ */
7
+ export declare function handleRun(packageSpec: string, options?: RunOptions): Promise<void>;
8
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/packages/run.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAiID;;GAEG;AACH,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAyIf"}
@@ -0,0 +1,216 @@
1
+ import { spawn, spawnSync } from 'child_process';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join, dirname } from 'path';
5
+ import { RegistryClient } from '../../lib/api/registry-client.js';
6
+ /**
7
+ * Parse package specification into name and version
8
+ */
9
+ function parsePackageSpec(spec) {
10
+ const lastAtIndex = spec.lastIndexOf('@');
11
+ if (lastAtIndex <= 0) {
12
+ return { name: spec };
13
+ }
14
+ const name = spec.substring(0, lastAtIndex);
15
+ const version = spec.substring(lastAtIndex + 1);
16
+ if (!name.startsWith('@')) {
17
+ return { name: spec };
18
+ }
19
+ return { name, version };
20
+ }
21
+ /**
22
+ * Get cache directory for a package
23
+ */
24
+ function getCacheDir(packageName) {
25
+ const cacheBase = join(homedir(), '.mpak', 'cache');
26
+ // @scope/name -> scope/name
27
+ const safeName = packageName.replace('@', '').replace('/', '-');
28
+ return join(cacheBase, safeName);
29
+ }
30
+ /**
31
+ * Read cache metadata
32
+ */
33
+ function getCacheMetadata(cacheDir) {
34
+ const metaPath = join(cacheDir, '.mpak-meta.json');
35
+ if (!existsSync(metaPath)) {
36
+ return null;
37
+ }
38
+ try {
39
+ return JSON.parse(readFileSync(metaPath, 'utf8'));
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /**
46
+ * Write cache metadata
47
+ */
48
+ function writeCacheMetadata(cacheDir, metadata) {
49
+ const metaPath = join(cacheDir, '.mpak-meta.json');
50
+ writeFileSync(metaPath, JSON.stringify(metadata, null, 2));
51
+ }
52
+ /**
53
+ * Extract ZIP file to directory (simple implementation without external deps)
54
+ */
55
+ async function extractZip(zipPath, destDir) {
56
+ // Use native unzip command (available on macOS, Linux, and Windows with WSL)
57
+ const { execSync } = await import('child_process');
58
+ // Ensure destination exists
59
+ mkdirSync(destDir, { recursive: true });
60
+ try {
61
+ execSync(`unzip -o -q "${zipPath}" -d "${destDir}"`, { stdio: 'pipe' });
62
+ }
63
+ catch (error) {
64
+ throw new Error(`Failed to extract bundle: ${error.message}`);
65
+ }
66
+ }
67
+ /**
68
+ * Read manifest from extracted bundle
69
+ */
70
+ function readManifest(cacheDir) {
71
+ const manifestPath = join(cacheDir, 'manifest.json');
72
+ if (!existsSync(manifestPath)) {
73
+ throw new Error(`Manifest not found in bundle: ${manifestPath}`);
74
+ }
75
+ return JSON.parse(readFileSync(manifestPath, 'utf8'));
76
+ }
77
+ /**
78
+ * Resolve placeholders in args (e.g., ${__dirname})
79
+ */
80
+ function resolveArgs(args, cacheDir) {
81
+ return args.map(arg => arg.replace(/\$\{__dirname\}/g, cacheDir));
82
+ }
83
+ /**
84
+ * Find Python executable (tries python3 first, then python)
85
+ */
86
+ function findPythonCommand() {
87
+ // Try python3 first (preferred on macOS/Linux)
88
+ const result = spawnSync('python3', ['--version'], { stdio: 'pipe' });
89
+ if (result.status === 0) {
90
+ return 'python3';
91
+ }
92
+ // Fall back to python
93
+ return 'python';
94
+ }
95
+ /**
96
+ * Run a package from the registry
97
+ */
98
+ export async function handleRun(packageSpec, options = {}) {
99
+ const { name, version: requestedVersion } = parsePackageSpec(packageSpec);
100
+ const client = new RegistryClient();
101
+ const platform = RegistryClient.detectPlatform();
102
+ const cacheDir = getCacheDir(name);
103
+ let needsPull = true;
104
+ let cachedMeta = getCacheMetadata(cacheDir);
105
+ // Check if we have a cached version
106
+ if (cachedMeta && !options.update) {
107
+ if (requestedVersion) {
108
+ // Specific version requested - check if cached version matches
109
+ needsPull = cachedMeta.version !== requestedVersion;
110
+ }
111
+ else {
112
+ // Latest requested - use cache (user can --update to refresh)
113
+ needsPull = false;
114
+ }
115
+ }
116
+ if (needsPull) {
117
+ // Fetch download info
118
+ const downloadInfo = await client.getDownloadInfo(name, requestedVersion, platform);
119
+ const bundle = downloadInfo.bundle;
120
+ // Check if cached version is already the latest
121
+ if (cachedMeta && cachedMeta.version === bundle.version && !options.update) {
122
+ needsPull = false;
123
+ }
124
+ if (needsPull) {
125
+ // Download to temp file
126
+ const tempPath = join(homedir(), '.mpak', 'tmp', `${Date.now()}.mcpb`);
127
+ mkdirSync(dirname(tempPath), { recursive: true });
128
+ process.stderr.write(`=> Pulling ${name}@${bundle.version}...\n`);
129
+ await client.downloadBundle(downloadInfo.url, tempPath);
130
+ // Clear old cache and extract
131
+ const { rmSync } = await import('fs');
132
+ if (existsSync(cacheDir)) {
133
+ rmSync(cacheDir, { recursive: true, force: true });
134
+ }
135
+ mkdirSync(cacheDir, { recursive: true });
136
+ await extractZip(tempPath, cacheDir);
137
+ // Write metadata
138
+ writeCacheMetadata(cacheDir, {
139
+ version: bundle.version,
140
+ pulledAt: new Date().toISOString(),
141
+ platform: bundle.platform,
142
+ });
143
+ // Cleanup temp file
144
+ rmSync(tempPath, { force: true });
145
+ process.stderr.write(`=> Cached ${name}@${bundle.version}\n`);
146
+ }
147
+ }
148
+ // Read manifest and execute
149
+ const manifest = readManifest(cacheDir);
150
+ const { type, entry_point, mcp_config } = manifest.server;
151
+ let command;
152
+ let args;
153
+ let env = { ...process.env, ...mcp_config.env };
154
+ switch (type) {
155
+ case 'binary': {
156
+ // For binary, the entry_point is the executable path relative to bundle
157
+ command = join(cacheDir, entry_point);
158
+ args = resolveArgs(mcp_config.args || [], cacheDir);
159
+ // Ensure binary is executable
160
+ try {
161
+ chmodSync(command, 0o755);
162
+ }
163
+ catch {
164
+ // Ignore chmod errors on Windows
165
+ }
166
+ break;
167
+ }
168
+ case 'node': {
169
+ command = mcp_config.command || 'node';
170
+ // Use mcp_config.args directly if provided, otherwise fall back to entry_point
171
+ if (mcp_config.args && mcp_config.args.length > 0) {
172
+ args = resolveArgs(mcp_config.args, cacheDir);
173
+ }
174
+ else {
175
+ args = [join(cacheDir, entry_point)];
176
+ }
177
+ break;
178
+ }
179
+ case 'python': {
180
+ // Use manifest command if specified, otherwise auto-detect python
181
+ command = mcp_config.command === 'python' ? findPythonCommand() : (mcp_config.command || findPythonCommand());
182
+ // Use mcp_config.args directly if provided, otherwise fall back to entry_point
183
+ if (mcp_config.args && mcp_config.args.length > 0) {
184
+ args = resolveArgs(mcp_config.args, cacheDir);
185
+ }
186
+ else {
187
+ args = [join(cacheDir, entry_point)];
188
+ }
189
+ // Set PYTHONPATH to deps/ directory for dependency resolution
190
+ const depsDir = join(cacheDir, 'deps');
191
+ const existingPythonPath = process.env.PYTHONPATH;
192
+ env.PYTHONPATH = existingPythonPath ? `${depsDir}:${existingPythonPath}` : depsDir;
193
+ break;
194
+ }
195
+ default:
196
+ throw new Error(`Unsupported server type: ${type}`);
197
+ }
198
+ // Spawn with stdio passthrough for MCP
199
+ const child = spawn(command, args, {
200
+ stdio: ['inherit', 'inherit', 'inherit'],
201
+ env,
202
+ cwd: cacheDir,
203
+ });
204
+ // Forward signals
205
+ process.on('SIGINT', () => child.kill('SIGINT'));
206
+ process.on('SIGTERM', () => child.kill('SIGTERM'));
207
+ // Wait for exit
208
+ child.on('exit', (code) => {
209
+ process.exit(code ?? 0);
210
+ });
211
+ child.on('error', (error) => {
212
+ process.stderr.write(`=> Failed to start server: ${error.message}\n`);
213
+ process.exit(1);
214
+ });
215
+ }
216
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/packages/run.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/commands/packages/show.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CA6Hf"}
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/commands/packages/show.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAmHf"}
@@ -52,18 +52,6 @@ export async function handleShow(packageName, options = {}) {
52
52
  console.log(` Downloads: ${bundle.downloads.toLocaleString()}`);
53
53
  console.log(` Published: ${new Date(bundle.published_at).toLocaleDateString()}`);
54
54
  console.log();
55
- // GitHub info
56
- if (bundle.github) {
57
- console.log('GitHub:');
58
- console.log(` Repository: ${bundle.github.repo}`);
59
- if (bundle.github.stars != null)
60
- console.log(` Stars: ${bundle.github.stars}`);
61
- if (bundle.github.forks != null)
62
- console.log(` Forks: ${bundle.github.forks}`);
63
- if (bundle.github.watchers != null)
64
- console.log(` Watchers: ${bundle.github.watchers}`);
65
- console.log();
66
- }
67
55
  // Tools
68
56
  if (bundle.tools && bundle.tools.length > 0) {
69
57
  console.log(`Tools (${bundle.tools.length}):`);
@@ -1 +1 @@
1
- {"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/commands/packages/show.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/commands/packages/show.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,9 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { config } from 'dotenv';
3
2
  import { createProgram } from './program.js';
4
3
  import { handleError } from './utils/errors.js';
5
- // Load environment variables from .env file
6
- config();
7
4
  async function main() {
8
5
  const program = createProgram();
9
6
  await program.parseAsync(process.argv);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,4CAA4C;AAC5C,MAAM,EAAE,CAAC;AAET,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAgEvC"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAyEvC"}
package/dist/program.js CHANGED
@@ -3,6 +3,7 @@ import { getVersion } from './utils/version.js';
3
3
  import { handleSearch } from './commands/packages/search.js';
4
4
  import { handleShow } from './commands/packages/show.js';
5
5
  import { handlePull } from './commands/packages/pull.js';
6
+ import { handleRun } from './commands/packages/run.js';
6
7
  /**
7
8
  * Creates and configures the CLI program
8
9
  *
@@ -64,6 +65,14 @@ export function createProgram() {
64
65
  .action(async (packageSpec, options) => {
65
66
  await handlePull(packageSpec, options);
66
67
  });
68
+ // Run command
69
+ program
70
+ .command('run <package>')
71
+ .description('Run an MCP server from the registry (e.g., @scope/name or @scope/name@1.0.0)')
72
+ .option('--update', 'Force re-download even if cached')
73
+ .action(async (packageSpec, options) => {
74
+ await handleRun(packageSpec, options);
75
+ });
67
76
  return program;
68
77
  }
69
78
  //# sourceMappingURL=program.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@nimblebrain/mpak",
3
- "version": "0.0.1-beta.1",
3
+ "version": "0.0.1-beta.3",
4
4
  "description": "CLI for downloading MCPB bundles from the mpak registry",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "mpak": "./dist/index.js"
8
+ "mpak": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsc",
@@ -15,10 +15,14 @@
15
15
  "lint:fix": "eslint src --fix",
16
16
  "prepublishOnly": "npm run build",
17
17
  "start": "node dist/index.js",
18
- "test": "vitest",
18
+ "test": "vitest --run src",
19
+ "test:unit": "vitest --run src",
20
+ "test:integration": "vitest --run test/integration",
21
+ "test:all": "vitest --run",
22
+ "test:watch": "vitest",
19
23
  "test:ui": "vitest --ui",
20
24
  "test:coverage": "vitest --coverage",
21
- "typecheck": "tsc --noEmit"
25
+ "typecheck": "tsc -p tsconfig.check.json"
22
26
  },
23
27
  "keywords": [
24
28
  "mcp",
@@ -29,9 +33,11 @@
29
33
  ],
30
34
  "author": "NimbleBrain Inc",
31
35
  "license": "Apache-2.0",
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
32
39
  "dependencies": {
33
- "commander": "^14.0.2",
34
- "dotenv": "^17.2.3"
40
+ "commander": "^14.0.2"
35
41
  },
36
42
  "devDependencies": {
37
43
  "@types/node": "^25.0.3",
@@ -45,4 +51,4 @@
45
51
  "access": "public",
46
52
  "registry": "https://registry.npmjs.org/"
47
53
  }
48
- }
54
+ }
@@ -0,0 +1,281 @@
1
+ import { spawn, spawnSync } from 'child_process';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join, dirname } from 'path';
5
+ import { RegistryClient } from '../../lib/api/registry-client.js';
6
+
7
+ export interface RunOptions {
8
+ update?: boolean;
9
+ }
10
+
11
+ interface McpConfig {
12
+ command: string;
13
+ args: string[];
14
+ env?: Record<string, string>;
15
+ }
16
+
17
+ interface McpbManifest {
18
+ manifest_version: string;
19
+ name: string;
20
+ version: string;
21
+ description: string;
22
+ server: {
23
+ type: 'node' | 'python' | 'binary';
24
+ entry_point: string;
25
+ mcp_config: McpConfig;
26
+ };
27
+ }
28
+
29
+ interface CacheMetadata {
30
+ version: string;
31
+ pulledAt: string;
32
+ platform: { os: string; arch: string };
33
+ }
34
+
35
+ /**
36
+ * Parse package specification into name and version
37
+ */
38
+ function parsePackageSpec(spec: string): { name: string; version?: string } {
39
+ const lastAtIndex = spec.lastIndexOf('@');
40
+
41
+ if (lastAtIndex <= 0) {
42
+ return { name: spec };
43
+ }
44
+
45
+ const name = spec.substring(0, lastAtIndex);
46
+ const version = spec.substring(lastAtIndex + 1);
47
+
48
+ if (!name.startsWith('@')) {
49
+ return { name: spec };
50
+ }
51
+
52
+ return { name, version };
53
+ }
54
+
55
+ /**
56
+ * Get cache directory for a package
57
+ */
58
+ function getCacheDir(packageName: string): string {
59
+ const cacheBase = join(homedir(), '.mpak', 'cache');
60
+ // @scope/name -> scope/name
61
+ const safeName = packageName.replace('@', '').replace('/', '-');
62
+ return join(cacheBase, safeName);
63
+ }
64
+
65
+ /**
66
+ * Read cache metadata
67
+ */
68
+ function getCacheMetadata(cacheDir: string): CacheMetadata | null {
69
+ const metaPath = join(cacheDir, '.mpak-meta.json');
70
+ if (!existsSync(metaPath)) {
71
+ return null;
72
+ }
73
+ try {
74
+ return JSON.parse(readFileSync(metaPath, 'utf8'));
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Write cache metadata
82
+ */
83
+ function writeCacheMetadata(cacheDir: string, metadata: CacheMetadata): void {
84
+ const metaPath = join(cacheDir, '.mpak-meta.json');
85
+ writeFileSync(metaPath, JSON.stringify(metadata, null, 2));
86
+ }
87
+
88
+ /**
89
+ * Extract ZIP file to directory (simple implementation without external deps)
90
+ */
91
+ async function extractZip(zipPath: string, destDir: string): Promise<void> {
92
+ // Use native unzip command (available on macOS, Linux, and Windows with WSL)
93
+ const { execSync } = await import('child_process');
94
+
95
+ // Ensure destination exists
96
+ mkdirSync(destDir, { recursive: true });
97
+
98
+ try {
99
+ execSync(`unzip -o -q "${zipPath}" -d "${destDir}"`, { stdio: 'pipe' });
100
+ } catch (error: any) {
101
+ throw new Error(`Failed to extract bundle: ${error.message}`);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Read manifest from extracted bundle
107
+ */
108
+ function readManifest(cacheDir: string): McpbManifest {
109
+ const manifestPath = join(cacheDir, 'manifest.json');
110
+ if (!existsSync(manifestPath)) {
111
+ throw new Error(`Manifest not found in bundle: ${manifestPath}`);
112
+ }
113
+ return JSON.parse(readFileSync(manifestPath, 'utf8'));
114
+ }
115
+
116
+ /**
117
+ * Resolve placeholders in args (e.g., ${__dirname})
118
+ */
119
+ function resolveArgs(args: string[], cacheDir: string): string[] {
120
+ return args.map(arg =>
121
+ arg.replace(/\$\{__dirname\}/g, cacheDir)
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Find Python executable (tries python3 first, then python)
127
+ */
128
+ function findPythonCommand(): string {
129
+ // Try python3 first (preferred on macOS/Linux)
130
+ const result = spawnSync('python3', ['--version'], { stdio: 'pipe' });
131
+ if (result.status === 0) {
132
+ return 'python3';
133
+ }
134
+ // Fall back to python
135
+ return 'python';
136
+ }
137
+
138
+ /**
139
+ * Run a package from the registry
140
+ */
141
+ export async function handleRun(
142
+ packageSpec: string,
143
+ options: RunOptions = {}
144
+ ): Promise<void> {
145
+ const { name, version: requestedVersion } = parsePackageSpec(packageSpec);
146
+ const client = new RegistryClient();
147
+ const platform = RegistryClient.detectPlatform();
148
+ const cacheDir = getCacheDir(name);
149
+
150
+ let needsPull = true;
151
+ let cachedMeta = getCacheMetadata(cacheDir);
152
+
153
+ // Check if we have a cached version
154
+ if (cachedMeta && !options.update) {
155
+ if (requestedVersion) {
156
+ // Specific version requested - check if cached version matches
157
+ needsPull = cachedMeta.version !== requestedVersion;
158
+ } else {
159
+ // Latest requested - use cache (user can --update to refresh)
160
+ needsPull = false;
161
+ }
162
+ }
163
+
164
+ if (needsPull) {
165
+ // Fetch download info
166
+ const downloadInfo = await client.getDownloadInfo(name, requestedVersion, platform);
167
+ const bundle = downloadInfo.bundle;
168
+
169
+ // Check if cached version is already the latest
170
+ if (cachedMeta && cachedMeta.version === bundle.version && !options.update) {
171
+ needsPull = false;
172
+ }
173
+
174
+ if (needsPull) {
175
+ // Download to temp file
176
+ const tempPath = join(homedir(), '.mpak', 'tmp', `${Date.now()}.mcpb`);
177
+ mkdirSync(dirname(tempPath), { recursive: true });
178
+
179
+ process.stderr.write(`=> Pulling ${name}@${bundle.version}...\n`);
180
+ await client.downloadBundle(downloadInfo.url, tempPath);
181
+
182
+ // Clear old cache and extract
183
+ const { rmSync } = await import('fs');
184
+ if (existsSync(cacheDir)) {
185
+ rmSync(cacheDir, { recursive: true, force: true });
186
+ }
187
+ mkdirSync(cacheDir, { recursive: true });
188
+
189
+ await extractZip(tempPath, cacheDir);
190
+
191
+ // Write metadata
192
+ writeCacheMetadata(cacheDir, {
193
+ version: bundle.version,
194
+ pulledAt: new Date().toISOString(),
195
+ platform: bundle.platform,
196
+ });
197
+
198
+ // Cleanup temp file
199
+ rmSync(tempPath, { force: true });
200
+
201
+ process.stderr.write(`=> Cached ${name}@${bundle.version}\n`);
202
+ }
203
+ }
204
+
205
+ // Read manifest and execute
206
+ const manifest = readManifest(cacheDir);
207
+ const { type, entry_point, mcp_config } = manifest.server;
208
+
209
+ let command: string;
210
+ let args: string[];
211
+ let env: Record<string, string | undefined> = { ...process.env, ...mcp_config.env };
212
+
213
+ switch (type) {
214
+ case 'binary': {
215
+ // For binary, the entry_point is the executable path relative to bundle
216
+ command = join(cacheDir, entry_point);
217
+ args = resolveArgs(mcp_config.args || [], cacheDir);
218
+
219
+ // Ensure binary is executable
220
+ try {
221
+ chmodSync(command, 0o755);
222
+ } catch {
223
+ // Ignore chmod errors on Windows
224
+ }
225
+ break;
226
+ }
227
+
228
+ case 'node': {
229
+ command = mcp_config.command || 'node';
230
+ // Use mcp_config.args directly if provided, otherwise fall back to entry_point
231
+ if (mcp_config.args && mcp_config.args.length > 0) {
232
+ args = resolveArgs(mcp_config.args, cacheDir);
233
+ } else {
234
+ args = [join(cacheDir, entry_point)];
235
+ }
236
+ break;
237
+ }
238
+
239
+ case 'python': {
240
+ // Use manifest command if specified, otherwise auto-detect python
241
+ command = mcp_config.command === 'python' ? findPythonCommand() : (mcp_config.command || findPythonCommand());
242
+
243
+ // Use mcp_config.args directly if provided, otherwise fall back to entry_point
244
+ if (mcp_config.args && mcp_config.args.length > 0) {
245
+ args = resolveArgs(mcp_config.args, cacheDir);
246
+ } else {
247
+ args = [join(cacheDir, entry_point)];
248
+ }
249
+
250
+ // Set PYTHONPATH to deps/ directory for dependency resolution
251
+ const depsDir = join(cacheDir, 'deps');
252
+ const existingPythonPath = process.env.PYTHONPATH;
253
+ env.PYTHONPATH = existingPythonPath ? `${depsDir}:${existingPythonPath}` : depsDir;
254
+ break;
255
+ }
256
+
257
+ default:
258
+ throw new Error(`Unsupported server type: ${type}`);
259
+ }
260
+
261
+ // Spawn with stdio passthrough for MCP
262
+ const child = spawn(command, args, {
263
+ stdio: ['inherit', 'inherit', 'inherit'],
264
+ env,
265
+ cwd: cacheDir,
266
+ });
267
+
268
+ // Forward signals
269
+ process.on('SIGINT', () => child.kill('SIGINT'));
270
+ process.on('SIGTERM', () => child.kill('SIGTERM'));
271
+
272
+ // Wait for exit
273
+ child.on('exit', (code) => {
274
+ process.exit(code ?? 0);
275
+ });
276
+
277
+ child.on('error', (error) => {
278
+ process.stderr.write(`=> Failed to start server: ${error.message}\n`);
279
+ process.exit(1);
280
+ });
281
+ }
@@ -65,19 +65,9 @@ export async function handleShow(
65
65
  // Stats
66
66
  console.log('Statistics:');
67
67
  console.log(` Downloads: ${bundle.downloads.toLocaleString()}`);
68
- console.log(` Published: ${new Date(bundle.published_at).toLocaleDateString()}`);
68
+ console.log(` Published: ${new Date(bundle.published_at as string).toLocaleDateString()}`);
69
69
  console.log();
70
70
 
71
- // GitHub info
72
- if (bundle.github) {
73
- console.log('GitHub:');
74
- console.log(` Repository: ${bundle.github.repo}`);
75
- if (bundle.github.stars != null) console.log(` Stars: ${bundle.github.stars}`);
76
- if (bundle.github.forks != null) console.log(` Forks: ${bundle.github.forks}`);
77
- if (bundle.github.watchers != null) console.log(` Watchers: ${bundle.github.watchers}`);
78
- console.log();
79
- }
80
-
81
71
  // Tools
82
72
  if (bundle.tools && bundle.tools.length > 0) {
83
73
  console.log(`Tools (${bundle.tools.length}):`);
@@ -95,7 +85,7 @@ export async function handleShow(
95
85
  console.log(`Versions (${versionsInfo.versions.length}):`);
96
86
  const recentVersions = versionsInfo.versions.slice(0, 5);
97
87
  for (const version of recentVersions) {
98
- const date = new Date(version.published_at).toLocaleDateString();
88
+ const date = new Date(version.published_at as string).toLocaleDateString();
99
89
  const downloads = version.downloads.toLocaleString();
100
90
  const isLatest = version.version === versionsInfo.latest ? ' (latest)' : '';
101
91
  const provTag = version.provenance ? ' 🔒' : '';
package/src/index.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { config } from 'dotenv';
4
3
  import { createProgram } from './program.js';
5
4
  import { handleError } from './utils/errors.js';
6
5
 
7
- // Load environment variables from .env file
8
- config();
9
-
10
6
  async function main() {
11
7
  const program = createProgram();
12
8
  await program.parseAsync(process.argv);
@@ -51,8 +51,7 @@ export interface paths {
51
51
  description?: string;
52
52
  }[];
53
53
  downloads: number;
54
- /** Format: date-time */
55
- published_at: string;
54
+ published_at: string | unknown;
56
55
  verified: boolean;
57
56
  provenance?: {
58
57
  schema_version: string;
@@ -121,27 +120,19 @@ export interface paths {
121
120
  description?: string;
122
121
  }[];
123
122
  downloads: number;
124
- /** Format: date-time */
125
- published_at: string;
123
+ published_at: string | unknown;
126
124
  verified: boolean;
127
- homepage?: string | null;
128
- license?: string | null;
129
- github?: {
130
- repo: string;
131
- stars?: number | null;
132
- forks?: number | null;
133
- watchers?: number | null;
134
- } | null;
135
125
  provenance?: {
136
126
  schema_version: string;
137
127
  provider: string;
138
128
  repository: string;
139
129
  sha: string;
140
130
  } | null;
131
+ homepage?: string | null;
132
+ license?: string | null;
141
133
  versions: {
142
134
  version: string;
143
- /** Format: date-time */
144
- published_at: string;
135
+ published_at: string | unknown;
145
136
  downloads: number;
146
137
  }[];
147
138
  };
@@ -188,15 +179,13 @@ export interface paths {
188
179
  mimeType: string;
189
180
  name: string;
190
181
  version: string;
191
- description?: string | null;
182
+ description: string | null;
192
183
  bundles: {
193
- mimeType: string;
184
+ mimeType: string | null;
194
185
  digest: string;
195
186
  size: number;
196
187
  platform: {
197
- /** @description Operating system (darwin, linux, win32, any) */
198
188
  os: string;
199
- /** @description Architecture (x64, arm64, any) */
200
189
  arch: string;
201
190
  };
202
191
  urls: string[];
@@ -250,15 +239,12 @@ export interface paths {
250
239
  version: string;
251
240
  artifacts_count: number;
252
241
  platforms: {
253
- /** @description Operating system (darwin, linux, win32, any) */
254
242
  os: string;
255
- /** @description Architecture (x64, arm64, any) */
256
243
  arch: string;
257
244
  }[];
258
- /** Format: date-time */
259
- published_at: string;
245
+ published_at: string | unknown;
260
246
  downloads: number;
261
- publish_method?: string | null;
247
+ publish_method: string | null;
262
248
  provenance?: {
263
249
  schema_version: string;
264
250
  provider: string;
@@ -309,14 +295,11 @@ export interface paths {
309
295
  "application/json": {
310
296
  name: string;
311
297
  version: string;
312
- /** Format: date-time */
313
- published_at: string;
298
+ published_at: string | unknown;
314
299
  downloads: number;
315
300
  artifacts: {
316
301
  platform: {
317
- /** @description Operating system (darwin, linux, win32, any) */
318
302
  os: string;
319
- /** @description Architecture (x64, arm64, any) */
320
303
  arch: string;
321
304
  };
322
305
  digest: string;
@@ -324,16 +307,19 @@ export interface paths {
324
307
  download_url: string;
325
308
  source_url?: string;
326
309
  }[];
327
- manifest?: {
310
+ manifest: {
328
311
  [key: string]: unknown;
329
312
  };
330
313
  release?: {
331
- tag?: string;
332
- url?: string;
333
- } | null;
334
- publish_method?: string | null;
335
- provenance?: {
336
- [key: string]: unknown;
314
+ tag: string | null;
315
+ url: string | null;
316
+ };
317
+ publish_method: string | null;
318
+ provenance: {
319
+ schema_version: string;
320
+ provider: string;
321
+ repository: string;
322
+ sha: string;
337
323
  } | null;
338
324
  };
339
325
  };
@@ -386,16 +372,13 @@ export interface paths {
386
372
  name: string;
387
373
  version: string;
388
374
  platform: {
389
- /** @description Operating system (darwin, linux, win32, any) */
390
375
  os: string;
391
- /** @description Architecture (x64, arm64, any) */
392
376
  arch: string;
393
377
  };
394
378
  sha256: string;
395
379
  size: number;
396
380
  };
397
- /** Format: date-time */
398
- expires_at: string;
381
+ expires_at?: string;
399
382
  };
400
383
  };
401
384
  };
@@ -425,7 +408,7 @@ export interface paths {
425
408
  };
426
409
  get?: never;
427
410
  put?: never;
428
- /** @description Announce a new bundle version from a GitHub release (OIDC only) */
411
+ /** @description Announce a single artifact for a bundle version from a GitHub release (OIDC only). Idempotent - can be called multiple times for different artifacts of the same version. */
429
412
  post: {
430
413
  parameters: {
431
414
  query?: never;
@@ -436,14 +419,21 @@ export interface paths {
436
419
  requestBody: {
437
420
  content: {
438
421
  "application/json": {
439
- /** @description Package name (@scope/name) */
440
422
  name: string;
441
- /** @description Semantic version */
442
423
  version: string;
443
- /** @description Bundle manifest */
444
- manifest: Record<string, never>;
445
- /** @description GitHub release tag (e.g., v0.1.0) */
424
+ manifest: {
425
+ [key: string]: unknown;
426
+ };
446
427
  release_tag: string;
428
+ /** @default false */
429
+ prerelease: boolean;
430
+ artifact: {
431
+ filename: string;
432
+ os: string;
433
+ arch: string;
434
+ sha256: string;
435
+ size: number;
436
+ };
447
437
  };
448
438
  };
449
439
  };
@@ -455,34 +445,16 @@ export interface paths {
455
445
  };
456
446
  content: {
457
447
  "application/json": {
458
- success: boolean;
459
- bundle: {
460
- name: string;
461
- version: string;
462
- artifacts_count: number;
463
- };
464
- release: {
465
- tag: string;
466
- url: string;
448
+ package: string;
449
+ version: string;
450
+ artifact: {
451
+ os: string;
452
+ arch: string;
453
+ filename: string;
467
454
  };
468
- artifacts: {
469
- platform: {
470
- /** @description Operating system (darwin, linux, win32, any) */
471
- os: string;
472
- /** @description Architecture (x64, arm64, any) */
473
- arch: string;
474
- };
475
- digest: string;
476
- size: number;
477
- url: string;
478
- source_url: string;
479
- }[];
480
- provenance: {
481
- schema_version: string;
482
- provider: string;
483
- repository: string;
484
- sha: string;
485
- } | null;
455
+ total_artifacts: number;
456
+ /** @enum {string} */
457
+ status: "created" | "updated";
486
458
  };
487
459
  };
488
460
  };
package/src/program.ts CHANGED
@@ -3,6 +3,7 @@ import { getVersion } from './utils/version.js';
3
3
  import { handleSearch } from './commands/packages/search.js';
4
4
  import { handleShow } from './commands/packages/show.js';
5
5
  import { handlePull } from './commands/packages/pull.js';
6
+ import { handleRun } from './commands/packages/run.js';
6
7
 
7
8
  /**
8
9
  * Creates and configures the CLI program
@@ -72,5 +73,14 @@ export function createProgram(): Command {
72
73
  await handlePull(packageSpec, options);
73
74
  });
74
75
 
76
+ // Run command
77
+ program
78
+ .command('run <package>')
79
+ .description('Run an MCP server from the registry (e.g., @scope/name or @scope/name@1.0.0)')
80
+ .option('--update', 'Force re-download even if cached')
81
+ .action(async (packageSpec, options) => {
82
+ await handleRun(packageSpec, options);
83
+ });
84
+
75
85
  return program;
76
86
  }
@@ -0,0 +1,180 @@
1
+ import { describe, it, expect, afterAll } from 'vitest';
2
+ import { RegistryClient } from '../../src/lib/api/registry-client.js';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ /**
7
+ * Integration tests for the mpak registry client
8
+ *
9
+ * These tests hit the live api.mpak.dev registry using the @nimblebraininc/echo
10
+ * bundle as a known fixture. They verify the full flow from search to download.
11
+ *
12
+ * Run with: npm run test:integration
13
+ */
14
+ describe('RegistryClient Integration', () => {
15
+ const client = new RegistryClient();
16
+ const testBundle = '@nimblebraininc/echo';
17
+ const downloadedFiles: string[] = [];
18
+
19
+ afterAll(() => {
20
+ // Clean up any downloaded files
21
+ for (const file of downloadedFiles) {
22
+ if (fs.existsSync(file)) {
23
+ fs.unlinkSync(file);
24
+ }
25
+ }
26
+ });
27
+
28
+ describe('searchBundles', () => {
29
+ it('should find echo bundle when searching for "echo"', async () => {
30
+ const result = await client.searchBundles('echo');
31
+
32
+ expect(result.bundles).toBeDefined();
33
+ expect(result.bundles.length).toBeGreaterThan(0);
34
+
35
+ const echoBundle = result.bundles.find(b => b.name === testBundle);
36
+ expect(echoBundle).toBeDefined();
37
+ expect(echoBundle?.description).toContain('Echo');
38
+ });
39
+
40
+ it('should return empty results for nonsense query', async () => {
41
+ const result = await client.searchBundles('xyznonexistent12345');
42
+
43
+ expect(result.bundles).toBeDefined();
44
+ expect(result.bundles.length).toBe(0);
45
+ });
46
+
47
+ it('should respect limit parameter', async () => {
48
+ const result = await client.searchBundles('', { limit: 1 });
49
+
50
+ expect(result.bundles.length).toBeLessThanOrEqual(1);
51
+ });
52
+ });
53
+
54
+ describe('getBundle', () => {
55
+ it('should return bundle details for @nimblebraininc/echo', async () => {
56
+ const bundle = await client.getBundle(testBundle);
57
+
58
+ expect(bundle.name).toBe(testBundle);
59
+ expect(bundle.description).toBeDefined();
60
+ expect(bundle.server_type).toBe('python');
61
+ expect(bundle.author).toBeDefined();
62
+ expect(bundle.latest_version).toBeDefined();
63
+ });
64
+
65
+ it('should include provenance information', async () => {
66
+ const bundle = await client.getBundle(testBundle);
67
+
68
+ expect(bundle.provenance).toBeDefined();
69
+ expect(bundle.provenance?.provider).toBe('github_oidc');
70
+ expect(bundle.provenance?.repository).toContain('mcp-echo');
71
+ });
72
+
73
+ it('should throw error for non-existent bundle', async () => {
74
+ await expect(
75
+ client.getBundle('@nonexistent/bundle-xyz')
76
+ ).rejects.toThrow('Bundle not found');
77
+ });
78
+
79
+ it('should throw error for unscoped package name', async () => {
80
+ await expect(
81
+ client.getBundle('unscoped-name')
82
+ ).rejects.toThrow('Package name must be scoped');
83
+ });
84
+ });
85
+
86
+ describe('getVersions', () => {
87
+ it('should return version list with platforms', async () => {
88
+ const result = await client.getVersions(testBundle);
89
+
90
+ expect(result.versions).toBeDefined();
91
+ expect(result.versions.length).toBeGreaterThan(0);
92
+
93
+ const latestVersion = result.versions[0];
94
+ expect(latestVersion.version).toBeDefined();
95
+ expect(latestVersion.platforms).toBeDefined();
96
+ expect(latestVersion.platforms.length).toBeGreaterThan(0);
97
+ });
98
+
99
+ it('should include linux platforms for echo bundle', async () => {
100
+ const result = await client.getVersions(testBundle);
101
+
102
+ const latestVersion = result.versions[0];
103
+ const platforms = latestVersion.platforms.map(p => `${p.os}-${p.arch}`);
104
+
105
+ expect(platforms).toContain('linux-x64');
106
+ expect(platforms).toContain('linux-arm64');
107
+ });
108
+ });
109
+
110
+ describe('getDownloadInfo', () => {
111
+ it('should return download URL for latest version', async () => {
112
+ const info = await client.getDownloadInfo(testBundle, undefined, {
113
+ os: 'linux',
114
+ arch: 'x64',
115
+ });
116
+
117
+ expect(info.url).toBeDefined();
118
+ expect(info.url).toMatch(/^https?:\/\//);
119
+ expect(info.bundle.version).toBeDefined();
120
+ expect(info.bundle.platform).toBeDefined();
121
+ expect(info.bundle.size).toBeGreaterThan(0);
122
+ expect(info.bundle.sha256).toBeDefined();
123
+ });
124
+
125
+ it('should return correct artifact for requested platform', async () => {
126
+ const info = await client.getDownloadInfo(testBundle, undefined, {
127
+ os: 'linux',
128
+ arch: 'arm64',
129
+ });
130
+
131
+ expect(info.bundle.platform.os).toBe('linux');
132
+ expect(info.bundle.platform.arch).toBe('arm64');
133
+ });
134
+
135
+ it('should return download info for specific version', async () => {
136
+ const versions = await client.getVersions(testBundle);
137
+ const specificVersion = versions.versions[0].version;
138
+
139
+ const info = await client.getDownloadInfo(testBundle, specificVersion, {
140
+ os: 'linux',
141
+ arch: 'x64',
142
+ });
143
+
144
+ expect(info.bundle.version).toBe(specificVersion);
145
+ });
146
+ });
147
+
148
+ describe('downloadBundle', () => {
149
+ it('should download bundle file successfully', async () => {
150
+ const info = await client.getDownloadInfo(testBundle, undefined, {
151
+ os: 'linux',
152
+ arch: 'x64',
153
+ });
154
+
155
+ const outputPath = path.join(
156
+ process.cwd(),
157
+ `test-download-${Date.now()}.mcpb`
158
+ );
159
+ downloadedFiles.push(outputPath);
160
+
161
+ await client.downloadBundle(info.url, outputPath);
162
+
163
+ expect(fs.existsSync(outputPath)).toBe(true);
164
+
165
+ const stats = fs.statSync(outputPath);
166
+ expect(stats.size).toBe(info.bundle.size);
167
+ }, 60000); // 60s timeout for download
168
+ });
169
+
170
+ describe('detectPlatform', () => {
171
+ it('should return valid platform object', () => {
172
+ const platform = RegistryClient.detectPlatform();
173
+
174
+ expect(platform.os).toBeDefined();
175
+ expect(platform.arch).toBeDefined();
176
+ expect(['darwin', 'linux', 'win32', 'any']).toContain(platform.os);
177
+ expect(['x64', 'arm64', 'any']).toContain(platform.arch);
178
+ });
179
+ });
180
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "noEmit": true
6
+ },
7
+ "include": ["src/**/*", "test/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
package/vitest.config.ts CHANGED
@@ -4,10 +4,11 @@ export default defineConfig({
4
4
  test: {
5
5
  globals: true,
6
6
  environment: 'node',
7
+ include: ['src/**/*.test.ts', 'test/**/*.test.ts'],
7
8
  coverage: {
8
9
  provider: 'v8',
9
10
  reporter: ['text', 'json', 'html'],
10
- exclude: ['dist', 'node_modules', '**/*.test.ts', '**/*.config.ts'],
11
+ exclude: ['dist', 'node_modules', '**/*.test.ts', '**/*.config.ts', 'test'],
11
12
  },
12
13
  },
13
14
  });