Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
server.ts5.41 kB
#!/usr/bin/env node import Fastify, { type FastifyInstance, type FastifyRequest, type FastifyReply, } from "fastify"; import cors from "@fastify/cors"; import staticFiles from "@fastify/static"; import { fileURLToPath } from "url"; import { dirname, join } from "path"; import { SMTPHandler } from "./smtp/handler.js"; import { ServerConfigSchema, type EmailListResponse, type EmailResponse, type ApiResponse, } from "./types/index.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const configResult = ServerConfigSchema.safeParse({ smtpPort: parseInt(process.env.SMTP_PORT || "1025"), webPort: parseInt(process.env.WEB_PORT || "8025"), host: process.env.HOST || "0.0.0.0", maxEmails: parseInt(process.env.MAX_EMAILS || "1000"), allowedHosts: process.env.ALLOWED_HOSTS?.split(",").map((h) => h.trim()), }); if (!configResult.success) { console.error("❌ Invalid configuration:", configResult.error.format()); process.exit(1); } const config = configResult.data; const fastify: FastifyInstance = Fastify({ logger: true, }); const smtpHandler = new SMTPHandler(config.smtpPort, config.maxEmails); async function setupServer(): Promise<void> { await fastify.register(cors, { origin: ["http://localhost:5173", "http://localhost:4173"], credentials: true, }); await fastify.register(staticFiles, { root: join(__dirname, "../ui/dist/assets"), prefix: "/assets/", decorateReply: false, }); await fastify.register(staticFiles, { root: join(__dirname, "../ui/dist"), prefix: "/", decorateReply: false, }); fastify.get("/api/health", async () => ({ success: true, data: { status: "healthy" }, })); fastify.get( "/api/emails", async ( request: FastifyRequest<{ Querystring: { page?: string; pageSize?: string }; }> ) => { const page = parseInt(request.query.page || "1"); const pageSize = parseInt(request.query.pageSize || "50"); return { success: true, data: smtpHandler.getEmails(page, pageSize) }; } ); fastify.get( "/api/emails/:id", async (request: FastifyRequest<{ Params: { id: string } }>) => { const email = smtpHandler.getEmailById(request.params.id); if (!email) { throw new Error("Email not found"); } return { success: true, data: email }; } ); fastify.delete( "/api/emails/:id", async (request: FastifyRequest<{ Params: { id: string } }>) => { const deleted = smtpHandler.deleteEmail(request.params.id); return { success: true, data: { deleted } }; } ); fastify.delete("/api/emails", async () => { const cleared = smtpHandler.clearAllEmails(); return { success: true, data: { cleared } }; }); fastify.get("/api/stats", async () => { const stats = smtpHandler.getStats(); return { success: true, data: { totalEmails: stats.totalEmails, uptime: process.uptime().toFixed(2) + "s", }, }; }); fastify.setNotFoundHandler( async (request: FastifyRequest, reply: FastifyReply) => { if (request.url.startsWith("/api/")) { return reply.code(404).send({ success: false, error: "Not found" }); } return reply.sendFile("index.html"); } ); } fastify.setErrorHandler(async (error, request, reply) => { const statusCode = error.statusCode || 500; const message = error.message || "Internal Server Error"; fastify.log.error({ error, request: request.url }, "Request error"); return reply.code(statusCode).send({ success: false, error: message }); }); async function closeGracefully(signal: string): Promise<void> { console.log(`\n🛑 Received ${signal}, shutting down gracefully...`); try { await smtpHandler.stop(); console.log("✅ SMTP server stopped"); await fastify.close(); console.log("✅ Web server stopped"); process.exit(0); } catch (error) { console.error("❌ Error during shutdown:", error); process.exit(1); } } async function main(): Promise<void> { try { console.log("🚀 Starting Phoenix Development SMTP Server..."); console.log("================================================"); console.log(`📧 SMTP Port: ${config.smtpPort}`); console.log(`🌐 Web Port: ${config.webPort}`); console.log(`🏠 Host: ${config.host}`); console.log(`📨 Max Emails: ${config.maxEmails}`); await setupServer(); await smtpHandler.start(); console.log(`✅ SMTP server listening on port ${config.smtpPort}`); await fastify.listen({ port: config.webPort, host: config.host, }); console.log( `✅ Web server listening on http://${config.host}:${config.webPort}` ); console.log(""); console.log("📧 Send emails to any address @localhost"); console.log(`🌐 View emails at: http://localhost:${config.webPort}`); console.log(""); console.log("Press Ctrl+C to stop the server"); process.on("SIGTERM", () => closeGracefully("SIGTERM")); process.on("SIGINT", () => closeGracefully("SIGINT")); } catch (error) { console.error("❌ Failed to start server:", error); process.exit(1); } } if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { console.error("❌ Startup error:", error); process.exit(1); }); } export { fastify };

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/Arize-ai/phoenix'

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