Skip to main content
Glama

1MCP Server

errorHandling.test.ts9.28 kB
import { ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { formatErrorResponse, getErrorCause, getErrorCode, getErrorMessage, isMCPError, normalizeError, withErrorHandling, } from './errorHandling.js'; import { InvalidRequestError, MCPError } from './errorTypes.js'; // Mock the logger vi.mock('@src/logger/logger.js', () => ({ default: { error: vi.fn(), }, })); describe('withErrorHandling', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should return successful function result', async () => { const fn = vi.fn().mockResolvedValue('success'); const wrappedFn = withErrorHandling(fn, 'Test operation'); const result = await wrappedFn('arg1', 'arg2'); expect(result).toBe('success'); expect(fn).toHaveBeenCalledWith('arg1', 'arg2'); }); it('should rethrow MCPError as-is', async () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); const fn = vi.fn().mockRejectedValue(mcpError); const wrappedFn = withErrorHandling(fn, 'Test operation'); await expect(wrappedFn()).rejects.toThrow(mcpError); }); it('should convert regular Error to MCPError', async () => { const originalError = new Error('Original error'); const fn = vi.fn().mockRejectedValue(originalError); const wrappedFn = withErrorHandling(fn, 'Test operation'); await expect(wrappedFn()).rejects.toThrow(MCPError); await expect(wrappedFn()).rejects.toThrow('Test operation'); try { await wrappedFn(); } catch (error) { expect(error).toBeInstanceOf(MCPError); expect((error as MCPError).code).toBe(ErrorCode.InternalError); expect((error as MCPError).data?.originalError).toBe(originalError); } }); it('should convert non-Error objects to MCPError', async () => { const fn = vi.fn().mockRejectedValue('string error'); const wrappedFn = withErrorHandling(fn, 'Test operation'); await expect(wrappedFn()).rejects.toThrow(MCPError); await expect(wrappedFn()).rejects.toThrow('Test operation'); try { await wrappedFn(); } catch (error) { expect(error).toBeInstanceOf(MCPError); expect((error as MCPError).data?.originalError).toBeInstanceOf(Error); expect((error as MCPError).data?.originalError.message).toBe('string error'); } }); it('should preserve function arguments and return type', async () => { const fn = vi.fn().mockImplementation((a: string, b: number) => Promise.resolve(a + b)); const wrappedFn = withErrorHandling(fn, 'Test operation'); const result = await wrappedFn('test', 42); expect(result).toBe('test42'); expect(fn).toHaveBeenCalledWith('test', 42); }); }); describe('normalizeError', () => { it('should return MCPError as-is', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); const result = normalizeError(mcpError, 'fallback message'); expect(result).toBe(mcpError); }); it('should convert regular Error to MCPError', () => { const originalError = new Error('Original error'); const result = normalizeError(originalError, 'fallback message'); expect(result).toBeInstanceOf(MCPError); expect(result.message).toBe('Original error'); expect(result.code).toBe(ErrorCode.InternalError); }); it('should use fallback message for Error with empty message', () => { const originalError = new Error(''); const result = normalizeError(originalError, 'fallback message'); expect(result).toBeInstanceOf(MCPError); expect(result.message).toBe('fallback message'); expect(result.code).toBe(ErrorCode.InternalError); }); it('should convert non-Error objects to MCPError', () => { const result = normalizeError('string error', 'fallback message'); expect(result).toBeInstanceOf(MCPError); expect(result.message).toBe('fallback message'); expect(result.code).toBe(ErrorCode.InternalError); }); it('should handle null and undefined', () => { const resultNull = normalizeError(null, 'fallback message'); const resultUndefined = normalizeError(undefined, 'fallback message'); expect(resultNull).toBeInstanceOf(MCPError); expect(resultNull.message).toBe('fallback message'); expect(resultUndefined).toBeInstanceOf(MCPError); expect(resultUndefined.message).toBe('fallback message'); }); }); describe('isMCPError', () => { it('should return true for matching MCP error types', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); const invalidRequestError = new InvalidRequestError('Invalid request'); expect(isMCPError(mcpError, MCPError)).toBe(true); expect(isMCPError(invalidRequestError, InvalidRequestError)).toBe(true); expect(isMCPError(invalidRequestError, MCPError)).toBe(true); }); it('should return false for non-matching error types', () => { const regularError = new Error('Regular error'); const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); expect(isMCPError(regularError, MCPError)).toBe(false); expect(isMCPError(mcpError, InvalidRequestError)).toBe(false); expect(isMCPError('string error', MCPError)).toBe(false); expect(isMCPError(null, MCPError)).toBe(false); }); }); describe('getErrorCode', () => { it('should return code from MCPError', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); expect(getErrorCode(mcpError)).toBe(ErrorCode.InvalidRequest); }); it('should return InternalError for non-MCP errors', () => { const regularError = new Error('Regular error'); expect(getErrorCode(regularError)).toBe(ErrorCode.InternalError); expect(getErrorCode('string error')).toBe(ErrorCode.InternalError); expect(getErrorCode(null)).toBe(ErrorCode.InternalError); }); }); describe('getErrorMessage', () => { it('should return message from Error objects', () => { const error = new Error('Error message'); expect(getErrorMessage(error)).toBe('Error message'); }); it('should return message from MCPError', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); expect(getErrorMessage(mcpError)).toBe('MCP Error'); }); it('should convert non-Error objects to string', () => { expect(getErrorMessage('string error')).toBe('string error'); expect(getErrorMessage(123)).toBe('123'); expect(getErrorMessage(null)).toBe('null'); expect(getErrorMessage(undefined)).toBe('undefined'); expect(getErrorMessage({})).toBe('[object Object]'); }); }); describe('getErrorCause', () => { it('should return cause from Error with cause', () => { const cause = new Error('Cause error'); const error = new Error('Main error', { cause }); expect(getErrorCause(error)).toBe(cause); }); it('should return undefined for Error without cause', () => { const error = new Error('Error without cause'); expect(getErrorCause(error)).toBeUndefined(); }); it('should return undefined for non-Error objects', () => { expect(getErrorCause('string error')).toBeUndefined(); expect(getErrorCause(null)).toBeUndefined(); expect(getErrorCause({})).toBeUndefined(); }); it('should handle Error with non-Error cause', () => { const error = new Error('Main error'); (error as any).cause = 'string cause'; expect(getErrorCause(error)).toBe('string cause'); }); }); describe('formatErrorResponse', () => { it('should format MCPError correctly', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest, { extra: 'data' }); const result = formatErrorResponse(mcpError); expect(result).toEqual({ code: ErrorCode.InvalidRequest, message: 'MCP Error', data: { extra: 'data' }, }); }); it('should format MCPError without data', () => { const mcpError = new MCPError('MCP Error', ErrorCode.InvalidRequest); const result = formatErrorResponse(mcpError); expect(result).toEqual({ code: ErrorCode.InvalidRequest, message: 'MCP Error', data: undefined, }); }); it('should format regular Error as internal error', () => { const error = new Error('Regular error'); const result = formatErrorResponse(error); expect(result).toEqual({ code: ErrorCode.InternalError, message: 'Regular error', }); }); it('should format non-Error objects as internal error', () => { const result = formatErrorResponse('string error'); expect(result).toEqual({ code: ErrorCode.InternalError, message: 'string error', }); }); it('should handle null and undefined', () => { const resultNull = formatErrorResponse(null); const resultUndefined = formatErrorResponse(undefined); expect(resultNull).toEqual({ code: ErrorCode.InternalError, message: 'null', }); expect(resultUndefined).toEqual({ code: ErrorCode.InternalError, message: 'undefined', }); }); it('should handle objects', () => { const result = formatErrorResponse({ error: 'custom error' }); expect(result).toEqual({ code: ErrorCode.InternalError, message: '[object Object]', }); }); });

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/1mcp-app/agent'

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