debug-mcp-client.js•7.68 kB
// Debug script for MCP client with SpiderFoot MCP server
import axios from 'axios';
import https from 'https';
// Create a custom agent to allow self-signed certificates
const httpsAgent = new https.Agent({
rejectUnauthorized: false // For testing only - accept self-signed certificates
});
const MCP_SERVER_URL = 'http://localhost:5002/mcp';
class DebugMCPClient {
constructor() {
this.sessionId = null;
this.requestId = 1;
}
async initialize() {
console.log('\n=== Initializing MCP Client ===');
console.log('Sending initialization request to:', MCP_SERVER_URL);
const requestData = {
jsonrpc: '2.0',
method: 'initialize',
params: {
protocolVersion: '1.0',
clientInfo: {
name: 'debug-client',
version: '1.0.0'
},
capabilities: {}
},
id: this.requestId++
};
console.log('Request data:', JSON.stringify(requestData, null, 2));
try {
const response = await axios({
method: 'post',
url: MCP_SERVER_URL,
data: requestData,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream'
},
responseType: 'text',
httpsAgent,
// Enable request/response interception
transformRequest: [(data, headers) => {
console.log('\n=== Request Headers ===');
console.log(headers);
console.log('=== Request Data ===');
console.log(JSON.stringify(data, null, 2));
return JSON.stringify(data);
}],
transformResponse: [(data) => {
console.log('\n=== Raw Response ===');
console.log(data);
return data;
}]
});
console.log('\n=== Response Headers ===');
console.log(response.headers);
// Extract session ID from headers
if (response.headers['mcp-session-id']) {
this.sessionId = response.headers['mcp-session-id'];
console.log('\n=== Session ID ===');
console.log(this.sessionId);
} else {
console.warn('No session ID received in response headers');
}
// Parse SSE response
const sseData = this.parseSSEResponse(response.data);
console.log('\n=== Parsed SSE Data ===');
console.log(JSON.stringify(sseData, null, 2));
return sseData;
} catch (error) {
console.error('\n=== Initialization Error ===');
this.logError(error);
throw error;
}
}
async callMethod(method, params = {}) {
if (!this.sessionId) {
throw new Error('Not initialized. Call initialize() first.');
}
console.log(`\n=== Calling Method: ${method} ===`);
console.log('Params:', JSON.stringify(params, null, 2));
const requestData = {
jsonrpc: '2.0',
method: method,
params: params,
id: this.requestId++
};
console.log('Request data:', JSON.stringify(requestData, null, 2));
try {
const response = await axios({
method: 'post',
url: MCP_SERVER_URL,
data: requestData,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
'mcp-session-id': this.sessionId
},
responseType: 'text',
httpsAgent,
// Enable request/response interception
transformRequest: [(data, headers) => {
console.log('\n=== Request Headers ===');
console.log(headers);
console.log('=== Request Data ===');
console.log(JSON.stringify(data, null, 2));
return JSON.stringify(data);
}],
transformResponse: [(data) => {
console.log('\n=== Raw Response ===');
console.log(data);
return data;
}]
});
console.log('\n=== Response Headers ===');
console.log(response.headers);
// Parse SSE response
const sseData = this.parseSSEResponse(response.data);
console.log('\n=== Parsed SSE Data ===');
console.log(JSON.stringify(sseData, null, 2));
return sseData;
} catch (error) {
console.error(`\n=== Method ${method} Call Error ===`);
this.logError(error);
throw error;
}
}
parseSSEResponse(data) {
if (!data) {
console.warn('No data to parse in SSE response');
return { event: null, data: null, id: null, retry: null };
}
const lines = data.split('\n').filter(line => line.trim() !== '');
const result = {
event: null,
data: null,
id: null,
retry: null
};
for (const line of lines) {
const colonIndex = line.indexOf(':');
if (colonIndex === -1) continue;
const field = line.slice(0, colonIndex).trim();
let value = line.slice(colonIndex + 1).trim();
// Remove leading space if present
if (value.startsWith(' ')) {
value = value.slice(1);
}
if (field === 'data') {
try {
result.data = JSON.parse(value);
} catch (e) {
result.data = value;
}
} else if (field === 'event') {
result.event = value;
} else if (field === 'id') {
result.id = value;
} else if (field === 'retry') {
result.retry = parseInt(value, 10);
}
}
return result;
}
logError(error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error('Response status:', error.response.status);
console.error('Response headers:', error.response.headers);
console.error('Response data:', error.response.data);
if (error.response.data) {
try {
const errorData = typeof error.response.data === 'string'
? JSON.parse(error.response.data)
: error.response.data;
console.error('Error details:', JSON.stringify(errorData, null, 2));
} catch (e) {
console.error('Error parsing error response:', e);
}
}
} else if (error.request) {
// The request was made but no response was received
console.error('No response received:', error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.error('Request setup error:', error.message);
}
if (error.config) {
console.error('Request config:', {
url: error.config.url,
method: error.config.method,
headers: error.config.headers,
data: error.config.data
});
}
console.error('Stack trace:', error.stack);
}
}
// Test the debug MCP client
async function testDebugMCPClient() {
const client = new DebugMCPClient();
try {
// 1. Initialize the client
console.log('\n=== Starting MCP Client Test ===');
await client.initialize();
if (!client.sessionId) {
throw new Error('Failed to initialize MCP session - no session ID received');
}
// 2. List available tools using the correct method name
console.log('\n=== Testing Tools List ===');
await client.callMethod('mcp.list_tools', {});
// 3. Test a specific tool (e.g., spiderfoot_ping)
console.log('\n=== Testing SpiderFoot Ping ===');
await client.callMethod('spiderfoot_ping', {});
console.log('\n✅ MCP client test completed successfully!');
} catch (error) {
console.error('\n❌ MCP client test failed:', error.message);
process.exit(1);
}
}
// Run the test
testDebugMCPClient();