Skip to main content
Glama
protocol.ts3.26 kB
/** * Protocol Bridge * Translates between HTTP and JSON-RPC for MCP * Zero-fallback: protocol errors fail fast with proper status codes */ import { Request, Response } from "express"; import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js"; import { HTTPRequestContext } from "./types.js"; export class ProtocolBridge { /** * Analyze HTTP request context for MCP protocol handling */ analyzeRequest(req: Request): HTTPRequestContext { const sessionId = req.headers['mcp-session-id'] as string | undefined; const isInitialize = req.method === 'POST' && isInitializeRequest(req.body); const method = req.method as 'GET' | 'POST' | 'DELETE'; return { sessionId, isInitialize, method }; } /** * Set proper HTTP headers for MCP responses */ setMCPHeaders(res: Response, sessionId?: string): void { res.setHeader('Content-Type', 'application/json'); res.setHeader('Access-Control-Allow-Origin', process.env.CORS_ORIGIN || '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept, Mcp-Session-Id, Last-Event-ID'); res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id'); if (sessionId) { res.setHeader('Mcp-Session-Id', sessionId); } } /** * Send JSON-RPC error response with proper HTTP status */ sendError(res: Response, statusCode: number, message: string, id?: string | number): void { this.setMCPHeaders(res); res.status(statusCode).json({ jsonrpc: "2.0", id: id || null, error: { code: this.mapHttpToJsonRpcError(statusCode), message, data: { httpStatusCode: statusCode } } }); } /** * Send successful JSON-RPC response */ sendSuccess(res: Response, result: any, id?: string | number, sessionId?: string): void { this.setMCPHeaders(res, sessionId); res.status(200).json({ jsonrpc: "2.0", id: id || null, result }); } /** * Validate JSON-RPC message structure */ validateJsonRpc(body: any): { valid: boolean; id?: string | number; error?: string } { if (!body || typeof body !== 'object') { return { valid: false, error: 'Invalid JSON structure' }; } if (body.jsonrpc !== '2.0') { return { valid: false, id: body.id, error: 'Invalid JSON-RPC version' }; } if (!body.method && !body.result && !body.error) { return { valid: false, id: body.id, error: 'Invalid JSON-RPC message type' }; } return { valid: true, id: body.id }; } /** * Map HTTP status codes to JSON-RPC error codes */ private mapHttpToJsonRpcError(httpStatus: number): number { switch (httpStatus) { case 400: return -32600; // Invalid Request case 404: return -32601; // Method not found case 405: return -32601; // Method not found case 422: return -32602; // Invalid params case 500: return -32603; // Internal error default: return -32000; // Server error } } /** * Handle CORS preflight requests */ handleCorsPrelight(_req: Request, res: Response): void { this.setMCPHeaders(res); res.status(200).send(); } }

Latest Blog Posts

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/sylweriusz/mcp-neo4j-memory-server'

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