@gorizond/mcp-rancher-multi
Version:
MCP server for multiple Rancher Manager backends with Fleet GitOps support
185 lines (153 loc) • 5.96 kB
text/typescript
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');
});
});
});