refactor: clean up remote server and improve PM2 configuration

- Remove all test files from remote server directory for cleaner production deployment
- Update PM2 ecosystem.config.js to use npm run start:server for automatic building
- Remove redundant pre_start build step since start:server handles building
This commit is contained in:
nasir@endelospay.com
2025-08-22 01:06:24 +05:00
parent f4ca680532
commit 08f094b12f
12 changed files with 3 additions and 1103 deletions

View File

@@ -2,7 +2,8 @@ module.exports = {
apps: [ apps: [
{ {
name: 'mcp-remote-server', name: 'mcp-remote-server',
script: 'dist/index.js', script: 'npm',
args: 'run start:server',
cwd: __dirname, cwd: __dirname,
instances: 1, instances: 1,
autorestart: true, autorestart: true,
@@ -48,8 +49,7 @@ module.exports = {
// Environment-specific overrides // Environment-specific overrides
merge_logs: true, merge_logs: true,
// Custom startup script (optional) // Build is handled by start:server script
pre_start: 'npm run build',
// Post-deployment hooks (optional) // Post-deployment hooks (optional)
post_start: 'echo "MCP Remote Server started successfully"', post_start: 'echo "MCP Remote Server started successfully"',

View File

@@ -1,62 +0,0 @@
/**
* Test Chrome extension connection to remote server
*/
import WebSocket from 'ws';
const CHROME_ENDPOINT = 'ws://localhost:3001/chrome';
async function testChromeConnection() {
console.log('🔌 Testing Chrome extension connection...');
return new Promise((resolve, reject) => {
const ws = new WebSocket(CHROME_ENDPOINT);
ws.on('open', () => {
console.log('✅ Connected to Chrome extension endpoint');
// Send a test message to see if any Chrome extensions are connected
const testMessage = {
id: 'test-' + Date.now(),
action: 'callTool',
params: {
name: 'chrome_navigate',
arguments: {
url: 'https://www.google.com',
newWindow: false
}
}
};
console.log('📤 Sending test message:', JSON.stringify(testMessage, null, 2));
ws.send(JSON.stringify(testMessage));
// Set a timeout to close the connection
setTimeout(() => {
console.log('⏰ Test timeout - closing connection');
ws.close();
resolve('Test completed');
}, 5000);
});
ws.on('message', (data) => {
try {
const response = JSON.parse(data.toString());
console.log('📨 Received response:', JSON.stringify(response, null, 2));
} catch (error) {
console.error('❌ Error parsing response:', error);
}
});
ws.on('error', (error) => {
console.error('❌ WebSocket error:', error);
reject(error);
});
ws.on('close', () => {
console.log('🔌 Chrome extension connection closed');
});
});
}
testChromeConnection().catch(console.error);

View File

@@ -1,49 +0,0 @@
/**
* Simple test client to verify the remote server is working
*/
import WebSocket from 'ws';
const SERVER_URL = 'ws://localhost:3001/mcp';
console.log('🔌 Connecting to MCP Remote Server...');
const ws = new WebSocket(SERVER_URL);
ws.on('open', () => {
console.log('✅ Connected to remote server!');
// Test listing tools
console.log('📋 Requesting available tools...');
ws.send(
JSON.stringify({
method: 'tools/list',
params: {},
}),
);
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
console.log('📨 Received response:', JSON.stringify(message, null, 2));
} catch (error) {
console.error('❌ Error parsing message:', error);
}
});
ws.on('close', () => {
console.log('🔌 Connection closed');
process.exit(0);
});
ws.on('error', (error) => {
console.error('❌ WebSocket error:', error);
process.exit(1);
});
// Close connection after 5 seconds
setTimeout(() => {
console.log('⏰ Closing connection...');
ws.close();
}, 5000);

View File

@@ -1,51 +0,0 @@
/**
* Monitor Chrome extension connections to the remote server
*/
import WebSocket from 'ws';
const CHROME_ENDPOINT = 'ws://localhost:3001/chrome';
function monitorConnections() {
console.log('🔍 Monitoring Chrome extension connections...');
console.log('📍 Endpoint:', CHROME_ENDPOINT);
console.log('');
console.log('Instructions:');
console.log('1. Load the Chrome extension from: app/chrome-extension/.output/chrome-mv3');
console.log('2. Open the extension popup to check connection status');
console.log('3. Watch this monitor for connection events');
console.log('');
const ws = new WebSocket(CHROME_ENDPOINT);
ws.on('open', () => {
console.log('✅ Connected to Chrome extension endpoint');
console.log('⏳ Waiting for Chrome extension to connect...');
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
console.log('📨 Received message from Chrome extension:', JSON.stringify(message, null, 2));
} catch (error) {
console.log('📨 Received raw message:', data.toString());
}
});
ws.on('error', (error) => {
console.error('❌ WebSocket error:', error);
});
ws.on('close', () => {
console.log('🔌 Connection closed');
});
// Keep the connection alive
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
console.log('💓 Connection still alive, waiting for Chrome extension...');
}
}, 10000);
}
monitorConnections();

View File

@@ -1,25 +0,0 @@
/**
* Simple health check test
*/
import fetch from 'node-fetch';
const SERVER_URL = 'http://localhost:3001';
async function testHealth() {
try {
console.log('🔍 Testing health endpoint...');
const response = await fetch(`${SERVER_URL}/health`);
console.log('Status:', response.status);
console.log('Headers:', Object.fromEntries(response.headers.entries()));
const data = await response.json();
console.log('Response:', data);
} catch (error) {
console.error('❌ Error:', error);
}
}
testHealth();

View File

@@ -1,230 +0,0 @@
/**
* Test script for multi-user Chrome extension to LiveKit agent integration
* This script simulates multiple Chrome extension connections and verifies
* that LiveKit agents are automatically started for each user
*/
import WebSocket from 'ws';
const SERVER_URL = 'ws://localhost:3001/chrome';
const NUM_USERS = 3;
class TestChromeUser {
constructor(userId) {
this.userId = userId;
this.ws = null;
this.sessionInfo = null;
this.connected = false;
this.liveKitAgentStarted = false;
}
async connect() {
return new Promise((resolve, reject) => {
console.log(`👤 User ${this.userId}: Connecting Chrome extension...`);
this.ws = new WebSocket(SERVER_URL);
this.ws.on('open', () => {
console.log(`✅ User ${this.userId}: Chrome extension connected`);
this.connected = true;
// Send connection info (simulating Chrome extension)
const connectionInfo = {
type: 'connection_info',
userAgent: `TestChromeUser-${this.userId}`,
timestamp: Date.now(),
extensionId: `test-extension-${this.userId}`
};
this.ws.send(JSON.stringify(connectionInfo));
});
this.ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
if (message.type === 'session_info') {
this.sessionInfo = message.sessionInfo;
console.log(`📋 User ${this.userId}: Received session info:`, {
userId: this.sessionInfo.userId,
sessionId: this.sessionInfo.sessionId,
connectionId: this.sessionInfo.connectionId
});
// Check if LiveKit agent should be starting
console.log(`🚀 User ${this.userId}: LiveKit agent should be starting for room: mcp-chrome-user-${this.sessionInfo.userId}`);
this.liveKitAgentStarted = true;
resolve();
} else {
console.log(`📨 User ${this.userId}: Received message:`, message);
}
} catch (error) {
console.error(`❌ User ${this.userId}: Error parsing message:`, error);
}
});
this.ws.on('close', () => {
console.log(`🔌 User ${this.userId}: Chrome extension disconnected`);
this.connected = false;
});
this.ws.on('error', (error) => {
console.error(`❌ User ${this.userId}: Connection error:`, error);
reject(error);
});
// Timeout after 10 seconds
setTimeout(() => {
if (!this.sessionInfo) {
reject(new Error(`User ${this.userId}: Timeout waiting for session info`));
}
}, 10000);
});
}
async sendTestCommand() {
if (!this.connected || !this.ws) {
throw new Error(`User ${this.userId}: Not connected`);
}
const testCommand = {
action: 'callTool',
params: {
name: 'chrome_navigate',
arguments: { url: `https://example.com?user=${this.userId}` }
},
id: `test_${this.userId}_${Date.now()}`
};
console.log(`🌐 User ${this.userId}: Sending navigation command`);
this.ws.send(JSON.stringify(testCommand));
}
disconnect() {
if (this.ws) {
console.log(`👋 User ${this.userId}: Disconnecting Chrome extension`);
this.ws.close();
}
}
getStatus() {
return {
userId: this.userId,
connected: this.connected,
sessionInfo: this.sessionInfo,
liveKitAgentStarted: this.liveKitAgentStarted,
expectedRoom: this.sessionInfo ? `mcp-chrome-user-${this.sessionInfo.userId}` : null
};
}
}
async function testMultiUserLiveKitIntegration() {
console.log('🚀 Testing Multi-User Chrome Extension to LiveKit Agent Integration\n');
console.log(`📊 Creating ${NUM_USERS} simulated Chrome extension users...\n`);
const users = [];
try {
// Create and connect multiple users
for (let i = 1; i <= NUM_USERS; i++) {
const user = new TestChromeUser(i);
users.push(user);
console.log(`\n--- Connecting User ${i} ---`);
await user.connect();
// Wait a bit between connections to see the sequential startup
await new Promise(resolve => setTimeout(resolve, 2000));
}
console.log('\n🎉 All Chrome extensions connected successfully!');
// Display session summary
console.log('\n📊 SESSION AND LIVEKIT AGENT SUMMARY:');
console.log('=' * 80);
users.forEach(user => {
const status = user.getStatus();
console.log(`👤 User ${status.userId}:`);
console.log(` 📋 Session ID: ${status.sessionInfo?.sessionId || 'N/A'}`);
console.log(` 🆔 User ID: ${status.sessionInfo?.userId || 'N/A'}`);
console.log(` 🏠 Expected LiveKit Room: ${status.expectedRoom || 'N/A'}`);
console.log(` 🚀 LiveKit Agent Started: ${status.liveKitAgentStarted ? '✅ YES' : '❌ NO'}`);
console.log('');
});
// Test sending commands from each user
console.log('\n--- Testing Commands from Each User ---');
for (const user of users) {
await user.sendTestCommand();
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Wait for responses and LiveKit agent startup
console.log('\n⏳ Waiting for LiveKit agents to start and process commands...');
await new Promise(resolve => setTimeout(resolve, 10000));
// Test session isolation
console.log('\n🔍 Session Isolation Test:');
const sessionIds = users.map(user => user.sessionInfo?.sessionId).filter(Boolean);
const userIds = users.map(user => user.sessionInfo?.userId).filter(Boolean);
const uniqueSessionIds = new Set(sessionIds);
const uniqueUserIds = new Set(userIds);
console.log(` Total users: ${users.length}`);
console.log(` Unique session IDs: ${uniqueSessionIds.size}`);
console.log(` Unique user IDs: ${uniqueUserIds.size}`);
console.log(` Session isolation: ${uniqueSessionIds.size === users.length ? '✅ PASS' : '❌ FAIL'}`);
console.log(` User ID isolation: ${uniqueUserIds.size === users.length ? '✅ PASS' : '❌ FAIL'}`);
// Test LiveKit room naming
console.log('\n🏠 LiveKit Room Naming Test:');
const expectedRooms = users.map(user => user.getStatus().expectedRoom).filter(Boolean);
const uniqueRooms = new Set(expectedRooms);
console.log(` Expected rooms: ${expectedRooms.length}`);
console.log(` Unique rooms: ${uniqueRooms.size}`);
console.log(` Room isolation: ${uniqueRooms.size === users.length ? '✅ PASS' : '❌ FAIL'}`);
expectedRooms.forEach((room, index) => {
console.log(` User ${index + 1} → Room: ${room}`);
});
} catch (error) {
console.error('❌ Test failed:', error);
} finally {
// Clean up connections
console.log('\n🧹 Cleaning up connections...');
users.forEach(user => user.disconnect());
setTimeout(() => {
console.log('\n✅ Multi-user LiveKit integration test completed');
console.log('\n📝 Expected Results:');
console.log(' - Each Chrome extension gets a unique session ID');
console.log(' - Each user gets a unique LiveKit room (mcp-chrome-user-{userId})');
console.log(' - LiveKit agents start automatically for each Chrome connection');
console.log(' - Commands are routed to the correct user\'s Chrome extension');
console.log(' - LiveKit agents stop when Chrome extensions disconnect');
process.exit(0);
}, 2000);
}
}
// Check if server is running
console.log('🔍 Checking if remote server is running...');
const testWs = new WebSocket(SERVER_URL);
testWs.on('open', () => {
testWs.close();
console.log('✅ Remote server is running, starting multi-user LiveKit test...\n');
testMultiUserLiveKitIntegration();
});
testWs.on('error', (error) => {
console.error('❌ Cannot connect to remote server. Please start the remote server first:');
console.error(' cd app/remote-server && npm start');
console.error('\nError:', error.message);
process.exit(1);
});

View File

@@ -1,219 +0,0 @@
/**
* Test script for multi-user session management
* This script simulates multiple Chrome extension connections to test session isolation
*/
import WebSocket from 'ws';
const SERVER_URL = 'ws://localhost:3001/chrome';
const NUM_CONNECTIONS = 3;
class TestConnection {
constructor(id) {
this.id = id;
this.ws = null;
this.sessionInfo = null;
this.connected = false;
}
async connect() {
return new Promise((resolve, reject) => {
console.log(`🔌 Connection ${this.id}: Connecting to ${SERVER_URL}`);
this.ws = new WebSocket(SERVER_URL);
this.ws.on('open', () => {
console.log(`✅ Connection ${this.id}: Connected`);
this.connected = true;
// Send connection info
const connectionInfo = {
type: 'connection_info',
userAgent: `TestAgent-${this.id}`,
timestamp: Date.now(),
extensionId: `test-extension-${this.id}`
};
this.ws.send(JSON.stringify(connectionInfo));
});
this.ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
if (message.type === 'session_info') {
this.sessionInfo = message.sessionInfo;
console.log(`📋 Connection ${this.id}: Received session info:`, this.sessionInfo);
resolve();
} else {
console.log(`📨 Connection ${this.id}: Received message:`, message);
}
} catch (error) {
console.error(`❌ Connection ${this.id}: Error parsing message:`, error);
}
});
this.ws.on('close', () => {
console.log(`🔌 Connection ${this.id}: Disconnected`);
this.connected = false;
});
this.ws.on('error', (error) => {
console.error(`❌ Connection ${this.id}: Error:`, error);
reject(error);
});
// Timeout after 5 seconds
setTimeout(() => {
if (!this.sessionInfo) {
reject(new Error(`Connection ${this.id}: Timeout waiting for session info`));
}
}, 5000);
});
}
async sendTestMessage() {
if (!this.connected || !this.ws) {
throw new Error(`Connection ${this.id}: Not connected`);
}
const testMessage = {
action: 'callTool',
params: {
name: 'chrome_navigate',
arguments: { url: `https://example.com?user=${this.id}` }
},
id: `test_${this.id}_${Date.now()}`
};
console.log(`📤 Connection ${this.id}: Sending test message:`, testMessage);
this.ws.send(JSON.stringify(testMessage));
}
disconnect() {
if (this.ws) {
this.ws.close();
}
}
}
async function testMultiUserSessions() {
console.log('🚀 Starting multi-user session test...\n');
const connections = [];
try {
// Create and connect multiple test connections
for (let i = 1; i <= NUM_CONNECTIONS; i++) {
const connection = new TestConnection(i);
connections.push(connection);
console.log(`\n--- Connecting User ${i} ---`);
await connection.connect();
// Wait a bit between connections
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log('\n🎉 All connections established successfully!');
console.log('\n📊 Session Summary:');
connections.forEach(conn => {
console.log(` User ${conn.id}: Session ${conn.sessionInfo.sessionId}, User ID: ${conn.sessionInfo.userId}`);
});
// Test sending messages from each connection
console.log('\n--- Testing Message Routing ---');
for (const connection of connections) {
await connection.sendTestMessage();
await new Promise(resolve => setTimeout(resolve, 500));
}
// Wait for responses
console.log('\n⏳ Waiting for responses...');
await new Promise(resolve => setTimeout(resolve, 3000));
// Test session isolation by checking unique session IDs
const sessionIds = connections.map(conn => conn.sessionInfo.sessionId);
const uniqueSessionIds = new Set(sessionIds);
console.log('\n🔍 Session Isolation Test:');
console.log(` Total connections: ${connections.length}`);
console.log(` Unique session IDs: ${uniqueSessionIds.size}`);
console.log(` Session isolation: ${uniqueSessionIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);
// Test user ID uniqueness
const userIds = connections.map(conn => conn.sessionInfo.userId);
const uniqueUserIds = new Set(userIds);
console.log(` Unique user IDs: ${uniqueUserIds.size}`);
console.log(` User ID isolation: ${uniqueUserIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);
} catch (error) {
console.error('❌ Test failed:', error);
} finally {
// Clean up connections
console.log('\n🧹 Cleaning up connections...');
connections.forEach(conn => conn.disconnect());
setTimeout(() => {
console.log('✅ Test completed');
process.exit(0);
}, 1000);
}
}
async function testSessionPersistence() {
console.log('\n🔄 Testing session persistence...');
const connection = new TestConnection('persistence');
try {
await connection.connect();
const originalSessionId = connection.sessionInfo.sessionId;
console.log(`📋 Original session: ${originalSessionId}`);
// Disconnect and reconnect
connection.disconnect();
await new Promise(resolve => setTimeout(resolve, 1000));
await connection.connect();
const newSessionId = connection.sessionInfo.sessionId;
console.log(`📋 New session: ${newSessionId}`);
console.log(`🔄 Session persistence: ${originalSessionId === newSessionId ? '❌ FAIL (sessions should be different)' : '✅ PASS (new session created)'}`);
connection.disconnect();
} catch (error) {
console.error('❌ Session persistence test failed:', error);
}
}
// Run tests
async function runAllTests() {
try {
await testMultiUserSessions();
await new Promise(resolve => setTimeout(resolve, 2000));
await testSessionPersistence();
} catch (error) {
console.error('❌ Tests failed:', error);
process.exit(1);
}
}
// Check if server is running
console.log('🔍 Checking if remote server is running...');
const testWs = new WebSocket(SERVER_URL);
testWs.on('open', () => {
testWs.close();
console.log('✅ Server is running, starting tests...\n');
runAllTests();
});
testWs.on('error', (error) => {
console.error('❌ Cannot connect to server. Please start the remote server first:');
console.error(' cd app/remote-server && npm run dev');
console.error('\nError:', error.message);
process.exit(1);
});

View File

@@ -1,58 +0,0 @@
/**
* Simple MCP endpoint test
*/
import fetch from 'node-fetch';
const SERVER_URL = 'http://localhost:3001';
async function testMcpEndpoint() {
try {
console.log('🔍 Testing MCP endpoint with simple request...');
const initMessage = {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {
tools: {},
},
clientInfo: {
name: 'test-simple-mcp-client',
version: '1.0.0',
},
},
};
console.log('📤 Sending:', JSON.stringify(initMessage, null, 2));
const response = await fetch(`${SERVER_URL}/mcp`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json, text/event-stream',
},
body: JSON.stringify(initMessage),
});
console.log('📥 Status:', response.status);
console.log('📥 Headers:', Object.fromEntries(response.headers.entries()));
if (response.ok) {
const sessionId = response.headers.get('mcp-session-id');
console.log('🆔 Session ID:', sessionId);
const text = await response.text();
console.log('📥 SSE Response:', text);
} else {
const text = await response.text();
console.log('📥 Error response:', text);
}
} catch (error) {
console.error('❌ Error:', error);
}
}
testMcpEndpoint();

