#!/usr/bin/env node
import { chromium } from 'playwright';
import fs from 'fs';
import path from 'path';
// Ensure screenshots directory exists
const screenshotsDir = './screenshots';
if (!fs.existsSync(screenshotsDir)) {
fs.mkdirSync(screenshotsDir, { recursive: true });
}
async function deployToSmitery() {
console.log('š Starting automated Smithery.ai deployment...');
const browser = await chromium.launch({
headless: false, // Keep visible for debugging
slowMo: 1000,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
});
const page = await context.newPage();
try {
// Step 1: Navigate to Smithery.ai homepage
console.log('š Step 1: Navigating to Smithery.ai...');
await page.goto('https://smithery.ai/', {
waitUntil: 'networkidle',
timeout: 30000
});
await page.waitForTimeout(3000);
await page.screenshot({ path: path.join(screenshotsDir, 'step1_homepage.png') });
console.log('ā
Screenshot saved: step1_homepage.png');
// Step 2: Check login status
console.log('š Step 2: Checking login status...');
let isLoggedIn = false;
try {
// Look for user avatar or profile indicators
await page.waitForSelector('img[alt*="avatar"], [data-testid="user-menu"], .user-avatar, .profile-menu', { timeout: 5000 });
isLoggedIn = true;
console.log('ā
Already logged in');
} catch (error) {
console.log('ā Not logged in, will need to authenticate');
}
// Step 3: Navigate to deployment page
console.log('š Step 3: Navigating to deployment page...');
await page.goto('https://smithery.ai/new', {
waitUntil: 'networkidle',
timeout: 30000
});
await page.waitForTimeout(3000);
await page.screenshot({ path: path.join(screenshotsDir, 'step2_deployment_page.png') });
console.log('ā
Screenshot saved: step2_deployment_page.png');
// Step 4: Handle authentication if needed
if (!isLoggedIn) {
console.log('š Step 4: Attempting to authenticate...');
// Look for login/auth buttons
const authSelectors = [
'button:has-text("Continue with GitHub")',
'button:has-text("Login")',
'button:has-text("Sign in")',
'a:has-text("Continue with GitHub")',
'a:has-text("Login")',
'[data-testid="github-auth"]',
'.github-auth'
];
let authClicked = false;
for (const selector of authSelectors) {
try {
const element = await page.waitForSelector(selector, { timeout: 2000 });
if (element) {
console.log(`š Found auth button: ${selector}`);
await element.click();
authClicked = true;
break;
}
} catch (error) {
// Continue to next selector
}
}
if (authClicked) {
console.log('š Authentication clicked, waiting for GitHub OAuth...');
await page.waitForTimeout(5000);
await page.screenshot({ path: path.join(screenshotsDir, 'step3_auth_flow.png') });
// Wait for return to Smithery after auth
console.log('ā³ Waiting for authentication to complete...');
await page.waitForTimeout(15000);
// Navigate back to deployment page
await page.goto('https://smithery.ai/new', {
waitUntil: 'networkidle',
timeout: 30000
});
await page.waitForTimeout(3000);
} else {
console.log('ā Could not find authentication button - manual auth required');
await page.screenshot({ path: path.join(screenshotsDir, 'step3_auth_required.png') });
}
}
// Repository deployment function
async function deployRepository(repoName, stepNumber) {
console.log(`š Step ${stepNumber}: Deploying ${repoName}...`);
// Navigate to new deployment page
await page.goto('https://smithery.ai/new', {
waitUntil: 'networkidle',
timeout: 30000
});
await page.waitForTimeout(3000);
// Look for repository input field
const repoInputSelectors = [
'input[placeholder*="repository"]',
'input[placeholder*="GitHub"]',
'input[placeholder*="repo"]',
'input[name="repository"]',
'input[name="repo"]',
'[data-testid="repo-input"]',
'input[type="text"]'
];
let repoInputFound = false;
for (const selector of repoInputSelectors) {
try {
const input = await page.waitForSelector(selector, { timeout: 3000 });
if (input) {
console.log(`š Found repo input: ${selector}`);
await input.fill(`samihalawa/${repoName}`);
repoInputFound = true;
break;
}
} catch (error) {
// Continue to next selector
}
}
if (!repoInputFound) {
console.log('ā Could not find repository input field');
await page.screenshot({ path: path.join(screenshotsDir, `step${stepNumber}_repo_input_error.png`) });
return false;
}
await page.waitForTimeout(2000);
// Look for deploy button
const deployButtonSelectors = [
'button:has-text("Deploy")',
'button:has-text("Deploy Server")',
'button:has-text("Create")',
'button[type="submit"]',
'[data-testid="deploy-button"]',
'.deploy-button'
];
let deployClicked = false;
for (const selector of deployButtonSelectors) {
try {
const button = await page.waitForSelector(selector, { timeout: 3000 });
if (button) {
console.log(`š Found deploy button: ${selector}`);
await button.click();
deployClicked = true;
break;
}
} catch (error) {
// Continue to next selector
}
}
if (!deployClicked) {
console.log('ā Could not find deploy button');
await page.screenshot({ path: path.join(screenshotsDir, `step${stepNumber}_deploy_button_error.png`) });
return false;
}
// Wait for deployment to process
console.log(`ā³ Waiting for ${repoName} deployment to process...`);
await page.waitForTimeout(10000);
// Take screenshot of deployment result
await page.screenshot({ path: path.join(screenshotsDir, `step${stepNumber}_${repoName}_deployed.png`) });
console.log(`ā
Screenshot saved: step${stepNumber}_${repoName}_deployed.png`);
return true;
}
// Step 5: Deploy wuolah-mcp
const wuolahDeployed = await deployRepository('wuolah-mcp', 5);
// Step 6: Deploy huggingface-mcp
const huggingfaceDeployed = await deployRepository('huggingface-mcp', 6);
// Step 7: Verify deployments
console.log('š Step 7: Verifying deployments...');
const repositories = [
{ name: 'wuolah-mcp', url: 'https://smithery.ai/server/@samihalawa/wuolah-mcp', deployed: wuolahDeployed },
{ name: 'huggingface-mcp', url: 'https://smithery.ai/server/@samihalawa/huggingface-mcp', deployed: huggingfaceDeployed }
];
const verificationResults = [];
for (const repo of repositories) {
console.log(`š Verifying ${repo.name} at ${repo.url}...`);
try {
await page.goto(repo.url, { waitUntil: 'networkidle', timeout: 30000 });
await page.waitForTimeout(3000);
// Check if page loads successfully (not 404)
const pageContent = await page.content();
const isSuccess = !pageContent.includes('404') && !pageContent.includes('Not Found');
await page.screenshot({ path: path.join(screenshotsDir, `step7_${repo.name}_verification.png`) });
verificationResults.push({
name: repo.name,
url: repo.url,
status: isSuccess ? 'SUCCESS' : 'FAILED',
deployed: repo.deployed
});
console.log(`${isSuccess ? 'ā
' : 'ā'} ${repo.name}: ${isSuccess ? 'SUCCESS' : 'FAILED'}`);
} catch (error) {
console.log(`ā Error verifying ${repo.name}:`, error.message);
verificationResults.push({
name: repo.name,
url: repo.url,
status: 'ERROR',
deployed: repo.deployed,
error: error.message
});
}
}
// Generate final report
console.log('š Generating deployment report...');
const report = {
timestamp: new Date().toISOString(),
deployments: verificationResults,
summary: {
total: repositories.length,
successful: verificationResults.filter(r => r.status === 'SUCCESS').length,
failed: verificationResults.filter(r => r.status === 'FAILED' || r.status === 'ERROR').length
}
};
fs.writeFileSync('./deployment_report.json', JSON.stringify(report, null, 2));
console.log('\\nš DEPLOYMENT SUMMARY:');
console.log('========================');
verificationResults.forEach(result => {
console.log(`${result.name}: ${result.status}`);
console.log(` URL: ${result.url}`);
console.log(` Deployed: ${result.deployed ? 'YES' : 'NO'}`);
if (result.error) {
console.log(` Error: ${result.error}`);
}
console.log('');
});
console.log(`š Total: ${report.summary.total} | Success: ${report.summary.successful} | Failed: ${report.summary.failed}`);
console.log('š Detailed report saved to: deployment_report.json');
} catch (error) {
console.error('š„ Error during deployment:', error);
await page.screenshot({ path: path.join(screenshotsDir, 'error_final.png') });
} finally {
console.log('š Closing browser...');
await browser.close();
}
}
// Run the deployment
deployToSmitery().catch(console.error);