mcp-quiz-server
Version:
🧠AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.
254 lines (253 loc) • 8.39 kB
JavaScript
;
/**
* @moduleName: MCP Transport Abstraction Layer
* @version: 2.0.0
* @since: 2025-07-25
* @lastUpdated: 2025-07-25
* @projectSummary: Enhanced MCP Quiz Server - Future-Ready Transport Architecture
* @techStack: TypeScript, JSON-RPC 2.0, MCP Protocol, Transport Abstraction
* @dependency: None (transport interface definitions)
* @interModuleDependency: ../types/mcp-types, core protocol handlers
* @requirementsTraceability:
* {@link Requirements.REQ_MCP_001} (JSON-RPC 2.0 MCP Protocol)
* @briefDescription: Transport abstraction layer to support current and future MCP transport protocols including STDIO, HTTP, SSE, WebSocket, and Streamable HTTP
* @methods: Transport interface definitions, factory patterns, protocol adapters
* @contributors: GitHub Copilot, Future Transport Design Team
* @examples:
* - STDIO transport for VS Code integration
* - HTTP transport for REST API compatibility
* - SSE transport for streaming responses
* - Future WebSocket transport support
* @vulnerabilitiesAssessment: Transport isolation prevents protocol-specific attacks, standardized error handling across transports
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransportUtils = exports.TRANSPORT_CAPABILITIES = exports.BaseTransport = exports.TransportType = void 0;
/**
* Transport types supported by MCP
*/
var TransportType;
(function (TransportType) {
TransportType["STDIO"] = "stdio";
TransportType["HTTP"] = "http";
TransportType["SSE"] = "sse";
TransportType["STREAMABLE_HTTP"] = "streamable-http";
TransportType["WEBSOCKET"] = "websocket";
TransportType["GRPC"] = "grpc";
TransportType["CUSTOM"] = "custom";
})(TransportType || (exports.TransportType = TransportType = {}));
/**
* Abstract base transport class
*/
class BaseTransport {
constructor() {
this.events = {};
this.metrics = {
messagesReceived: 0,
messagesSent: 0,
errors: 0,
connectionUptime: 0,
averageResponseTime: 0,
currentConnections: 0,
reconnections: 0,
};
}
onMessage(handler) {
this.messageHandler = handler;
}
async processMessage(request, metadata) {
const startTime = Date.now();
try {
this.metrics.messagesReceived++;
if (!this.messageHandler) {
throw new Error('No message handler registered');
}
const response = await this.messageHandler(request);
// Update metrics
const responseTime = Date.now() - startTime;
this.metrics.averageResponseTime = (this.metrics.averageResponseTime + responseTime) / 2;
return response;
}
catch (error) {
this.metrics.errors++;
// Return standardized error response
return {
jsonrpc: '2.0',
id: request.id,
error: {
code: -32603,
message: 'Transport processing error',
data: error instanceof Error ? error.message : String(error),
},
};
}
}
getMetrics() {
return { ...this.metrics };
}
on(event, listener) {
this.events[event] = listener;
}
emit(event, ...args) {
const listener = this.events[event];
if (listener) {
listener(...args);
}
}
}
exports.BaseTransport = BaseTransport;
/**
* Transport capability definitions for each transport type
*/
exports.TRANSPORT_CAPABILITIES = {
[TransportType.STDIO]: {
bidirectional: true,
streaming: false,
serverSentEvents: false,
realTime: true,
connectionPersistent: true,
authentication: false,
compression: false,
binaryData: false,
multiplexing: false,
},
[TransportType.HTTP]: {
bidirectional: true,
streaming: false,
serverSentEvents: false,
realTime: false,
connectionPersistent: false,
authentication: true,
compression: true,
binaryData: true,
multiplexing: false,
},
[TransportType.SSE]: {
bidirectional: true,
streaming: true,
serverSentEvents: true,
realTime: true,
connectionPersistent: true,
authentication: true,
compression: false,
binaryData: false,
multiplexing: false,
},
[TransportType.STREAMABLE_HTTP]: {
bidirectional: true,
streaming: true,
serverSentEvents: true,
realTime: true,
connectionPersistent: true,
authentication: true,
compression: true,
binaryData: true,
multiplexing: true,
},
[TransportType.WEBSOCKET]: {
bidirectional: true,
streaming: true,
serverSentEvents: false,
realTime: true,
connectionPersistent: true,
authentication: true,
compression: true,
binaryData: true,
multiplexing: true,
},
[TransportType.GRPC]: {
bidirectional: true,
streaming: true,
serverSentEvents: false,
realTime: true,
connectionPersistent: true,
authentication: true,
compression: true,
binaryData: true,
multiplexing: true,
},
[TransportType.CUSTOM]: {
bidirectional: true,
streaming: true,
serverSentEvents: true,
realTime: true,
connectionPersistent: true,
authentication: true,
compression: true,
binaryData: true,
multiplexing: true,
},
};
/**
* Transport utility functions
*/
class TransportUtils {
/**
* Detect optimal transport based on context
*/
static detectOptimalTransport(context) {
var _a, _b, _c;
// VS Code environment - prefer STDIO
if (context.environment === 'vscode') {
return TransportType.STDIO;
}
// Browser environment - prefer SSE or Streamable HTTP
if (context.environment === 'browser') {
// Check for Streamable HTTP support
if ((_a = context.capabilities) === null || _a === void 0 ? void 0 : _a.includes('streamable-http')) {
return TransportType.STREAMABLE_HTTP;
}
// Fall back to SSE
if ((_b = context.capabilities) === null || _b === void 0 ? void 0 : _b.includes('sse')) {
return TransportType.SSE;
}
// Fall back to HTTP
return TransportType.HTTP;
}
// Node.js environment - prefer HTTP or WebSocket
if (context.environment === 'node') {
if ((_c = context.capabilities) === null || _c === void 0 ? void 0 : _c.includes('websocket')) {
return TransportType.WEBSOCKET;
}
return TransportType.HTTP;
}
// Default to HTTP for unknown environments
return TransportType.HTTP;
}
/**
* Validate transport configuration
*/
static validateConfig(type, config) {
const capabilities = exports.TRANSPORT_CAPABILITIES[type];
// Add validation logic based on transport type and capabilities
switch (type) {
case TransportType.STDIO:
return true; // STDIO has minimal configuration requirements
case TransportType.HTTP:
case TransportType.SSE:
case TransportType.STREAMABLE_HTTP:
return !!(config.host || config.path);
case TransportType.WEBSOCKET:
return !!(config.host && config.port);
default:
return true;
}
}
/**
* Get recommended transport for specific use case
*/
static getRecommendedTransport(useCase) {
switch (useCase) {
case 'development':
return TransportType.STDIO;
case 'production':
return TransportType.STREAMABLE_HTTP;
case 'streaming':
return TransportType.SSE;
case 'realtime':
return TransportType.WEBSOCKET;
default:
return TransportType.HTTP;
}
}
}
exports.TransportUtils = TransportUtils;