View File

@@ -1,85 +0,0 @@
/**
* Test client for SSE (Server-Sent Events) streaming connection
*/
import { EventSource } from 'eventsource';
import fetch from 'node-fetch';
const SERVER_URL = 'http://localhost:3001';
const SSE_URL = `${SERVER_URL}/sse`;
const MESSAGES_URL = `${SERVER_URL}/messages`;
console.log('🔌 Testing SSE streaming connection...');
let sessionId = null;
// Create SSE connection
const eventSource = new EventSource(SSE_URL);
eventSource.onopen = () => {
console.log('✅ SSE connection established!');
};
eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('📨 Received SSE message:', JSON.stringify(data, null, 2));
// Extract session ID from the first message
if (data.sessionId && !sessionId) {
sessionId = data.sessionId;
console.log(`🆔 Session ID: ${sessionId}`);
// Test listing tools after connection is established
setTimeout(() => testListTools(), 1000);
}
} catch (error) {
console.log('📨 Received SSE data:', event.data);
}
};
eventSource.onerror = (error) => {
console.error('❌ SSE error:', error);
};
async function testListTools() {
if (!sessionId) {
console.error('❌ No session ID available');
return;
}
console.log('📋 Testing tools/list via SSE...');
const message = {
jsonrpc: '2.0',
id: 1,
method: 'tools/list',
params: {},
};
try {
const response = await fetch(MESSAGES_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Session-ID': sessionId,
},
body: JSON.stringify(message),
});
if (!response.ok) {
console.error('❌ Failed to send message:', response.status, response.statusText);
} else {
console.log('✅ Message sent successfully');
}
} catch (error) {
console.error('❌ Error sending message:', error);
}
}
// Close connection after 10 seconds
setTimeout(() => {
console.log('⏰ Closing SSE connection...');
eventSource.close();
process.exit(0);
}, 10000);

