@aithr-ai/mcp-server 1.0.14 → 1.0.16

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.
Files changed (2) hide show
  1. package/index.js +121 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -583,6 +583,33 @@ class MCPServer {
583
583
  required: ['targetPath'],
584
584
  },
585
585
  },
586
+ {
587
+ name: 'aether_download_zip',
588
+ description: 'Download all project artifacts as a ZIP file to a local path. Extracts code files from artifacts and saves them in proper directory structure.',
589
+ inputSchema: {
590
+ type: 'object',
591
+ properties: {
592
+ targetPath: {
593
+ type: 'string',
594
+ description: 'Full path where to save the ZIP file (e.g., C:/Users/you/Downloads/project.zip)',
595
+ },
596
+ extractCode: {
597
+ type: 'boolean',
598
+ description: 'Extract code files from artifacts (default: true)',
599
+ },
600
+ includeRaw: {
601
+ type: 'boolean',
602
+ description: 'Include raw artifact markdown files (default: false)',
603
+ },
604
+ artifactIds: {
605
+ type: 'array',
606
+ items: { type: 'string' },
607
+ description: 'Specific artifact IDs to include (optional, includes all if not provided)',
608
+ },
609
+ },
610
+ required: ['targetPath'],
611
+ },
612
+ },
586
613
  // =========================================================================
587
614
  // Canvas Folder Tools
588
615
  // =========================================================================
@@ -1095,6 +1122,9 @@ class MCPServer {
1095
1122
  case 'aether_write_local':
1096
1123
  result = await this.writeLocal(args);
1097
1124
  break;
1125
+ case 'aether_download_zip':
1126
+ result = await this.downloadZip(args);
1127
+ break;
1098
1128
  // Canvas Folder Tools
1099
1129
  case 'aether_list_folders':
1100
1130
  result = await this.listFolders(args);
@@ -2298,6 +2328,97 @@ class MCPServer {
2298
2328
  }
2299
2329
  }
2300
2330
 
2331
+ /**
2332
+ * Download all project artifacts as a ZIP file to a local path
2333
+ */
2334
+ async downloadZip(args) {
2335
+ const projectId = config.projectId;
2336
+
2337
+ if (!projectId) {
2338
+ return { error: 'No project ID configured. Set AETHER_PROJECT_ID environment variable.' };
2339
+ }
2340
+
2341
+ const {
2342
+ targetPath,
2343
+ extractCode = true,
2344
+ includeRaw = false,
2345
+ artifactIds,
2346
+ } = args;
2347
+
2348
+ if (!targetPath) {
2349
+ return { error: 'targetPath is required - specify where to save the ZIP file (e.g., C:/Users/you/Downloads/project.zip)' };
2350
+ }
2351
+
2352
+ // Ensure targetPath ends with .zip
2353
+ const zipPath = targetPath.endsWith('.zip') ? targetPath : `${targetPath}.zip`;
2354
+
2355
+ try {
2356
+ // Build query string
2357
+ const params = new URLSearchParams();
2358
+ params.set('extractCode', String(extractCode));
2359
+ params.set('includeRaw', String(includeRaw));
2360
+ if (artifactIds && artifactIds.length > 0) {
2361
+ params.set('artifactIds', artifactIds.join(','));
2362
+ }
2363
+
2364
+ // Fetch the ZIP from the download endpoint
2365
+ const url = `${config.apiBaseUrl}/api/workspaces/${config.workspaceSlug}/projects/${projectId}/artifacts/download?${params.toString()}`;
2366
+
2367
+ const response = await fetch(url, {
2368
+ headers: {
2369
+ 'Authorization': `Bearer ${config.apiKey}`,
2370
+ },
2371
+ });
2372
+
2373
+ if (!response.ok) {
2374
+ const errorText = await response.text();
2375
+ let errorMessage;
2376
+ try {
2377
+ const errorJson = JSON.parse(errorText);
2378
+ errorMessage = errorJson.error || 'Failed to download ZIP';
2379
+ } catch {
2380
+ errorMessage = errorText || 'Failed to download ZIP';
2381
+ }
2382
+ return { error: errorMessage };
2383
+ }
2384
+
2385
+ // Get file info from headers
2386
+ const fileCount = response.headers.get('X-File-Count') || '0';
2387
+ const artifactCount = response.headers.get('X-Artifact-Count') || '0';
2388
+
2389
+ // Get the ZIP data
2390
+ const zipBuffer = await response.arrayBuffer();
2391
+
2392
+ // Ensure the directory exists
2393
+ const path = await import('path');
2394
+ const fs = await import('fs');
2395
+ const dir = path.dirname(zipPath);
2396
+
2397
+ if (!fs.existsSync(dir)) {
2398
+ fs.mkdirSync(dir, { recursive: true });
2399
+ }
2400
+
2401
+ // Write the ZIP file
2402
+ fs.writeFileSync(zipPath, Buffer.from(zipBuffer));
2403
+
2404
+ const stats = fs.statSync(zipPath);
2405
+
2406
+ return {
2407
+ success: true,
2408
+ path: zipPath,
2409
+ size: stats.size,
2410
+ sizeFormatted: stats.size > 1024 * 1024
2411
+ ? `${(stats.size / (1024 * 1024)).toFixed(2)} MB`
2412
+ : `${(stats.size / 1024).toFixed(2)} KB`,
2413
+ fileCount: parseInt(fileCount, 10),
2414
+ artifactCount: parseInt(artifactCount, 10),
2415
+ message: `ZIP file saved to ${zipPath} (${fileCount} files from ${artifactCount} artifacts)`,
2416
+ };
2417
+ } catch (e) {
2418
+ return { error: e.message };
2419
+ }
2420
+ }
2421
+
2301
2422
  /**
2302
2423
  * Write files directly to local disk (runs in MCP server, not Vercel)
2303
2424
  * Fetches files from generatedFiles API in batches and writes them locally
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aithr-ai/mcp-server",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "MCP server to connect Claude Code to Aether canvas - AI-powered team workspace for software development",
5
5
  "main": "index.js",
6
6
  "bin": {