Skip to main content
Glama
amineremache

Daft.ie MCP Server

by amineremache
server.test.ts6.83 kB
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { startServer } from '../server.js'; import * as daftScraperService from '../services/daftScraper.service.js'; import * as daftApiService from '../services/daftApi.service.js'; import * as errorUtils from '../utils/error.utils.js'; import * as queryParserService from '../services/queryParser.service.js'; // Mock the entire SDK and services vi.mock('@modelcontextprotocol/sdk/server/mcp.js'); vi.mock('@modelcontextprotocol/sdk/server/sse.js'); vi.mock('../services/daftScraper.service.js'); vi.mock('../services/daftApi.service.js'); vi.mock('../utils/error.utils.js'); vi.mock('../services/queryParser.service.js'); vi.mock('../logger'); describe('Server Setup', () => { let mockServerInstance: McpServer; let mockTransportInstance: SSEServerTransport; beforeEach(() => { vi.resetAllMocks(); // Mock the McpServer and its methods mockServerInstance = { tool: vi.fn(), connect: vi.fn().mockResolvedValue(undefined), } as unknown as McpServer; (McpServer as Mock).mockReturnValue(mockServerInstance); // Mock the SSEServerTransport mockTransportInstance = {} as SSEServerTransport; (SSEServerTransport as Mock).mockReturnValue(mockTransportInstance); }); it('should initialize the McpServer', async () => { await startServer(); expect(McpServer).toHaveBeenCalledWith(expect.objectContaining({ name: 'dafty-mcp' })); }); it('should register all tools', async () => { await startServer(); expect(mockServerInstance.tool).toHaveBeenCalledWith( 'search_rental_properties', expect.any(Object), expect.any(Function) ); expect(mockServerInstance.tool).toHaveBeenCalledWith( 'get_rental_property_details', expect.any(Object), expect.any(Function) ); expect(mockServerInstance.tool).toHaveBeenCalledWith( 'parse_query', expect.any(Object), expect.any(Function) ); expect(mockServerInstance.tool).toHaveBeenCalledTimes(3); }); describe('Tool Handlers', () => { let toolHandlers: Record<string, (extra: Record<string, unknown>) => Promise<unknown>>; beforeEach(async () => { toolHandlers = {}; // Capture the tool handlers by spying on the .tool() method (mockServerInstance.tool as Mock).mockImplementation( (name: string, _: unknown, handler: (extra: Record<string, unknown>) => Promise<unknown>) => { toolHandlers[name] = handler; } ); await startServer(); }); it('should call handleSearchRentalPropertiesScraping for search_rental_properties', async () => { const handlerSpy = vi.spyOn(daftScraperService, 'handleSearchRentalPropertiesScraping'); await toolHandlers.search_rental_properties({ location: 'Dublin' }); expect(handlerSpy).toHaveBeenCalledWith({ location: 'Dublin' }); }); it('should call handleGetRentalPropertyDetailsApi for get_rental_property_details', async () => { const handlerSpy = vi.spyOn(daftApiService, 'handleGetRentalPropertyDetailsApi'); await toolHandlers.get_rental_property_details({ property_id: '123' }); expect(handlerSpy).toHaveBeenCalledWith({ property_id: '123' }); }); it('should call parseQueryWithLLM for parse_query', async () => { const handlerSpy = vi.spyOn(queryParserService, 'parseQueryWithLLM'); await toolHandlers.parse_query({ query: 'find a house' }); expect(handlerSpy).toHaveBeenCalledWith('find a house'); }); }); describe('Tool Error Handling', () => { let toolHandlers: Record<string, (extra: Record<string, unknown>) => Promise<unknown>>; beforeEach(async () => { toolHandlers = {}; (mockServerInstance.tool as Mock).mockImplementation( (name: string, _: unknown, handler: (extra: Record<string, unknown>) => Promise<unknown>) => { toolHandlers[name] = handler; } ); await startServer(); }); // Test cases for search_rental_properties it('search_rental_properties: should create a validation error for invalid input', async () => { const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.search_rental_properties({ location: 123 }); // Invalid type expect(errorSpy).toHaveBeenCalledWith(expect.any(Error), 'search_rental_properties', { location: 123 }); }); it('search_rental_properties: should create an error response on service failure', async () => { const error = new Error('Scraper failed'); vi.spyOn(daftScraperService, 'handleSearchRentalPropertiesScraping').mockRejectedValue(error); const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.search_rental_properties({ location: 'Dublin' }); expect(errorSpy).toHaveBeenCalledWith(error, 'search_rental_properties', { location: 'Dublin' }); }); // Test cases for get_rental_property_details it('get_rental_property_details: should create a validation error for invalid input', async () => { const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.get_rental_property_details({ property_id: 123 }); // Invalid type expect(errorSpy).toHaveBeenCalledWith(expect.any(Error), 'get_rental_property_details', { property_id: 123 }); }); it('get_rental_property_details: should create an error response on service failure', async () => { const error = new Error('API failed'); vi.spyOn(daftApiService, 'handleGetRentalPropertyDetailsApi').mockRejectedValue(error); const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.get_rental_property_details({ property_id: '123' }); expect(errorSpy).toHaveBeenCalledWith(error, 'get_rental_property_details', { property_id: '123' }); }); // Test cases for parse_query it('parse_query: should create a validation error for invalid input', async () => { const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.parse_query({ query: 123 }); // Invalid type expect(errorSpy).toHaveBeenCalledWith(expect.any(Error), 'parse_query', { query: 123 }); }); it('parse_query: should create an error response on service failure', async () => { const error = new Error('LLM failed'); vi.spyOn(queryParserService, 'parseQueryWithLLM').mockRejectedValue(error); const errorSpy = vi.spyOn(errorUtils, 'createErrorResponse'); await toolHandlers.parse_query({ query: 'a query' }); expect(errorSpy).toHaveBeenCalledWith(error, 'parse_query', { query: 'a query' }); }); }); });

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/amineremache/daft-ie-mcp'

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