/** * Tests for DashCaddy MCP Server — direct handler testing * * Instead of spawning the server process, we test the message handler * logic directly by loading the handler module. */ // We'll test the protocol handler logic directly // by extracting and testing the response shapes describe('DashCaddy MCP Server Tools', () => { // Load the MCP server source and extract tool definitions const fs = require('fs'); const path = require('path'); const mcpSource = fs.readFileSync( path.join(__dirname, '..', '..', 'src', 'mcp', 'mcp-server.js'), 'utf8' ); // Extract tool names from the source const toolNames = [...mcpSource.matchAll(/name: '(dashcaddy_[^']+)'/g)].map(m => m[1]); test('defines at least 15 tools', () => { expect(toolNames.length).toBeGreaterThanOrEqual(15); }); test('includes core service management tools', () => { expect(toolNames).toContain('dashcaddy_list_services'); expect(toolNames).toContain('dashcaddy_get_service'); expect(toolNames).toContain('dashcaddy_check_health'); expect(toolNames).toContain('dashcaddy_container_action'); }); test('includes deployment and catalog tools', () => { expect(toolNames).toContain('dashcaddy_deploy_app'); expect(toolNames).toContain('dashcaddy_search_catalog'); expect(toolNames).toContain('dashcaddy_discover_services'); expect(toolNames).toContain('dashcaddy_wizard_recommend'); }); test('includes system tools', () => { expect(toolNames).toContain('dashcaddy_system_health'); expect(toolNames).toContain('dashcaddy_system_metrics'); expect(toolNames).toContain('dashcaddy_diagnose'); }); test('includes DNS and proxy tools', () => { expect(toolNames).toContain('dashcaddy_list_dns'); expect(toolNames).toContain('dashcaddy_generate_caddyfile'); }); test('includes backup and fleet tools', () => { expect(toolNames).toContain('dashcaddy_create_backup'); expect(toolNames).toContain('dashcaddy_get_backup_status'); expect(toolNames).toContain('dashcaddy_list_fleet'); }); test('each tool has description and inputSchema in source', () => { // Verify the TOOLS array structure by checking patterns in source expect(mcpSource).toContain('inputSchema'); expect(mcpSource).toContain('description:'); expect(mcpSource).toContain('required:'); }); test('deploy_app requires templateId parameter', () => { const deploySection = mcpSource.substring( mcpSource.indexOf("name: 'dashcaddy_deploy_app'"), mcpSource.indexOf("name: 'dashcaddy_deploy_app'") + 1000 ); expect(deploySection).toContain('templateId'); expect(deploySection).toContain('required'); }); test('MCP protocol version is 2024-11-05', () => { expect(mcpSource).toContain('2024-11-05'); }); test('server identifies as dashcaddy', () => { expect(mcpSource).toContain("'dashcaddy'"); expect(mcpSource).toContain('1.15.0'); }); test('uses JSON-RPC 2.0', () => { expect(mcpSource).toContain('jsonrpc'); expect(mcpSource).toContain("'2.0'"); }); test('supports stdio transport', () => { expect(mcpSource).toContain('readline'); expect(mcpSource).toContain('process.stdin'); expect(mcpSource).toContain('process.stdout'); }); test('includes all MCP methods (initialize, tools/list, tools/call)', () => { expect(mcpSource).toContain("case 'initialize'"); expect(mcpSource).toContain("case 'tools/list'"); expect(mcpSource).toContain("case 'tools/call'"); expect(mcpSource).toContain("case 'resources/list'"); expect(mcpSource).toContain("case 'ping'"); }); test('has error handling for unknown methods', () => { expect(mcpSource).toContain('-32601'); expect(mcpSource).toContain('Method not found'); }); });