Skip to main content
Glama

Mailgun MCP Server

Official
by mailgun
mailgun-mcp.test.js7.92 kB
import { jest } from '@jest/globals'; import * as serverModule from '../src/mailgun-mcp.js'; // Disable console.error during tests const originalConsoleError = console.error; console.error = jest.fn(); // Override process.exit during tests const originalProcessExit = process.exit; process.exit = jest.fn(); describe('Mailgun MCP Server', () => { // Focus on testing the pure utility functions that don't need mocks describe('processPathParameters()', () => { test('replaces path parameters with values', () => { const path = '/v3/{domain_name}/messages'; const operation = { parameters: [ { name: 'domain_name', in: 'path', required: true } ] }; const params = { domain_name: 'example.com', to: 'test@example.com' }; const result = serverModule.processPathParameters(path, operation, params); expect(result.actualPath).toBe('/v3/example.com/messages'); expect(result.remainingParams).toEqual({ to: 'test@example.com' }); }); test('throws error if required path parameter is missing', () => { const path = '/v3/{domain_name}/messages'; const operation = { parameters: [ { name: 'domain_name', in: 'path', required: true } ] }; const params = { to: 'test@example.com' }; expect(() => { serverModule.processPathParameters(path, operation, params); }).toThrow(/required path parameter.*missing/i); }); }); describe('separateParameters()', () => { test('separates query and body parameters', () => { const params = { limit: 10, page: 1, to: 'test@example.com', from: 'sender@example.com' }; const operation = { parameters: [ { name: 'limit', in: 'query' }, { name: 'page', in: 'query' } ] }; const result = serverModule.separateParameters(params, operation, 'POST'); expect(result.queryParams).toEqual({ limit: 10, page: 1 }); expect(result.bodyParams).toEqual({ to: 'test@example.com', from: 'sender@example.com' }); }); test('moves all params to query for GET requests', () => { const params = { limit: 10, page: 1, to: 'test@example.com', from: 'sender@example.com' }; const operation = { parameters: [ { name: 'limit', in: 'query' }, { name: 'page', in: 'query' } ] }; const result = serverModule.separateParameters(params, operation, 'GET'); expect(result.queryParams).toEqual({ limit: 10, page: 1, to: 'test@example.com', from: 'sender@example.com' }); expect(result.bodyParams).toEqual({}); }); }); describe('appendQueryString()', () => { test('appends query parameters to path', () => { const path = '/v3/domains'; const queryParams = { limit: 10, skip: 0 }; const result = serverModule.appendQueryString(path, queryParams); expect(result).toBe('/v3/domains?limit=10&skip=0'); }); test('returns original path if no query parameters', () => { const path = '/v3/domains'; const queryParams = {}; const result = serverModule.appendQueryString(path, queryParams); expect(result).toBe('/v3/domains'); }); }); // Clean up after all tests afterAll(() => { console.error = originalConsoleError; process.exit = originalProcessExit; }); }); describe('openapiToZod()', () => { test('converts string schema correctly', () => { const schema = { type: 'string', description: 'A test string' }; const result = serverModule.openapiToZod(schema, {}); expect(result._def.typeName).toBe('ZodString'); expect(result._def.description).toBe('A test string'); }); test('converts enum schema correctly', () => { const schema = { type: 'string', enum: ['yes', 'no', 'maybe'] }; const result = serverModule.openapiToZod(schema, {}); expect(result._def.typeName).toBe('ZodEnum'); expect(result._def.values).toEqual(['yes', 'no', 'maybe']); }); test('converts number schema with constraints', () => { const schema = { type: 'number', minimum: 1, maximum: 100, description: 'A constrained number' }; const result = serverModule.openapiToZod(schema, {}); expect(result._def.typeName).toBe('ZodNumber'); // Check for min constraint expect(result._def.checks.some(check => check.kind === 'min' && check.value === 1 )).toBe(true); // Check for max constraint expect(result._def.checks.some(check => check.kind === 'max' && check.value === 100 )).toBe(true); }); test('resolves references correctly', () => { const schema = { $ref: '#/components/schemas/TestType' }; const fullSpec = { components: { schemas: { TestType: { type: 'string', description: 'Referenced type' } } } }; const result = serverModule.openapiToZod(schema, fullSpec); expect(result._def.typeName).toBe('ZodString'); expect(result._def.description).toBe('Referenced type'); }); }); describe('getOperationDetails()', () => { test('returns operation details for valid path and method', () => { const openApiSpec = { paths: { '/test/path': { get: { operationId: 'getTest', summary: 'Test operation' } } } }; const result = serverModule.getOperationDetails(openApiSpec, 'get', '/test/path'); expect(result).toEqual({ operation: { operationId: 'getTest', summary: 'Test operation' }, operationId: 'get--test-path' }); }); test('returns null for invalid path', () => { const openApiSpec = { paths: { '/test/path': { get: { operationId: 'getTest', summary: 'Test operation' } } } }; const result = serverModule.getOperationDetails(openApiSpec, 'get', '/nonexistent/path'); expect(result).toBeNull(); }); test('returns null for invalid method', () => { const openApiSpec = { paths: { '/test/path': { get: { operationId: 'getTest', summary: 'Test operation' } } } }; const result = serverModule.getOperationDetails(openApiSpec, 'post', '/test/path'); expect(result).toBeNull(); }); }); describe('resolveReference()', () => { test('resolves reference path correctly', () => { const openApiSpec = { components: { schemas: { TestSchema: { type: 'string', description: 'Test schema' } } } }; const result = serverModule.resolveReference('#/components/schemas/TestSchema', openApiSpec); expect(result).toEqual({ type: 'string', description: 'Test schema' }); }); test('handles nested reference path', () => { const openApiSpec = { components: { schemas: { Parent: { NestedType: { type: 'number', minimum: 0 } } } } }; const result = serverModule.resolveReference('#/components/schemas/Parent/NestedType', openApiSpec); expect(result).toEqual({ type: 'number', minimum: 0 }); }); });

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

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