Skip to main content
Glama

SpiderFoot MCP Server

final-mcp-client.js7.26 kB
// Final MCP Client with proper SSE and JSON handling import http from 'http'; class FinalMCPClient { constructor() { this.sessionId = null; this.requestId = 1; this.hostname = 'localhost'; this.port = 5002; this.path = '/mcp'; } async request(method, params = {}) { return new Promise((resolve, reject) => { const postData = JSON.stringify({ jsonrpc: '2.0', method: method, params: params, id: this.requestId++ }); const options = { hostname: this.hostname, port: this.port, path: this.path, method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json, text/event-stream', 'Content-Length': Buffer.byteLength(postData), 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Accept-Encoding': 'identity' // Disable compression for SSE } }; // Add session ID if available (except for initialize) if (this.sessionId && method !== 'initialize') { options.headers['mcp-session-id'] = this.sessionId; } console.log(`\n=== Request: ${method} ===`); console.log('Headers:', options.headers); console.log('Body:', postData); const req = http.request(options, (res) => { console.log(`\n=== Response: ${res.statusCode} ===`); console.log('Headers:', JSON.stringify(res.headers, null, 2)); // Save session ID from response headers (case-insensitive) const sessionHeader = Object.entries(res.headers).find( ([key]) => key.toLowerCase() === 'mcp-session-id' ); if (sessionHeader && sessionHeader[1]) { this.sessionId = sessionHeader[1]; console.log('Session ID:', this.sessionId); } let buffer = ''; const results = []; let isSSE = res.headers['content-type']?.includes('text/event-stream'); res.on('data', (chunk) => { const chunkStr = chunk.toString(); buffer += chunkStr; if (isSSE) { // Process SSE format: event: message\n // data: {json_data_here} const lines = buffer.split('\n'); buffer = lines.pop() || ''; for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (line.startsWith('data: ')) { const dataStr = line.substring(5).trim(); if (dataStr) { try { const data = JSON.parse(dataStr); results.push(data); console.log('SSE Data:', JSON.stringify(data, null, 2)); } catch (e) { console.error('Error parsing SSE data:', e); console.error('Problematic data:', dataStr); } } } } } }); res.on('end', () => { if (buffer.trim()) { try { if (isSSE) { // Try to parse any remaining data as SSE const lines = buffer.split('\n'); for (const line of lines) { const trimmed = line.trim(); if (trimmed.startsWith('data: ')) { const dataStr = trimmed.substring(5).trim(); if (dataStr) { const data = JSON.parse(dataStr); results.push(data); console.log('SSE Data (end):', JSON.stringify(data, null, 2)); } } } } else { // Try to parse as JSON const data = JSON.parse(buffer); results.push(data); console.log('JSON Data:', JSON.stringify(data, null, 2)); } } catch (e) { console.error('Error parsing final buffer:', e); console.error('Buffer content:', buffer); } } if (res.statusCode >= 400) { const error = new Error(`Request failed with status code ${res.statusCode}`); error.statusCode = res.statusCode; error.headers = res.headers; error.data = results[0] || null; reject(error); } else { // For initialization, we expect a single result // For other requests, return all results const result = method === 'initialize' ? results[0] : results; resolve({ statusCode: res.statusCode, headers: res.headers, data: result }); } }); }); req.on('error', (error) => { console.error('Request error:', error); reject(error); }); // Write data to request body req.write(postData); req.end(); }); } async initialize() { console.log('Initializing MCP client...'); const response = await this.request('initialize', { protocolVersion: '1.0', clientInfo: { name: 'final-mcp-client', version: '1.0.0' }, capabilities: {} }); console.log('Initialization successful'); return response; } async listTools() { return this.request('mcp.list_tools', {}); } async ping() { return this.request('spiderfoot_ping', {}); } async listScans() { return this.request('spiderfoot_scans', {}); } async startScan(target, moduleList = 'all', scanName = 'mcp-scan') { return this.request('spiderfoot_start_scan', { scanname: scanName, scantarget: target, modulelist: moduleList, usecase: 'all' }); } } // Test the client async function testClient() { const client = new FinalMCPClient(); try { console.log('=== Testing Final MCP Client ==='); // 1. Initialize the client console.log('\n1. Initializing...'); await client.initialize(); if (!client.sessionId) { throw new Error('Failed to get session ID'); } // 2. List tools console.log('\n2. Listing tools...'); const toolsResponse = await client.listTools(); console.log('Tools response:', JSON.stringify(toolsResponse.data, null, 2)); // 3. Test ping console.log('\n3. Testing ping...'); const pingResponse = await client.ping(); console.log('Ping response:', JSON.stringify(pingResponse.data, null, 2)); // 4. List scans console.log('\n4. Listing scans...'); try { const scansResponse = await client.listScans(); console.log('Scans response:', JSON.stringify(scansResponse.data, null, 2)); } catch (error) { console.warn('Failed to list scans:', error.message); } console.log('\n✅ Test completed successfully!'); } catch (error) { console.error('\n❌ Test failed:', error.message); if (error.statusCode) { console.error('Status code:', error.statusCode); } if (error.data) { console.error('Error data:', JSON.stringify(error.data, null, 2)); } process.exit(1); } } // Run the test testClient();

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/CorbettCajun/Spiderfoot-MCP-Server'

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