#!/usr/bin/env node
/**
* Postinstall script that downloads the correct prebuilt binary for the current platform.
* This allows the MCP server to run without Node.js in the PATH.
*/
const https = require('https');
const fs = require('fs');
const path = require('path');
const PACKAGE_NAME = 'fastmode-mcp';
const BINARY_NAME = 'fastmode-mcp';
// Get package version from package.json
const packageJson = require('../package.json');
const VERSION = packageJson.version;
// Platform/arch mapping
const PLATFORM_MAP = {
'darwin-arm64': 'macos-arm64',
'darwin-x64': 'macos-x64',
'linux-arm64': 'linux-arm64',
'linux-x64': 'linux-x64',
'win32-x64': 'win-x64',
'win32-arm64': 'win-arm64',
};
function getPlatformKey() {
const platform = process.platform;
const arch = process.arch;
return `${platform}-${arch}`;
}
function getBinaryUrl(version, platformKey) {
const platformSuffix = PLATFORM_MAP[platformKey];
if (!platformSuffix) {
return null;
}
const ext = process.platform === 'win32' ? '.exe' : '';
const filename = `${BINARY_NAME}-${platformSuffix}${ext}`;
// Download from GitHub Releases (public repo for binaries)
return `https://github.com/arihgoldstein/fastmode-mcp/releases/download/v${version}/${filename}`;
}
function downloadFile(url, destPath) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(destPath);
const request = (url) => {
https.get(url, (response) => {
// Handle redirects
if (response.statusCode === 301 || response.statusCode === 302) {
request(response.headers.location);
return;
}
if (response.statusCode === 404) {
file.close();
fs.unlinkSync(destPath);
reject(new Error(`Binary not found at ${url}`));
return;
}
if (response.statusCode !== 200) {
file.close();
fs.unlinkSync(destPath);
reject(new Error(`Failed to download: ${response.statusCode}`));
return;
}
response.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
}).on('error', (err) => {
file.close();
fs.unlinkSync(destPath);
reject(err);
});
};
request(url);
});
}
async function main() {
const platformKey = getPlatformKey();
const binaryUrl = getBinaryUrl(VERSION, platformKey);
if (!binaryUrl) {
console.log(`No prebuilt binary available for ${platformKey}`);
console.log('Falling back to Node.js execution');
return;
}
const binDir = path.join(__dirname, '..', 'bin');
const ext = process.platform === 'win32' ? '.exe' : '';
const binaryPath = path.join(binDir, `${BINARY_NAME}${ext}`);
// Create bin directory if it doesn't exist
if (!fs.existsSync(binDir)) {
fs.mkdirSync(binDir, { recursive: true });
}
console.log(`Downloading ${PACKAGE_NAME} binary for ${platformKey}...`);
try {
await downloadFile(binaryUrl, binaryPath);
// Make executable on Unix
if (process.platform !== 'win32') {
fs.chmodSync(binaryPath, 0o755);
}
console.log(`Successfully installed ${BINARY_NAME} binary`);
} catch (error) {
// Binary download failed - this is OK, we'll fall back to Node.js
console.log(`Binary download failed: ${error.message}`);
console.log('Falling back to Node.js execution');
}
}
main().catch((error) => {
// Don't fail the install if binary download fails
console.error('Postinstall warning:', error.message);
process.exit(0);
});