View File

@@ -1,132 +0,0 @@
/**
* Test client for Streamable HTTP connection
*/
import fetch from 'node-fetch';
import { EventSource } from 'eventsource';
const SERVER_URL = 'http://localhost:3001';
const MCP_URL = `${SERVER_URL}/mcp`;
console.log('🔌 Testing Streamable HTTP connection...');
let sessionId = null;
async function testStreamableHttp() {
try {
// Step 1: Send initialization request
console.log('🚀 Sending initialization request...');
const initMessage = {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {
tools: {},
},
clientInfo: {
name: 'test-streamable-http-client',
version: '1.0.0',
},
},
};
const initResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json, text/event-stream',
},
body: JSON.stringify(initMessage),
});
if (!initResponse.ok) {
throw new Error(`Initialization failed: ${initResponse.status} ${initResponse.statusText}`);
}
// Extract session ID from response headers
sessionId = initResponse.headers.get('mcp-session-id');
console.log(`✅ Initialization successful! Session ID: ${sessionId}`);
const initResult = await initResponse.text();
console.log('📨 Initialization response (SSE):', initResult);
// Step 2: Establish SSE stream for this session
console.log('🔌 Establishing SSE stream...');
const eventSource = new EventSource(MCP_URL, {
headers: {
'MCP-Session-ID': sessionId,
},
});
eventSource.onopen = () => {
console.log('✅ SSE stream established!');
// Test listing tools after stream is ready
setTimeout(() => testListTools(), 1000);
};
eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('📨 Received streaming message:', JSON.stringify(data, null, 2));
} catch (error) {
console.log('📨 Received streaming data:', event.data);
}
};
eventSource.onerror = (error) => {
console.error('❌ SSE stream error:', error);
};
// Close after 10 seconds
setTimeout(() => {
console.log('⏰ Closing connections...');
eventSource.close();
process.exit(0);
}, 10000);
} catch (error) {
console.error('❌ Error in streamable HTTP test:', error);
process.exit(1);
}
}
async function testListTools() {
if (!sessionId) {
console.error('❌ No session ID available');
return;
}
console.log('📋 Testing tools/list via Streamable HTTP...');
const message = {
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {},
};
try {
const response = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'MCP-Session-ID': sessionId,
},
body: JSON.stringify(message),
});
if (!response.ok) {
console.error('❌ Failed to send tools/list:', response.status, response.statusText);
} else {
console.log('✅ tools/list message sent successfully');
}
} catch (error) {
console.error('❌ Error sending tools/list:', error);
}
}
// Start the test
testStreamableHttp();

