#!/usr/bin/env node
/**
* @file Check tunnel status
* @module scripts/tunnel-status
*/
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.join(__dirname, '..');
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
};
function log(message: string, color: string = colors.reset): void {
console.log(`${color}${message}${colors.reset}`);
}
function checkTunnelStatus(): void {
console.log('๐ Tunnel Status Check\n');
// Check for tunnel URL in environment or daemon logs
let url: string | null = null;
const daemonTunnelFile = path.join(projectRoot, 'daemon', 'logs', 'tunnel-url.txt');
// Check environment first
if (process.env.TUNNEL_URL) {
url = process.env.TUNNEL_URL;
} else if (fs.existsSync(daemonTunnelFile)) {
url = fs.readFileSync(daemonTunnelFile, 'utf8').trim();
}
if (url) {
// Check if cloudflared process is running
let processRunning = false;
try {
execSync('pgrep cloudflared', { stdio: 'ignore' });
processRunning = true;
} catch {
processRunning = false;
}
if (processRunning) {
log('โ
Tunnel is ACTIVE', colors.green);
log(`๐ Public URL: ${colors.cyan}${url}${colors.reset}`);
log(`๐ก MCP Endpoint: ${colors.cyan}${url}/mcp${colors.reset}`);
console.log('\nTo use this tunnel:');
console.log(` 1. In tests: ${colors.yellow}MCP_BASE_URL="${url}" npm test${colors.reset}`);
console.log(` 2. Auto-detect: ${colors.yellow}cd e2e-test && npm run test:tunnel${colors.reset}`);
console.log(` 3. From root: ${colors.yellow}npm run test:tunnel${colors.reset}`);
// Test connectivity
console.log('\n๐ Testing connectivity...');
fetch(`${url}/health`)
.then(res => {
if (res.ok) {
log('โ
Tunnel is accessible and working!', colors.green);
} else {
log(`โ ๏ธ Tunnel returned status ${res.status}`, colors.yellow);
}
})
.catch(err => {
log('โ Cannot connect to tunnel', colors.red);
console.log(` Error: ${err.message}`);
});
} else {
log('โ ๏ธ Tunnel URL found but cloudflared is not running', colors.yellow);
log(` Stale URL: ${url}`, colors.yellow);
console.log('\nCleaning up stale tunnel file...');
if (fs.existsSync(daemonTunnelFile)) {
fs.unlinkSync(daemonTunnelFile);
}
log('โ
Cleaned up', colors.green);
}
} else {
log('โ No tunnel is currently running', colors.red);
console.log('\nTo start a tunnel:');
console.log(` 1. Manual: ${colors.yellow}npm run tunnel${colors.reset}`);
console.log(` 2. With test: ${colors.yellow}npm run test:tunnel${colors.reset}`);
console.log(` 3. Just tunnel: ${colors.yellow}cloudflared tunnel --url http://localhost:3000${colors.reset}`);
}
// Check if server is running
console.log('\n๐ Server Status:');
fetch('http://localhost:3000/health')
.then(res => {
if (res.ok) {
log('โ
MCP server is running on port 3000', colors.green);
} else {
log(`โ ๏ธ Server returned status ${res.status}`, colors.yellow);
}
})
.catch(() => {
log('โ MCP server is not running', colors.red);
console.log(` Start it with: ${colors.yellow}npm start${colors.reset}`);
});
}
// Run the check
checkTunnelStatus();