UNPKG

context-engine

Version:

ContextEngine MCP Server - Up-to-date documentation and code examples for any library

100 lines (99 loc) 3.42 kB
import { logger } from "./logger.js"; /** * Extracts client IP from request headers */ export function getClientIp(req) { 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) { if (!value) return undefined; return typeof value === "string" ? value : value[0]; } /** * Extracts Authorization header and removes Bearer prefix if present */ export function extractBearerToken(authHeader) { 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) { 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) { 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, statusCode, message) { res.writeHead(statusCode); res.end(message); } /** * Handles preflight OPTIONS requests */ export function handlePreflightRequest(res) { 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, serverUrl) { 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"); } } }