Skip to main content
Glama

Next.js MCP Server

by vertile-ai
setup.ts4.04 kB
import type { Express } from 'express' import express from 'express'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js' import { Server } from '@modelcontextprotocol/sdk/server/index.js'; /** * Resolve port from command line args or environment variables * Returns port number with 8080 as the default * * Note: The port option is only applicable when using --transport=sse * as it controls the HTTP server port for SSE connections. */ export function resolvePort(): { port: number; source: string } { // Get command line arguments const args = parseCommandLineArgs(); // 1. Check command line arguments first (highest priority) if (args.port) { const port = parseInt(args.port, 10); return { port, source: 'command line argument' }; } // 2. Check environment variables if (process.env.PORT) { const port = parseInt(process.env.PORT, 10); return { port, source: 'environment variable' }; } // 3. Default to 4857 return { port: 4857, source: 'default' }; } export async function setupSSE(base: string, server: Server): Promise<Express> { const app = express(); const transports = new Map<string, SSEServerTransport>() app.use(`${base}/sse`, async (req, res) => { const transport = new SSEServerTransport(`${base}/messages`, res) transports.set(transport.sessionId, transport) res.on('close', () => { transports.delete(transport.sessionId) }) await server.connect(transport) }) app.use(`${base}/messages`, async (req, res) => { if (req.method !== 'POST') { res.statusCode = 405 res.end('Method Not Allowed') return } const query = new URLSearchParams(req.url?.split('?').pop() || '') const clientId = query.get('sessionId') if (!clientId || typeof clientId !== 'string') { res.statusCode = 400 res.end('Bad Request due to missing sessionId') return } const transport = transports.get(clientId) if (!transport) { res.statusCode = 404 res.end('Not Found due to invalid sessionId') return } await transport.handlePostMessage(req, res); }) return app; } /** * Parse command line arguments * @returns {Record<string, string>} */ export function parseCommandLineArgs(): Record<string, string> { // Check if any args start with '--' (the way tsx passes them) const args = process.argv.slice(2); const parsedManually: Record<string, string> = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--')) { const [key, value] = arg.substring(2).split('='); if (value) { // Handle --key=value format parsedManually[key] = value; } else if (i + 1 < args.length && !args[i + 1].startsWith('--')) { // Handle --key value format parsedManually[key] = args[i + 1]; i++; // Skip the next argument as it's the value } else { // Handle --key format (boolean flag) parsedManually[key] = 'true'; } } } // Just use the manually parsed args - removed parseArgs dependency for Node.js <18.3.0 compatibility return parsedManually; } /** * Resolve transport type from command line args or environment variables * Returns 'stdio' or 'sse', with 'stdio' as the default */ export function resolveTransport(): { type: 'stdio' | 'sse'; source: string } { // Get command line arguments const args = parseCommandLineArgs(); // 1. Check command line arguments first (highest priority) if (args.transport) { const type = args.transport === 'sse' ? 'sse' : 'stdio'; return { type, source: 'command line argument' }; } // 2. Check environment variables if (process.env.TRANSPORT) { const type = process.env.TRANSPORT === 'sse' ? 'sse' : 'stdio'; return { type, source: 'environment variable' }; } // 3. Default to localhost sse return { type: 'sse', source: 'default' }; }

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/vertile-ai/next-mcp-server'

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