@tb.p/terminai
Version:
MCP (Model Context Protocol) server for secure SSH remote command execution. Enables AI assistants like Claude, Cursor, and VS Code to execute commands on remote servers via SSH with command validation, history tracking, and web-based configuration UI.
67 lines (53 loc) • 1.89 kB
JavaScript
import express from 'express';
import { readFileSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import { createConfigRouter } from './routes/config.js';
import { createFilesRouter } from './routes/files.js';
import { createKeysRouter } from './routes/keys.js';
import { createHistoryRouter } from './routes/history.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function startUIServer(port = 8374, configPath) {
const app = express();
app.use(express.json());
app.use('/api', createConfigRouter(configPath));
app.use('/api', createFilesRouter());
app.use('/api', createKeysRouter());
app.use('/api', createHistoryRouter());
app.get('/', (req, res) => {
try {
const htmlPath = resolve(__dirname, 'index.html');
const html = readFileSync(htmlPath, 'utf-8');
res.send(html);
} catch (error) {
res.status(500).send('Error loading UI');
}
});
const server = app.listen(port, '127.0.0.1', () => {
console.log(`SSH MCP Server Web UI running at http://127.0.0.1:${port}`);
console.log('Press Ctrl+C to stop');
const open = async (url) => {
const { default: openModule } = await import('open');
await openModule(url);
};
open(`http://127.0.0.1:${port}`).catch(() => {
console.log('Could not auto-open browser. Please open the URL manually.');
});
});
let isShuttingDown = false;
const handleShutdown = () => {
if (isShuttingDown) return;
isShuttingDown = true;
console.log('\nShutting down...');
server.close(() => {
process.exit(0);
});
// Force exit after 5 seconds if graceful shutdown fails
setTimeout(() => {
process.exit(1);
}, 5000);
};
process.once('SIGINT', handleShutdown);
process.once('SIGTERM', handleShutdown);
}