Skip to main content
Glama
terminal-protocol-mismatch-critical-bug.test.ts5.81 kB
/** * CRITICAL BUG REPRODUCTION TEST * * This test reproduces the exact protocol mismatch that breaks all terminal functionality. * The TypeScript source sends 'data: command + \r' but server expects 'command: command'. * This causes "Command is required and must be a string" errors. */ import { MCPServerManager } from './integration/terminal-history-framework/mcp-server-manager'; import { MCPClient } from './integration/terminal-history-framework/mcp-client'; import WebSocket from 'ws'; describe('CRITICAL: Terminal Protocol Mismatch Bug', () => { let mcpServerManager: MCPServerManager; let mcpClient: MCPClient; beforeEach(async () => { mcpServerManager = new MCPServerManager(); // Start MCP server await mcpServerManager.start(); const processInfo = mcpServerManager.getProcess(); if (!processInfo || !processInfo.stdin || !processInfo.stdout) { throw new Error('Failed to start MCP server for testing'); } mcpClient = new MCPClient({ stdin: processInfo.stdin, stdout: processInfo.stdout } as any); }); afterEach(async () => { if (mcpServerManager) { await mcpServerManager.stop(); } }); it('REPRODUCES CRITICAL BUG: TypeScript sends wrong message format causing server rejection', async () => { // This test reproduces the exact server error that occurs when TypeScript // sends { data: command + '\r' } but server expects { command: command } // Set up SSH session const sessionName = 'protocol-test'; await mcpClient.callTool('ssh_connect', { name: sessionName, host: 'localhost', username: 'jsbattig', keyFilePath: '~/.ssh/id_ed25519' }); // Get monitoring URL const monitoringResponse = await mcpClient.callTool('ssh_get_monitoring_url', { sessionName: sessionName }) as any; expect(monitoringResponse.success).toBe(true); expect(monitoringResponse.monitoringUrl).toBeDefined(); // Convert monitoring URL to WebSocket URL // http://localhost:8083/session/test-session -> ws://localhost:8083/ws/session/test-session const httpUrl = monitoringResponse.monitoringUrl as string; const wsUrl = httpUrl.replace('http://', 'ws://').replace('/session/', '/ws/session/'); // Connect to WebSocket const ws = new WebSocket(wsUrl); await new Promise((resolve, reject) => { ws.on('open', resolve); ws.on('error', reject); }); let serverResponse: string | null = null; // Listen for server response ws.on('message', (data: Buffer) => { serverResponse = data.toString(); }); // Send message in WRONG format (reproduces current TypeScript bug) const wrongFormatMessage = { type: 'terminal_input', sessionName: sessionName, data: 'pwd' + '\r', // ❌ WRONG: server doesn't expect 'data' field commandId: 'test_cmd_001', timestamp: new Date().toISOString() }; ws.send(JSON.stringify(wrongFormatMessage)); // Wait for server response await new Promise(resolve => setTimeout(resolve, 1000)); // Verify we get the exact error that breaks terminal functionality expect(serverResponse).toBeDefined(); const response = JSON.parse(serverResponse!); expect(response.type).toBe('error'); expect(response.message).toBe('Command is required and must be a string'); // This proves the terminal is COMPLETELY BROKEN due to protocol mismatch console.log('CRITICAL BUG REPRODUCED: Server rejects TypeScript message format'); ws.close(); // Cleanup session await mcpClient.callTool('ssh_disconnect', { sessionName }); }); it('VERIFIES FIX: Correct message format should work', async () => { // This test will pass ONLY after TypeScript source is fixed // Set up SSH session const sessionName = 'protocol-test-2'; await mcpClient.callTool('ssh_connect', { name: sessionName, host: 'localhost', username: 'jsbattig', keyFilePath: '~/.ssh/id_ed25519' }); // Get monitoring URL const monitoringResponse = await mcpClient.callTool('ssh_get_monitoring_url', { sessionName: sessionName }) as any; expect(monitoringResponse.success).toBe(true); const httpUrl = monitoringResponse.monitoringUrl as string; const wsUrl = httpUrl.replace('http://', 'ws://').replace('/session/', '/ws/session/'); // Connect to WebSocket const ws = new WebSocket(wsUrl); await new Promise((resolve, reject) => { ws.on('open', resolve); ws.on('error', reject); }); let serverResponse: string | null = null; ws.on('message', (data: Buffer) => { serverResponse = data.toString(); }); // Send message in CORRECT format (how it should be) const correctFormatMessage = { type: 'terminal_input', sessionName: sessionName, command: 'pwd', // ✅ CORRECT: server expects 'command' field commandId: 'test_cmd_002', timestamp: new Date().toISOString() }; ws.send(JSON.stringify(correctFormatMessage)); // Wait for server response await new Promise(resolve => setTimeout(resolve, 2000)); // Verify command executes successfully (no error response) if (serverResponse) { const response = JSON.parse(serverResponse); expect(response.type).not.toBe('error'); // Should get terminal_ready or terminal_output (both indicate successful protocol) expect(response.type).toMatch(/^(terminal_output|terminal_ready)$/); console.log('SUCCESS: Protocol fix works! Received:', response.type); } ws.close(); // Cleanup session await mcpClient.callTool('ssh_disconnect', { sessionName }); }); });

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/LightspeedDMS/ssh-mcp'

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