UNPKG

@gorizond/mcp-rancher-multi

Version:

MCP server for multiple Rancher Manager backends with Fleet GitOps support

185 lines (153 loc) 5.96 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { RancherClient } from '../../src/rancher-client.js'; import { RancherServerConfig } from '../../src/utils.js'; // Mock the modules vi.mock('@modelcontextprotocol/sdk/server/mcp.js'); vi.mock('@modelcontextprotocol/sdk/server/stdio.js'); vi.mock('../../src/rancher-client.js'); describe('MCP Server Integration', () => { let mockServer: any; let mockTransport: any; beforeEach(() => { // Reset mocks vi.clearAllMocks(); // Mock McpServer mockServer = { registerTool: vi.fn(), connect: vi.fn() }; (McpServer as any).mockImplementation(() => mockServer); // Mock StdioServerTransport mockTransport = {}; (StdioServerTransport as any).mockImplementation(() => mockTransport); }); afterEach(() => { vi.restoreAllMocks(); }); describe('Server initialization', () => { it('should create server with correct name and version', () => { // Create a new instance to trigger the mock new McpServer({ name: 'test-server', version: '1.0.0' }); expect(McpServer).toHaveBeenCalledWith({ name: 'test-server', version: '1.0.0' }); }); it('should register tools', () => { // Create a new instance to trigger the mock const server = new McpServer({ name: 'test-server', version: '1.0.0' }); // Simulate tool registration mockServer.registerTool('test.tool', {}, () => {}); expect(mockServer.registerTool).toHaveBeenCalled(); }); }); describe('Tool registration', () => { it('should register rancher_servers_list tool', () => { // Simulate tool registration mockServer.registerTool('rancher_servers_list', { title: 'List registered Rancher servers', description: 'Returns known servers from local store', inputSchema: {} }, () => {}); const calls = mockServer.registerTool.mock.calls; const serverListCall = calls.find((call: any) => call[0] === 'rancher_servers_list' ); expect(serverListCall).toBeDefined(); expect(serverListCall[1]).toEqual({ title: 'List registered Rancher servers', description: 'Returns known servers from local store', inputSchema: {} }); }); it('should register rancher_servers_add tool', () => { // Simulate tool registration mockServer.registerTool('rancher_servers_add', { title: 'Add/Update Rancher server', description: 'Register a Rancher Manager for later use', inputSchema: {} }, () => {}); const calls = mockServer.registerTool.mock.calls; const serverAddCall = calls.find((call: any) => call[0] === 'rancher_servers_add' ); expect(serverAddCall).toBeDefined(); expect(serverAddCall[1]).toEqual({ title: 'Add/Update Rancher server', description: 'Register a Rancher Manager for later use', inputSchema: {} }); }); it('should register rancher_clusters_list tool', () => { // Simulate tool registration mockServer.registerTool('rancher_clusters_list', { title: 'List clusters', description: 'Return clusters from selected Rancher server', inputSchema: {} }, () => {}); const calls = mockServer.registerTool.mock.calls; const clustersListCall = calls.find((call: any) => call[0] === 'rancher_clusters_list' ); expect(clustersListCall).toBeDefined(); expect(clustersListCall[1]).toEqual({ title: 'List clusters', description: 'Return clusters from selected Rancher server', inputSchema: {} }); }); }); describe('Tool handlers', () => { it('should handle rancher_servers_list correctly', async () => { // This would test the actual handler function // For now, we'll create a mock implementation const mockHandler = vi.fn().mockResolvedValue({ content: [{ type: 'text', text: '[]' }] }); const result = await mockHandler(); expect(result).toEqual({ content: [{ type: 'text', text: '[]' }] }); }); it('should handle rancher_servers_add correctly', async () => { const mockHandler = vi.fn().mockImplementation(async (args: any) => { return { content: [{ type: 'text', text: JSON.stringify(args, null, 2) }] }; }); const testConfig = { id: 'test-server', baseUrl: 'https://test.local', token: 'test-token' }; const result = await mockHandler(testConfig); expect(result).toEqual({ content: [{ type: 'text', text: JSON.stringify(testConfig, null, 2) }] }); }); }); describe('Error handling', () => { it('should handle missing server gracefully', async () => { const mockHandler = vi.fn().mockImplementation(async ({ serverId }: { serverId: string }) => { if (!serverId) { throw new Error('Server ID is required'); } throw new Error(`Rancher server '${serverId}' not found`); }); await expect(mockHandler({ serverId: 'non-existent' })) .rejects.toThrow("Rancher server 'non-existent' not found"); }); it('should handle invalid server configuration', async () => { const mockHandler = vi.fn().mockImplementation(async (config: any) => { if (!config.baseUrl || !config.token) { throw new Error('Invalid server configuration'); } return { content: [{ type: 'text', text: 'OK' }] }; }); await expect(mockHandler({ id: 'test' })) .rejects.toThrow('Invalid server configuration'); }); }); });