View File

@@ -1,77 +0,0 @@
/**
* Test tool call to verify Chrome extension connection using MCP WebSocket
*/
import WebSocket from 'ws';
const MCP_SERVER_URL = 'ws://localhost:3001/ws/mcp';
async function testToolCall() {
console.log('🔌 Testing tool call via MCP WebSocket...');
return new Promise((resolve, reject) => {
const ws = new WebSocket(MCP_SERVER_URL);
ws.on('open', () => {
console.log('✅ Connected to MCP WebSocket');
// Send a proper MCP tool call
const message = {
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: {
name: 'chrome_navigate',
arguments: {
url: 'https://www.google.com',
newWindow: false,
},
},
};
console.log('📤 Sending MCP message:', JSON.stringify(message, null, 2));
ws.send(JSON.stringify(message));
});
ws.on('message', (data) => {
try {
const response = JSON.parse(data.toString());
console.log('📨 MCP Response:', JSON.stringify(response, null, 2));
if (response.error) {
console.error('❌ Tool call failed:', response.error);
reject(new Error(response.error.message || response.error));
} else if (response.result) {
console.log('✅ Tool call successful!');
resolve(response.result);
} else {
console.log('📨 Received other message:', response);
}
ws.close();
} catch (error) {
console.error('❌ Error parsing response:', error);
reject(error);
ws.close();
}
});
ws.on('error', (error) => {
console.error('❌ WebSocket error:', error);
reject(error);
});
ws.on('close', () => {
console.log('🔌 WebSocket connection closed');
});
// Timeout after 10 seconds
setTimeout(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.close();
reject(new Error('Test timeout'));
}
}, 10000);
});
}
testToolCall().catch(console.error);

