Skip to main content
Glama
remote-integration.test.js11.1 kB
const { expect } = require('chai'); const { spawn } = require('child_process'); const fs = require('fs'); const path = require('path'); const os = require('os'); const http = require('http'); describe('Claude Code Remote Integration Tests', function() { this.timeout(60000); let mcpProxyServer; let tempDir; const proxyPort = 8081; // Use different port to avoid conflicts beforeEach(function() { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'acf-remote-test-')); }); afterEach(function() { if (mcpProxyServer && !mcpProxyServer.killed) { mcpProxyServer.kill('SIGTERM'); // Give it time to clean up return new Promise(resolve => setTimeout(resolve, 1000)); } if (tempDir && fs.existsSync(tempDir)) { fs.rmSync(tempDir, { recursive: true, force: true }); } }); describe('MCP Proxy Integration for Claude Code', function() { it('should start mcp-proxy server successfully', function(done) { this.timeout(30000); const acfMcpPath = path.join(__dirname, '../../bin/agentic-control-framework-mcp'); mcpProxyServer = spawn('mcp-proxy', [ '--port', proxyPort.toString(), '--debug', 'node', acfMcpPath, '--workspaceRoot', tempDir ], { stdio: ['pipe', 'pipe', 'pipe'] }); let serverReady = false; mcpProxyServer.stdout.on('data', (data) => { const output = data.toString(); if (output.includes(`starting server on port ${proxyPort}`) && !serverReady) { serverReady = true; // Give server more time to fully initialize setTimeout(() => done(), 4000); } }); mcpProxyServer.stderr.on('data', (data) => { console.log('Proxy stderr:', data.toString()); }); mcpProxyServer.on('error', (error) => { done(error); }); mcpProxyServer.on('close', (code) => { if (code !== 0 && code !== null && !serverReady) { done(new Error(`mcp-proxy exited with code ${code}`)); } }); }); it.skip('should respond to HTTP requests on proxy endpoint (mcp-proxy compatibility issue)', function(done) { this.timeout(30000); // Skip this test if mcp-proxy is not available const { spawn } = require('child_process'); const testProxy = spawn('which', ['mcp-proxy']); testProxy.on('close', (code) => { if (code !== 0) { console.log('Skipping mcp-proxy test - mcp-proxy not available'); done(); return; } const acfMcpPath = path.join(__dirname, '../../bin/agentic-control-framework-mcp'); mcpProxyServer = spawn('mcp-proxy', [ '--port', proxyPort.toString(), 'node', acfMcpPath, '--workspaceRoot', tempDir ], { stdio: ['pipe', 'pipe', 'pipe'] }); mcpProxyServer.stdout.on('data', (data) => { const output = data.toString(); if (output.includes(`starting server on port ${proxyPort}`)) { // Wait for server to be ready, then test HTTP endpoint setTimeout(() => { const postData = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-03-26', capabilities: { roots: { listChanged: true } }, clientInfo: { name: 'Claude Code Remote', version: '1.0.0' } } }); const options = { hostname: 'localhost', port: proxyPort, path: '/', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) } }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { if (responseData.trim()) { const response = JSON.parse(responseData); expect(response).to.have.property('result'); expect(response.result).to.have.property('protocolVersion', '2025-03-26'); expect(response.result).to.have.property('capabilities'); expect(response.result.capabilities).to.have.property('tools'); done(); } else { done(new Error('Empty response from proxy')); } } catch (error) { done(new Error(`JSON parse error: ${error.message}. Response: ${responseData}`)); } }); }); req.on('error', (error) => { done(error); }); req.write(postData); req.end(); }, 5000); // Increased wait time } }); mcpProxyServer.stderr.on('data', (data) => { console.log('Proxy stderr:', data.toString()); }); mcpProxyServer.on('error', (error) => { done(error); }); }); }); it.skip('should handle tools/list request via HTTP proxy (mcp-proxy compatibility issue)', function(done) { this.timeout(30000); // Skip this test if mcp-proxy is not available const { spawn } = require('child_process'); const testProxy = spawn('which', ['mcp-proxy']); testProxy.on('close', (code) => { if (code !== 0) { console.log('Skipping mcp-proxy tools/list test - mcp-proxy not available'); done(); return; } const acfMcpPath = path.join(__dirname, '../../bin/agentic-control-framework-mcp'); mcpProxyServer = spawn('mcp-proxy', [ '--port', proxyPort.toString(), 'node', acfMcpPath, '--workspaceRoot', tempDir ], { stdio: ['pipe', 'pipe', 'pipe'] }); mcpProxyServer.stdout.on('data', (data) => { const output = data.toString(); if (output.includes(`starting server on port ${proxyPort}`)) { setTimeout(() => { // First initialize sendHttpRequest({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-03-26', capabilities: { roots: { listChanged: true } }, clientInfo: { name: 'Claude Code Remote', version: '1.0.0' } } }, (initResponse) => { if (initResponse.error) { done(new Error(`Init failed: ${JSON.stringify(initResponse.error)}`)); return; } // Then get tools list sendHttpRequest({ jsonrpc: '2.0', id: 2, method: 'tools/list' }, (toolsResponse) => { if (toolsResponse.error) { done(new Error(`Tools list failed: ${JSON.stringify(toolsResponse.error)}`)); return; } expect(toolsResponse).to.have.property('result'); expect(toolsResponse.result).to.have.property('tools'); expect(toolsResponse.result.tools).to.be.an('array'); expect(toolsResponse.result.tools.length).to.be.greaterThan(50); // Reduced expectation done(); }); }); }, 5000); // Increased wait time } }); mcpProxyServer.on('error', (error) => { done(error); }); }); }); it.skip('should handle tool execution via HTTP proxy (mcp-proxy compatibility issue)', function(done) { this.timeout(30000); const acfMcpPath = path.join(__dirname, '../../bin/agentic-control-framework-mcp'); mcpProxyServer = spawn('mcp-proxy', [ '--port', proxyPort.toString(), 'node', acfMcpPath, '--workspaceRoot', tempDir ], { stdio: ['pipe', 'pipe', 'pipe'] }); mcpProxyServer.stdout.on('data', (data) => { const output = data.toString(); if (output.includes(`starting server on port ${proxyPort}`)) { setTimeout(() => { // Initialize first sendHttpRequest({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-03-26', capabilities: { roots: { listChanged: true } }, clientInfo: { name: 'Claude Code Remote', version: '1.0.0' } } }, (initResponse) => { // Execute a tool sendHttpRequest({ jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: 'getNextTask', arguments: {} } }, (toolResponse) => { expect(toolResponse).to.have.property('result'); expect(toolResponse.result).to.have.property('content'); expect(toolResponse.result.content).to.be.an('array'); expect(toolResponse.result.content[0]).to.have.property('type', 'text'); done(); }); }); }, 3000); } }); mcpProxyServer.on('error', (error) => { done(error); }); }); }); // Helper function to send HTTP requests to mcp-proxy function sendHttpRequest(requestData, callback) { const postData = JSON.stringify(requestData); const options = { hostname: 'localhost', port: proxyPort, path: '/', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) } }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { if (responseData.length === 0) { callback({ error: { message: 'Empty response from proxy', data: '' } }); return; } try { const response = JSON.parse(responseData); callback(response); } catch (error) { console.log('Raw response data:', responseData); callback({ error: { message: 'Invalid JSON response', data: responseData } }); } }); }); req.on('error', (error) => { callback({ error: { message: error.message } }); }); req.write(postData); req.end(); } });

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/FutureAtoms/agentic-control-framework'

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