UNPKG

ultimate-mcp-server

Version:

The definitive all-in-one Model Context Protocol server for AI-assisted coding across 30+ platforms

233 lines 7.49 kB
/** * Platform-specific adapters for compatibility */ import { SUPPORTED_PLATFORMS } from './platform-detector.js'; export class PlatformAdapterFactory { static adapters = new Map(); // Static initialization will be done after class definitions static registerAdapter(adapter) { this.adapters.set(adapter.platform, adapter); } static getAdapter(platform) { return this.adapters.get(platform) || this.adapters.get('default'); } } // Platform-specific adapter implementations class DefaultAdapter { platform = 'default'; adaptStdioRequest(input) { // Standard JSON-RPC format return input; } adaptStdioResponse(response) { return response; } adaptHttpRequest(req) { return req.body; } adaptHttpResponse(response, res) { res.json(response); } adaptSSEMessage(data) { return `data: ${JSON.stringify(data)}\n\n`; } adaptWebSocketMessage(data) { return JSON.stringify(data); } formatError(error) { return { error: { code: -32603, message: error.message, data: { stack: error.stack } } }; } } class ClaudeDesktopAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.CLAUDE_DESKTOP; adaptStdioRequest(input) { // Claude Desktop sends requests in a specific format if (typeof input === 'string') { try { return JSON.parse(input); } catch { // If we can't parse it, create a basic request return { id: Date.now(), method: 'unknown', params: { input } }; } } return input; } adaptStdioResponse(response) { // Claude Desktop expects newline-delimited JSON return JSON.stringify(response) + '\n'; } formatError(error) { // Claude Desktop expects specific error format return { jsonrpc: '2.0', error: { code: -32603, message: error.message } }; } } class CursorAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.CURSOR; async initialize() { // Cursor-specific initialization console.error('Initializing Cursor adapter...'); } adaptHttpRequest(req) { // Cursor may send additional headers const request = req.body; if (req.headers['x-cursor-session']) { request._cursorSession = req.headers['x-cursor-session']; } return request; } async handleAuthentication(credentials) { // Cursor-specific authentication if (credentials.cursorToken) { // Validate Cursor token return true; } return false; } } class WindsurfAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.WINDSURF; adaptSSEMessage(data) { // Windsurf expects SSE messages with specific event types return `event: message\ndata: ${JSON.stringify(data)}\n\n`; } adaptHttpResponse(response, res) { // Windsurf expects specific headers res.setHeader('X-Windsurf-Compatible', 'true'); res.json(response); } } class VSCodeAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.VSCODE; adaptStdioRequest(input) { // VSCode extension host might wrap requests if (input.type === 'mcp-request' && input.payload) { return input.payload; } return input; } handleEnvironmentVariables() { // Filter VSCode-specific env vars const env = { ...process.env }; const vscodeKeys = Object.keys(env).filter(key => key.startsWith('VSCODE_')); const filtered = {}; for (const key of vscodeKeys) { if (env[key]) { filtered[key] = env[key]; } } return filtered; } } class ClineAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.CLINE; adaptHttpRequest(req) { // Cline sends requests with specific structure const { method, params, id } = req.body; return { jsonrpc: '2.0', method, params, id: id || Date.now() }; } async handleFileAccess(path, operation) { // Cline has specific file access restrictions if (path.includes('node_modules') || path.includes('.git')) { return false; } return true; } } class BoltAIAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.BOLTAI; adaptWebSocketMessage(data) { // BoltAI expects WebSocket messages in specific format return { type: 'mcp-response', timestamp: Date.now(), data: data }; } async handleAuthentication(credentials) { // BoltAI uses API key authentication if (credentials.apiKey && credentials.apiKey.startsWith('bolt_')) { return true; } return false; } } class LibreChatAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.LIBRECHAT; adaptSSEMessage(data) { // LibreChat expects SSE with retry and id fields const id = Date.now(); return `id: ${id}\nretry: 3000\ndata: ${JSON.stringify(data)}\n\n`; } adaptHttpResponse(response, res) { // LibreChat expects CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.json(response); } } class BigAGIAdapter extends DefaultAdapter { platform = SUPPORTED_PLATFORMS.BIGAGI; adaptWebSocketMessage(data) { // Big-AGI expects WebSocket messages with metadata return { protocol: 'mcp', version: '1.0', timestamp: new Date().toISOString(), payload: data }; } formatError(error) { // Big-AGI expects detailed error information return { error: { type: 'MCPError', code: error.name === 'ValidationError' ? -32602 : -32603, message: error.message, details: { stack: error.stack, timestamp: new Date().toISOString() } } }; } } // Additional adapters for other platforms can be added here... // Initialize adapters after all classes are defined (() => { PlatformAdapterFactory.registerAdapter(new ClaudeDesktopAdapter()); PlatformAdapterFactory.registerAdapter(new CursorAdapter()); PlatformAdapterFactory.registerAdapter(new WindsurfAdapter()); PlatformAdapterFactory.registerAdapter(new VSCodeAdapter()); PlatformAdapterFactory.registerAdapter(new ClineAdapter()); PlatformAdapterFactory.registerAdapter(new BoltAIAdapter()); PlatformAdapterFactory.registerAdapter(new LibreChatAdapter()); PlatformAdapterFactory.registerAdapter(new BigAGIAdapter()); PlatformAdapterFactory.registerAdapter(new DefaultAdapter()); })(); export { PlatformAdapterFactory as default }; //# sourceMappingURL=platform-adapter.js.map