Skip to main content
Glama

firewalla-mcp-server

unified-response.test.ts8.66 kB
/** * Tests for Unified Response Format */ import { createSuccessResponse, createErrorResponse, toToolResponse, isUnifiedResponse, withUnifiedResponse, type UnifiedResponse, } from '../../src/utils/unified-response.js'; describe('Unified Response Format', () => { describe('createSuccessResponse', () => { it('should create a proper success response', () => { const data = { message: 'Hello, world!' }; const response = createSuccessResponse(data, 'test-tool'); expect(response.success).toBe(true); expect(response.data).toEqual(data); expect(response.meta.tool).toBe('test-tool'); expect(response.meta.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/); expect(response.meta.request_id).toMatch(/^req_/); expect(response.error).toBeUndefined(); }); it('should include count for array data', () => { const data = [1, 2, 3]; const response = createSuccessResponse(data, 'test-tool'); expect(response.meta.count).toBe(3); }); it('should include execution time when provided', () => { const data = { test: true }; const response = createSuccessResponse(data, 'test-tool', { executionTimeMs: 123, }); expect(response.meta.execution_time_ms).toBe(123); }); }); describe('createErrorResponse', () => { it('should create a proper error response', () => { const error = 'Something went wrong'; const response = createErrorResponse(error, 'test-tool'); expect(response.success).toBe(false); expect(response.error).toBe(error); expect(response.meta.tool).toBe('test-tool'); expect(response.meta.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/); expect(response.meta.request_id).toMatch(/^req_/); expect(response.data).toBeUndefined(); }); }); describe('toToolResponse', () => { it('should convert unified success response to ToolResponse', () => { const unifiedResponse = createSuccessResponse({ test: true }, 'test-tool'); const toolResponse = toToolResponse(unifiedResponse); expect(toolResponse.content).toHaveLength(1); expect(toolResponse.content[0].type).toBe('text'); expect(toolResponse.isError).toBe(false); const parsedContent = JSON.parse(toolResponse.content[0].text); expect(parsedContent.success).toBe(true); expect(parsedContent.data.test).toBe(true); }); it('should convert unified error response to ToolResponse', () => { const unifiedResponse = createErrorResponse('Error message', 'test-tool'); const toolResponse = toToolResponse(unifiedResponse); expect(toolResponse.content).toHaveLength(1); expect(toolResponse.content[0].type).toBe('text'); expect(toolResponse.isError).toBe(true); const parsedContent = JSON.parse(toolResponse.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('Error message'); }); }); describe('isUnifiedResponse', () => { it('should identify valid unified responses', () => { const response = createSuccessResponse({ test: true }, 'test-tool'); expect(isUnifiedResponse(response)).toBe(true); }); it('should reject invalid objects', () => { expect(isUnifiedResponse({})).toBe(false); expect(isUnifiedResponse({ success: true })).toBe(false); expect(isUnifiedResponse(null)).toBe(false); expect(isUnifiedResponse('string')).toBe(false); expect(isUnifiedResponse(undefined)).toBe(false); }); }); describe('withUnifiedResponse wrapper', () => { it('should wrap a successful handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: JSON.stringify({ result: 'success' }) }], isError: false, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(false); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(true); expect(parsedContent.data.result).toBe('success'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should wrap an error handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: JSON.stringify({ message: 'Error occurred' }) }], isError: true, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(true); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('Error occurred'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle thrown exceptions', async () => { const mockHandler = jest.fn().mockRejectedValue(new Error('Handler threw error')); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(true); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('Handler threw error'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle non-JSON error text from handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: 'This is not JSON' }], isError: true, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(true); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('This is not JSON'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle non-string error content from handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: 12345 }], // Non-string content isError: true, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(true); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('Unknown error'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle non-JSON success text from handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: 'Plain text response' }], isError: false, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(false); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(true); expect(parsedContent.data).toBe('Plain text response'); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle non-string success content from handler', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: { nested: 'object' } }], // Non-string content isError: false, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(false); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(true); expect(parsedContent.data).toEqual({ nested: 'object' }); expect(parsedContent.meta.tool).toBe('test-tool'); }); it('should handle missing error field in parsed error', async () => { const mockHandler = jest.fn().mockResolvedValue({ content: [{ type: 'text', text: JSON.stringify({ someField: 'value' }) }], // No message or error field isError: true, }); const wrappedHandler = withUnifiedResponse(mockHandler, 'test-tool'); const result = await wrappedHandler(); expect(result.isError).toBe(true); const parsedContent = JSON.parse(result.content[0].text); expect(parsedContent.success).toBe(false); expect(parsedContent.error).toBe('Unknown error'); expect(parsedContent.meta.tool).toBe('test-tool'); }); }); });

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/amittell/firewalla-mcp-server'

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