Skip to main content
Glama

MCP TypeScript Template

httpErrorHandler.ts3.77 kB
/** * @fileoverview Centralized error handler for the Hono HTTP transport. * This middleware intercepts errors that occur during request processing, * standardizes them using the application's ErrorHandler utility, and * formats them into a consistent JSON-RPC error response. * @module src/mcp-server/transports/http/httpErrorHandler */ import type { Context } from 'hono'; import type { StatusCode } from 'hono/utils/http-status'; import type { HonoNodeBindings } from '@/mcp-server/transports/http/httpTypes.js'; import { JsonRpcErrorCode, McpError } from '@/types-global/errors.js'; import { ErrorHandler, logger, requestContextService } from '@/utils/index.js'; /** * A centralized error handling middleware for Hono. * This function is registered with `app.onError()` and will catch any errors * thrown from preceding middleware or route handlers. * * @param err - The error that was thrown. * @param c - The Hono context object for the request. * @returns A Response object containing the formatted JSON-RPC error. */ export const httpErrorHandler = async ( err: Error, c: Context<{ Bindings: HonoNodeBindings }>, ): Promise<Response> => { const context = requestContextService.createRequestContext({ operation: 'httpErrorHandler', additionalContext: { path: c.req.path, method: c.req.method, }, }); logger.debug('HTTP error handler invoked.', context); const handledError = ErrorHandler.handleError(err, { operation: 'httpTransport', context, }); let status: StatusCode = 500; if (handledError instanceof McpError) { switch (handledError.code) { case JsonRpcErrorCode.NotFound: status = 404; break; case JsonRpcErrorCode.Unauthorized: status = 401; break; case JsonRpcErrorCode.Forbidden: status = 403; break; case JsonRpcErrorCode.ValidationError: case JsonRpcErrorCode.InvalidRequest: status = 400; break; case JsonRpcErrorCode.Conflict: status = 409; break; case JsonRpcErrorCode.RateLimited: status = 429; break; default: status = 500; } } logger.debug(`Mapping error to HTTP status ${status}.`, { ...context, status, errorCode: (handledError as McpError).code, }); // Attempt to get the request ID from the body, but don't fail if it's not there or unreadable. let requestId: string | number | null = null; // Only attempt to read the body if it hasn't been consumed already. if (c.req.raw.bodyUsed === false) { try { const body: unknown = await c.req.json(); if (body && typeof body === 'object' && 'id' in body) { const id = (body as Record<string, unknown>).id; requestId = typeof id === 'string' || typeof id === 'number' ? id : null; } else { requestId = null; } logger.debug('Extracted JSON-RPC request ID from body.', { ...context, jsonRpcId: requestId, }); } catch { logger.warning( 'Could not parse request body to extract JSON-RPC ID.', context, ); // Ignore parsing errors, requestId will remain null } } else { logger.debug( 'Request body already consumed, cannot extract JSON-RPC ID.', context, ); } const errorCode = handledError instanceof McpError ? handledError.code : -32603; c.status(status); const errorResponse = { jsonrpc: '2.0', error: { code: errorCode, message: handledError.message, }, id: requestId, }; logger.info(`Sending formatted error response for request.`, { ...context, status, errorCode, jsonRpcId: requestId, }); return c.json(errorResponse); };

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/mintedmaterial/mcp-ts-template'

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