context-engine
Version:
ContextEngine MCP Server - Up-to-date documentation and code examples for any library
100 lines (99 loc) • 3.42 kB
JavaScript
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");
}
}
}