View File

@@ -1,112 +0,0 @@
/**
* Test tools/list via streamable HTTP
*/
import fetch from 'node-fetch';
const SERVER_URL = 'http://localhost:3001';
const MCP_URL = `${SERVER_URL}/mcp`;
async function testToolsList() {
try {
console.log('🔍 Testing tools/list via streamable HTTP...');
// Step 1: Initialize session
const initMessage = {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {
tools: {}
},
clientInfo: {
name: 'test-tools-list-client',
version: '1.0.0'
}
}
};
console.log('🚀 Step 1: Initializing session...');
const initResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream'
},
body: JSON.stringify(initMessage)
});
if (!initResponse.ok) {
throw new Error(`Initialization failed: ${initResponse.status} ${initResponse.statusText}`);
}
const sessionId = initResponse.headers.get('mcp-session-id');
console.log(`✅ Session initialized! Session ID: ${sessionId}`);
// Step 2: Send tools/list request
const toolsListMessage = {
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {}
};
console.log('📋 Step 2: Requesting tools list...');
const toolsResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
'MCP-Session-ID': sessionId
},
body: JSON.stringify(toolsListMessage)
});
if (!toolsResponse.ok) {
throw new Error(`Tools list failed: ${toolsResponse.status} ${toolsResponse.statusText}`);
}
const toolsResult = await toolsResponse.text();
console.log('📋 Tools list response (SSE):', toolsResult);
// Step 3: Test a tool call (navigate_to_url)
const toolCallMessage = {
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'navigate_to_url',
arguments: {
url: 'https://example.com'
}
}
};
console.log('🔧 Step 3: Testing tool call (navigate_to_url)...');
const toolCallResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
'MCP-Session-ID': sessionId
},
body: JSON.stringify(toolCallMessage)
});
if (!toolCallResponse.ok) {
throw new Error(`Tool call failed: ${toolCallResponse.status} ${toolCallResponse.statusText}`);
}
const toolCallResult = await toolCallResponse.text();
console.log('🔧 Tool call response (SSE):', toolCallResult);
console.log('✅ All tests completed successfully!');
} catch (error) {
console.error('❌ Error:', error);
}
}
testToolsList();