Skip to main content
Glama
kevin-weitgenant

LinkedIn-Posts-Hunter-MCP-Server

start-server.ts3.62 kB
import express from 'express'; import path from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; import http from 'http'; import open from 'open'; import cors from 'cors'; import { createApiRouter } from './server-api/api-router.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export interface ViteViewerResult { port: number; status: 'started' | 'already_running'; url: string; message: string; } // Module-level state tracking for singleton pattern let activeViteServer: { server: http.Server; port: number; url: string; } | null = null; /** * Start the Vite static viewer using Express * Serves pre-built static files from dist/ with API routes * Reuses existing server if already running */ export async function startViteViewer(): Promise<ViteViewerResult> { // Check if server is already running if (activeViteServer) { // Open browser again for convenience await open(activeViteServer.url); return { port: activeViteServer.port, status: 'already_running', url: activeViteServer.url, message: `Vite viewer already running at ${activeViteServer.url}. Browser opened again.` }; } const PORT = 4327; // Get the dist directory path (build/client-vite/dist/) const buildRoot = path.resolve(__dirname, '..'); const distDir = path.join(buildRoot, 'client-vite', 'dist'); // Check if dist directory exists if (!fs.existsSync(distDir)) { throw new Error(`Dist directory not found: ${distDir}. Did you run 'npm run build'?`); } // Create Express app const app = express(); // Middleware app.use(cors()); app.use(express.json()); // API routes app.use('/api', createApiRouter()); // Serve static files from dist directory app.use(express.static(distDir)); // SPA fallback - serve index.html for all other routes app.get('/*splat', (req, res) => { res.sendFile(path.join(distDir, 'index.html')); }); // Create HTTP server return new Promise((resolve, reject) => { const server = http.createServer(app); // Handle server errors server.on('error', (error: Error) => { reject(new Error(`Failed to start Vite viewer: ${error.message}`)); }); // Start listening server.listen(PORT, () => { const url = `http://localhost:${PORT}`; // Store active server info for singleton pattern activeViteServer = { server, port: PORT, url }; // Open browser open(url).catch(() => { // Ignore browser open errors }); resolve({ port: PORT, status: 'started', url: url, message: `Vite viewer started at ${url}. Browser opened automatically.\n\nReact app auto-polls for updates every 3 seconds - no page reloads needed!` }); }); }); } /** * Stop the Vite viewer server * Shuts down the active server and clears the singleton state */ export function stopViteViewer(): { success: boolean; message: string } { if (!activeViteServer) { return { success: false, message: 'No Vite viewer server is currently running.' }; } try { const url = activeViteServer.url; activeViteServer.server.close(); activeViteServer = null; return { success: true, message: `Vite viewer server at ${url} has been stopped.` }; } catch (error) { return { success: false, message: `Failed to stop Vite viewer: ${error instanceof Error ? error.message : 'Unknown error'}` }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kevin-weitgenant/LinkedIn-Posts-Hunter-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server