import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import express, { Express } from 'express';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { MCPServer } from '../../src/server.js';
describe('Health Endpoint', () => {
let app: Express;
let mcpServer: MCPServer;
beforeAll(() => {
// Create a test MCP server instance
const server = new Server(
{
name: 'test-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
logging: {},
},
}
);
mcpServer = new MCPServer(server);
// Set up Express app with health endpoint
app = express();
app.use(express.json());
app.get('/health', (req, res) => {
const healthCheck = {
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
service: 'mcp-server',
version: '1.0.0',
checks: {
server: mcpServer.isHealthy() ? 'ok' : 'degraded',
},
};
const httpStatus = healthCheck.checks.server === 'ok' ? 200 : 503;
res.status(httpStatus).json(healthCheck);
});
});
afterAll(async () => {
await mcpServer.cleanup();
});
it('should return 200 status when server is healthy', async () => {
const response = await request(app).get('/health');
expect(response.status).toBe(200);
});
it('should return correct health check structure', async () => {
const response = await request(app).get('/health');
expect(response.body).toHaveProperty('status');
expect(response.body).toHaveProperty('timestamp');
expect(response.body).toHaveProperty('uptime');
expect(response.body).toHaveProperty('service');
expect(response.body).toHaveProperty('version');
expect(response.body).toHaveProperty('checks');
});
it('should indicate server status as healthy', async () => {
const response = await request(app).get('/health');
expect(response.body.status).toBe('healthy');
expect(response.body.checks.server).toBe('ok');
});
it('should return valid timestamp in ISO format', async () => {
const response = await request(app).get('/health');
const timestamp = new Date(response.body.timestamp);
expect(timestamp.toISOString()).toBe(response.body.timestamp);
});
it('should return positive uptime value', async () => {
const response = await request(app).get('/health');
expect(response.body.uptime).toBeGreaterThan(0);
expect(typeof response.body.uptime).toBe('number');
});
it('should return correct service name', async () => {
const response = await request(app).get('/health');
expect(response.body.service).toBe('mcp-server');
});
it('should return version information', async () => {
const response = await request(app).get('/health');
expect(response.body.version).toBe('1.0.0');
});
it('should return JSON content-type', async () => {
const response = await request(app).get('/health');
expect(response.headers['content-type']).toMatch(/application\/json/);
});
it('should handle multiple concurrent health check requests', async () => {
const requests = Array(5)
.fill(null)
.map(() => request(app).get('/health').timeout(5000));
const responses = await Promise.all(requests);
responses.forEach((response) => {
expect(response.status).toBe(200);
expect(response.body.status).toBe('healthy');
});
});
it('should return consistent structure across multiple calls', async () => {
const response1 = await request(app).get('/health');
const response2 = await request(app).get('/health');
expect(Object.keys(response1.body).sort()).toEqual(
Object.keys(response2.body).sort()
);
});
});