#!/usr/bin/env node
import { execSync } from 'child_process';
import { readFileSync, existsSync } from 'fs';
import { createInterface } from 'readline';
const rl = createInterface({
input: process.stdin,
output: process.stdout
});
function question(query) {
return new Promise(resolve => rl.question(query, resolve));
}
function exec(command, options = {}) {
try {
return execSync(command, { stdio: 'inherit', ...options });
} catch (error) {
console.error(`Command failed: ${command}`);
throw error;
}
}
async function main() {
console.log('π Netlify Deployment for MCP Server Airflow\n');
// Check if netlify CLI is installed
try {
execSync('netlify --version', { stdio: 'pipe' });
} catch (error) {
console.log('β Netlify CLI not found. Installing...');
exec('npm install -g netlify-cli');
}
// Check if user is authenticated
try {
execSync('netlify status', { stdio: 'pipe' });
console.log('β
Netlify authentication confirmed');
} catch (error) {
console.log('π Please authenticate with Netlify...');
exec('netlify login');
}
// Build the project
console.log('\nπ¦ Building project for Netlify...');
exec('npm run build:netlify');
// Check if site exists
let siteExists = false;
try {
execSync('netlify status', { stdio: 'pipe' });
siteExists = true;
console.log('β
Existing Netlify site found');
} catch (error) {
console.log('π No existing site found, will create new one');
}
if (!siteExists) {
const siteName = await question('Enter a site name (optional): ');
const deployCmd = siteName
? `netlify init --manual --name ${siteName}`
: 'netlify init --manual';
console.log('\nπ Creating new Netlify site...');
exec(deployCmd);
}
// Configure environment variables
console.log('\nπ§ Environment Variables Setup');
const setupEnv = await question('Would you like to set up environment variables now? (y/n): ');
if (setupEnv.toLowerCase() === 'y') {
console.log('\nπ Setting up Airflow connection...');
const airflowBaseUrl = await question('Enter your Airflow base URL (e.g., https://your-airflow.com): ');
if (!airflowBaseUrl.trim()) {
console.log('β Airflow base URL is required');
rl.close();
return;
}
console.log('\nChoose authentication method:');
console.log('1. API Token (recommended)');
console.log('2. Username/Password');
const authChoice = await question('Enter choice (1 or 2): ');
try {
// Set the base URL
console.log('\nπ Setting AIRFLOW_BASE_URL...');
exec(`netlify env:set AIRFLOW_BASE_URL "${airflowBaseUrl}"`);
if (authChoice === '1') {
const airflowToken = await question('Enter your Airflow API token: ');
if (!airflowToken.trim()) {
console.log('β Airflow token is required');
rl.close();
return;
}
console.log('π Setting AIRFLOW_TOKEN...');
exec(`netlify env:set AIRFLOW_TOKEN "${airflowToken}"`);
} else if (authChoice === '2') {
const airflowUsername = await question('Enter your Airflow username: ');
const airflowPassword = await question('Enter your Airflow password: ');
if (!airflowUsername.trim() || !airflowPassword.trim()) {
console.log('β Both username and password are required');
rl.close();
return;
}
console.log('π Setting AIRFLOW_USERNAME...');
exec(`netlify env:set AIRFLOW_USERNAME "${airflowUsername}"`);
console.log('π Setting AIRFLOW_PASSWORD...');
exec(`netlify env:set AIRFLOW_PASSWORD "${airflowPassword}"`);
} else {
console.log('β Invalid authentication choice');
rl.close();
return;
}
console.log('β
Environment variables configured successfully!');
// Verify environment variables
console.log('\nπ Verifying environment variables...');
try {
exec('netlify env:list');
} catch (error) {
console.log('β οΈ Could not list environment variables, but they should be set');
}
} catch (error) {
console.log('β Failed to set environment variables:', error.message);
console.log('\nπ‘ You can set them manually in the Netlify dashboard:');
console.log('1. Go to your site settings');
console.log('2. Navigate to Environment Variables');
console.log('3. Add the variables listed in .env.netlify.example');
const continueAnyway = await question('\nContinue with deployment? (y/n): ');
if (continueAnyway.toLowerCase() !== 'y') {
rl.close();
return;
}
}
} else {
console.log('\nπ‘ You can set environment variables later using:');
console.log('netlify env:set AIRFLOW_BASE_URL "https://your-airflow.com"');
console.log('netlify env:set AIRFLOW_TOKEN "your_token"');
console.log('');
console.log('Or manually in the Netlify dashboard.');
const continueAnyway = await question('\nContinue with deployment? (y/n): ');
if (continueAnyway.toLowerCase() !== 'y') {
rl.close();
return;
}
}
// Deploy to production
console.log('\nπ Deploying to production...');
exec('netlify deploy --prod');
// Get the site URL
try {
const siteInfo = execSync('netlify status --json', { encoding: 'utf8' });
const site = JSON.parse(siteInfo);
const siteUrl = site.site_url;
console.log('\nβ
Deployment successful!');
console.log(`π Site URL: ${siteUrl}`);
console.log(`π₯ Health check: ${siteUrl}/health`);
console.log(`π§ MCP endpoint: ${siteUrl}/mcp`);
console.log('\nπ‘ Claude Desktop Configuration:');
console.log('Add this to your Claude Desktop MCP settings:');
console.log(`{
"mcpServers": {
"airflow": {
"transport": {
"type": "http",
"url": "${siteUrl}/mcp"
}
}
}
}`);
} catch (error) {
console.log('\nβ
Deployment completed! Check your Netlify dashboard for the site URL.');
}
rl.close();
}
main().catch(console.error);