Skip to main content
Glama

ContextEngine MCP Server

server-utils.ts•3.62 kB
import { IncomingMessage, ServerResponse } from "http"; import { logger } from "./logger.js"; /** * Extracts client IP from request headers */ export function getClientIp(req: IncomingMessage): string | undefined { const forwardedFor = req.headers["x-forwarded-for"] || req.headers["X-Forwarded-For"]; if (forwardedFor) { const ips = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor; const ipList = ips.split(",").map((ip) => ip.trim()); for (const ip of ipList) { const plainIp = ip.replace(/^::ffff:/, ""); if ( !plainIp.startsWith("10.") && !plainIp.startsWith("192.168.") && !/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(plainIp) ) { return plainIp; } } return ipList[0].replace(/^::ffff:/, ""); } if (req.socket?.remoteAddress) { return req.socket.remoteAddress.replace(/^::ffff:/, ""); } return undefined; } /** * Extracts header value safely, handling both string and string[] cases */ export function extractHeaderValue(value: string | string[] | undefined): string | undefined { if (!value) return undefined; return typeof value === "string" ? value : value[0]; } /** * Extracts Authorization header and removes Bearer prefix if present */ export function extractBearerToken(authHeader: string | string[] | undefined): string | undefined { const header = extractHeaderValue(authHeader); if (!header) return undefined; if (header.startsWith("Bearer ")) { return header.substring(7).trim(); } return header; } /** * Extracts API key from request headers in order of preference */ export function extractApiKey(req: IncomingMessage): string | undefined { return ( extractBearerToken(req.headers.authorization) || extractHeaderValue(req.headers["ContextEngine-API-Key"]) || extractHeaderValue(req.headers["context-engine-api-key"]) || extractHeaderValue(req.headers["X-API-Key"]) || extractHeaderValue(req.headers["x-api-key"]) ); } /** * Sets up CORS headers for HTTP responses */ export function setupCorsHeaders(res: ServerResponse): void { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE"); res.setHeader( "Access-Control-Allow-Headers", "Content-Type, MCP-Session-Id, MCP-Protocol-Version, X-ContextEngine-API-Key, ContextEngine-API-Key, X-API-Key, Authorization" ); res.setHeader("Access-Control-Expose-Headers", "MCP-Session-Id"); } /** * Sends error response with consistent formatting */ export function sendErrorResponse(res: ServerResponse, statusCode: number, message: string): void { res.writeHead(statusCode); res.end(message); } /** * Handles preflight OPTIONS requests */ export function handlePreflightRequest(res: ServerResponse): void { res.writeHead(200); res.end(); } /** * Validates API key based on server environment * @param apiKey The API key to validate * @param serverUrl The server URL to determine environment * @returns void - throws error if validation fails */ export function validateApiKey(apiKey: string | undefined, serverUrl?: string): void { const isLocalServer = serverUrl && serverUrl.includes("localhost"); if (isLocalServer) { logger.info(`Using local server: ${serverUrl}`); // For local server, allow test API keys or skip validation if (!apiKey || apiKey === "local") { logger.info("Using test API key for local development"); } } else { // Validate API key for production if (!apiKey) { throw new Error("API key is required for production use"); } } }

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/livelifelively/context-engine-mcp'

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