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:
@@ -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"',
|
||||||
|
@@ -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);
|
|
@@ -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);
|
|
@@ -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();
|
|
@@ -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();
|
|
@@ -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);
|
|
||||||
});
|
|
@@ -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);
|
|
||||||
});
|
|
@@ -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();
|
|
@@ -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);
|
|
@@ -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();
|
|
@@ -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);
|
|
@@ -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();
|
|
Reference in New Issue
Block a user