UNPKG

fusion-mcp-cli

Version:

CLI tool for Fusion MCP Hub - Manage custom and community MCP servers. Web App: https://fusion-mcp-hub.vercel.app (General) | https://fusion-mcp-prod.isc-code-connect.dal.app.cirrus.ibm.com (IBM)

264 lines 10 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDefaultServersPath = getDefaultServersPath; exports.downloadFile = downloadFile; exports.extractZip = extractZip; exports.ensureDir = ensureDir; exports.dirExists = dirExists; exports.fileExists = fileExists; exports.readJsonFile = readJsonFile; exports.writeJsonFile = writeJsonFile; exports.getLocalServerMetadata = getLocalServerMetadata; exports.saveLocalServerMetadata = saveLocalServerMetadata; exports.downloadAndExtractServer = downloadAndExtractServer; exports.createZipFromDirectory = createZipFromDirectory; exports.getDirectoryFiles = getDirectoryFiles; exports.calculateFileHash = calculateFileHash; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const axios_1 = __importDefault(require("axios")); const adm_zip_1 = __importDefault(require("adm-zip")); const https = __importStar(require("https")); const os = __importStar(require("os")); const config_1 = require("./config"); /** * Get the default servers directory path */ function getDefaultServersPath() { return path_1.default.join(os.homedir(), ".fusion-mcp", "servers"); } /** * Download file from URL */ async function downloadFile(url, outputPath) { const token = (0, config_1.getApiToken)(); // Create HTTPS agent that accepts self-signed certificates for localhost and Cirrus environments const isLocalhost = url.includes('localhost') || url.includes('127.0.0.1'); const isCirrusEnvironment = url.includes('.cirrus.ibm.com'); const allowSelfSignedCerts = isLocalhost || isCirrusEnvironment; const httpsAgent = new https.Agent({ rejectUnauthorized: !allowSelfSignedCerts, // Allow self-signed certs for localhost and Cirrus environments }); const response = await (0, axios_1.default)({ url, method: "GET", responseType: "stream", headers: token ? { Authorization: `Bearer ${token}`, } : undefined, httpsAgent, }); const writer = fs_extra_1.default.createWriteStream(outputPath); response.data.pipe(writer); return new Promise((resolve, reject) => { writer.on("finish", resolve); writer.on("error", reject); }); } /** * Extract zip file to directory */ async function extractZip(zipPath, outputDir) { const zip = new adm_zip_1.default(zipPath); zip.extractAllTo(outputDir, true); } /** * Create directory if it doesn't exist */ async function ensureDir(dirPath) { await fs_extra_1.default.ensureDir(dirPath); } /** * Check if directory exists */ function dirExists(dirPath) { return fs_extra_1.default.existsSync(dirPath) && fs_extra_1.default.statSync(dirPath).isDirectory(); } /** * Check if file exists */ function fileExists(filePath) { return fs_extra_1.default.existsSync(filePath) && fs_extra_1.default.statSync(filePath).isFile(); } /** * Read JSON file */ async function readJsonFile(filePath) { const content = await fs_extra_1.default.readFile(filePath, "utf-8"); return JSON.parse(content); } /** * Write JSON file */ async function writeJsonFile(filePath, data) { await fs_extra_1.default.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8"); } /** * Get server metadata from local directory */ async function getLocalServerMetadata(serverDir) { const metadataPath = path_1.default.join(serverDir, ".fusion-mcp-metadata.json"); if (!fileExists(metadataPath)) { return null; } return readJsonFile(metadataPath); } /** * Save server metadata to local directory */ async function saveLocalServerMetadata(serverDir, metadata) { const metadataPath = path_1.default.join(serverDir, ".fusion-mcp-metadata.json"); await writeJsonFile(metadataPath, metadata); } /** * Download and extract server package */ async function downloadAndExtractServer(serverId, serverName, downloadUrl, outputDir) { // Create output directory if it doesn't exist await ensureDir(outputDir); // Use original server name for directory const serverDir = path_1.default.join(outputDir, serverName); // Check if directory already exists if (dirExists(serverDir)) { throw new Error(`Directory already exists: ${serverDir}. Please remove it first or use a different output directory.`); } // Server directory name (sanitized) for temp file only const serverDirName = serverName.replace(/[^a-zA-Z0-9-_]/g, "_"); const tempZipPath = path_1.default.join(outputDir, `${serverDirName}.zip`); const tempExtractDir = path_1.default.join(outputDir, `${serverDirName}_temp`); try { await downloadFile(downloadUrl, tempZipPath); // Extract zip to temp directory await extractZip(tempZipPath, tempExtractDir); // Check if contents are in a nested subdirectory const entries = await fs_extra_1.default.readdir(tempExtractDir, { withFileTypes: true }); // If there's only one subdirectory and no package.json at root, use that subdirectory const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")); const hasPackageJson = entries.some((e) => e.isFile() && e.name === "package.json"); if (!hasPackageJson && subdirs.length === 1) { const nestedPath = path_1.default.join(tempExtractDir, subdirs[0].name); const nestedEntries = await fs_extra_1.default.readdir(nestedPath, { withFileTypes: true, }); const hasNestedPackageJson = nestedEntries.some((e) => e.isFile() && e.name === "package.json"); if (hasNestedPackageJson) { // Nested structure detected, move the nested directory to final location await fs_extra_1.default.move(nestedPath, serverDir); } else { // No nested package.json, move temp dir as-is await fs_extra_1.default.move(tempExtractDir, serverDir); } } else { // No nesting, move temp dir directly await fs_extra_1.default.move(tempExtractDir, serverDir); } // Clean up temp files await fs_extra_1.default.remove(tempZipPath); // Clean up temp extract directory if it still exists if (await fs_extra_1.default.pathExists(tempExtractDir)) { await fs_extra_1.default.remove(tempExtractDir); } if (await fs_extra_1.default.pathExists(tempExtractDir)) { await fs_extra_1.default.remove(tempExtractDir); } return serverDir; } catch (error) { // Clean up on error if (fileExists(tempZipPath)) { await fs_extra_1.default.remove(tempZipPath); } if (dirExists(tempExtractDir)) { await fs_extra_1.default.remove(tempExtractDir); } if (dirExists(serverDir)) { await fs_extra_1.default.remove(serverDir); } throw error; } } /** * Create a zip file from directory */ async function createZipFromDirectory(sourceDir, outputZipPath) { const zip = new adm_zip_1.default(); // Add the entire directory zip.addLocalFolder(sourceDir); // Write zip file zip.writeZip(outputZipPath); } /** * Get list of files in directory */ async function getDirectoryFiles(dirPath, relativeTo) { const files = []; async function walk(dir) { const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path_1.default.join(dir, entry.name); if (entry.isDirectory()) { // Skip node_modules and hidden directories if (entry.name !== "node_modules" && !entry.name.startsWith(".")) { await walk(fullPath); } } else { const relativePath = relativeTo ? path_1.default.relative(relativeTo, fullPath) : fullPath; files.push(relativePath); } } } await walk(dirPath); return files; } /** * Calculate file hash for comparison */ async function calculateFileHash(filePath) { const crypto = require("crypto"); const content = await fs_extra_1.default.readFile(filePath); return crypto.createHash("sha256").update(content).digest("hex"); } //# sourceMappingURL=file.js.map