test-http-transport.mjsโข9.74 kB
#!/usr/bin/env node
/**
* Test script to verify HTTP transport functionality for M365 Core MCP Server
* This script tests the HTTP endpoints and MCP protocol over HTTP
*/
import fetch from 'node-fetch';
import { spawn } from 'child_process';
import { setTimeout } from 'timers/promises';
const SERVER_PORT = 8080;
const SERVER_URL = `http://localhost:${SERVER_PORT}`;
const MCP_ENDPOINT = `${SERVER_URL}/mcp`;
let serverProcess = null;
async function startServer() {
console.log('๐ Starting M365 Core MCP Server in HTTP mode...');
serverProcess = spawn('node', ['build/index.js'], {
env: {
...process.env,
USE_HTTP: 'true',
PORT: SERVER_PORT.toString(),
STATELESS: 'true', // Use stateless mode for testing
LOG_LEVEL: 'info'
},
stdio: ['pipe', 'pipe', 'pipe']
});
serverProcess.stdout.on('data', (data) => {
console.log(`[SERVER] ${data.toString().trim()}`);
});
serverProcess.stderr.on('data', (data) => {
console.error(`[SERVER ERROR] ${data.toString().trim()}`);
});
// Wait for server to start
await setTimeout(3000);
console.log('โ
Server should be running now');
}
async function stopServer() {
if (serverProcess) {
console.log('๐ Stopping server...');
serverProcess.kill('SIGTERM');
await setTimeout(1000);
}
}
async function testHealthEndpoint() {
console.log('\n๐ Test 1: Health Check Endpoint');
try {
const response = await fetch(`${SERVER_URL}/health`);
const data = await response.json();
console.log(' โ
Health endpoint accessible');
console.log(` ๐ Server: ${data.server}`);
console.log(` ๐ Version: ${data.version}`);
console.log(` ๐ Status: ${data.status}`);
console.log(` ๐ Capabilities: ${Object.keys(data.capabilities).join(', ')}`);
return true;
} catch (error) {
console.log(` โ Health endpoint failed: ${error.message}`);
return false;
}
}
async function testCapabilitiesEndpoint() {
console.log('\n๐ Test 2: Capabilities Endpoint');
try {
const response = await fetch(`${SERVER_URL}/capabilities`);
const data = await response.json();
console.log(' โ
Capabilities endpoint accessible');
console.log(` ๐ Protocol: ${data.protocol}`);
console.log(` ๐ Tools available: ${data.tools.length}`);
console.log(` ๐ Sample tools: ${data.tools.slice(0, 5).join(', ')}`);
return true;
} catch (error) {
console.log(` โ Capabilities endpoint failed: ${error.message}`);
return false;
}
}
async function testMCPInitialize() {
console.log('\n๐ Test 3: MCP Initialize Request');
try {
const initializeRequest = {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {
roots: {
listChanged: true
},
sampling: {}
},
clientInfo: {
name: 'test-client',
version: '1.0.0'
}
}
};
const response = await fetch(MCP_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
},
body: JSON.stringify(initializeRequest)
});
const data = await response.json();
if (data.result && data.result.capabilities) {
console.log(' โ
MCP Initialize successful');
console.log(` ๐ Server capabilities: ${Object.keys(data.result.capabilities).join(', ')}`);
console.log(` ๐ Server info: ${data.result.serverInfo?.name || 'Unknown'}`);
return true;
} else {
console.log(' โ MCP Initialize failed - no capabilities in response');
console.log(` ๐ Response: ${JSON.stringify(data, null, 2)}`);
return false;
}
} catch (error) {
console.log(` โ MCP Initialize failed: ${error.message}`);
return false;
}
}
async function testMCPListTools() {
console.log('\n๐ Test 4: MCP List Tools Request');
try {
const listToolsRequest = {
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {}
};
const response = await fetch(MCP_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
},
body: JSON.stringify(listToolsRequest)
});
const data = await response.json();
if (data.result && data.result.tools) {
console.log(' โ
MCP List Tools successful');
console.log(` ๐ Tools found: ${data.result.tools.length}`);
console.log(` ๐ Sample tools: ${data.result.tools.slice(0, 3).map(t => t.name).join(', ')}`);
// Check for specific M365 tools
const m365Tools = data.result.tools.filter(t =>
t.name.includes('manage_') || t.name.includes('m365') || t.name.includes('azure')
);
console.log(` ๐ M365-specific tools: ${m365Tools.length}`);
return true;
} else {
console.log(' โ MCP List Tools failed - no tools in response');
console.log(` ๐ Response: ${JSON.stringify(data, null, 2)}`);
return false;
}
} catch (error) {
console.log(` โ MCP List Tools failed: ${error.message}`);
return false;
}
}
async function testMCPHealthCheckTool() {
console.log('\n๐ Test 5: MCP Health Check Tool (No Auth Required)');
try {
const toolCallRequest = {
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'health_check',
arguments: {}
}
};
const response = await fetch(MCP_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream',
},
body: JSON.stringify(toolCallRequest)
});
const data = await response.json();
if (data.result && data.result.content) {
console.log(' โ
Health Check Tool successful');
const content = data.result.content[0];
if (content && content.text) {
const healthData = JSON.parse(content.text.split('\n\n')[1]);
console.log(` ๐ Server Status: ${healthData.serverStatus}`);
console.log(` ๐ Auth Configured: ${healthData.authentication.configured}`);
console.log(` ๐ Auth Status: ${healthData.authentication.status}`);
}
return true;
} else {
console.log(' โ Health Check Tool failed');
console.log(` ๐ Response: ${JSON.stringify(data, null, 2)}`);
return false;
}
} catch (error) {
console.log(` โ Health Check Tool failed: ${error.message}`);
return false;
}
}
async function testCORSHeaders() {
console.log('\n๐ Test 6: CORS Headers');
try {
const response = await fetch(MCP_ENDPOINT, {
method: 'OPTIONS',
headers: {
'Origin': 'https://example.com',
'Access-Control-Request-Method': 'POST',
'Access-Control-Request-Headers': 'Content-Type'
}
});
const corsHeaders = {
'Access-Control-Allow-Origin': response.headers.get('Access-Control-Allow-Origin'),
'Access-Control-Allow-Methods': response.headers.get('Access-Control-Allow-Methods'),
'Access-Control-Allow-Headers': response.headers.get('Access-Control-Allow-Headers')
};
console.log(' โ
CORS preflight successful');
console.log(` ๐ Allow Origin: ${corsHeaders['Access-Control-Allow-Origin']}`);
console.log(` ๐ Allow Methods: ${corsHeaders['Access-Control-Allow-Methods']}`);
console.log(` ๐ Allow Headers: ${corsHeaders['Access-Control-Allow-Headers']}`);
return response.status === 200;
} catch (error) {
console.log(` โ CORS test failed: ${error.message}`);
return false;
}
}
async function runAllTests() {
console.log('๐งช M365 Core MCP Server HTTP Transport Test Suite\n');
try {
// Start the server
await startServer();
// Run tests
const results = [];
results.push(await testHealthEndpoint());
results.push(await testCapabilitiesEndpoint());
results.push(await testMCPInitialize());
results.push(await testMCPListTools());
results.push(await testMCPHealthCheckTool());
results.push(await testCORSHeaders());
// Summary
const passed = results.filter(r => r).length;
const total = results.length;
console.log('\n๐ Test Results Summary:');
console.log(` โ
Passed: ${passed}/${total}`);
console.log(` โ Failed: ${total - passed}/${total}`);
if (passed === total) {
console.log('\n๐ All tests passed! HTTP transport is working correctly.');
console.log('\n๐ Your M365 Core MCP Server is ready for HTTP deployment!');
console.log('\n๐ Next steps:');
console.log(' 1. Configure your Azure AD credentials');
console.log(' 2. Deploy to Smithery or your preferred platform');
console.log(' 3. Test with real M365 operations');
} else {
console.log('\nโ ๏ธ Some tests failed. Please check the server configuration.');
}
} catch (error) {
console.error('๐ฅ Test suite crashed:', error);
} finally {
await stopServer();
}
}
// Handle cleanup on exit
process.on('SIGINT', async () => {
console.log('\n๐ Received SIGINT, cleaning up...');
await stopServer();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('\n๐ Received SIGTERM, cleaning up...');
await stopServer();
process.exit(0);
});
// Run the tests
runAllTests().catch(error => {
console.error('๐ฅ Test execution failed:', error);
process.exit(1);
});