UNPKG

@vibe-kit/grok-cli

Version:

An open-source AI agent that brings the power of Grok directly into your terminal.

191 lines 6.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.McpProtocolClient = void 0; const events_1 = require("events"); const stdio_transport_1 = require("./transports/stdio-transport"); const sse_transport_1 = require("./transports/sse-transport"); class McpProtocolClient extends events_1.EventEmitter { constructor(options) { super(); this.options = options; this.requestId = 0; this.pendingRequests = new Map(); this.serverInfo = null; this.tools = []; // Determine if we should run in quiet mode (suppress stderr in interactive mode) const isInteractiveMode = !process.argv.includes('--prompt'); const quiet = isInteractiveMode && !process.env.MCP_DEBUG; // Create appropriate transport if (options.transport === 'sse') { if (!options.url) { throw new Error('URL is required for SSE transport'); } this.transport = new sse_transport_1.SseTransport({ url: options.url, headers: options.headers, env: options.env, quiet }); } else { if (!options.command) { throw new Error('Command is required for stdio transport'); } this.transport = new stdio_transport_1.StdioTransport({ command: options.command, args: options.args, env: options.env, quiet }); } // Set up transport event handlers this.transport.on('message', (message) => { this.handleMessage(message); }); this.transport.on('disconnect', () => { this.emit('disconnect'); }); this.transport.on('error', (error) => { this.emit('error', error); }); } async connect() { try { await this.transport.connect(); await this.initialize(); } catch (error) { throw new Error(`Failed to connect to MCP server: ${error}`); } } handleMessage(message) { if ('id' in message) { // Response const pending = this.pendingRequests.get(message.id); if (pending) { this.pendingRequests.delete(message.id); if (message.error) { pending.reject(new Error(`${message.error.message} (${message.error.code})`)); } else { pending.resolve(message.result); } } } else { // Notification this.emit('notification', message); } } async sendRequest(method, params) { if (!this.transport.isConnected()) { throw new Error('MCP server not connected'); } const id = ++this.requestId; const request = { jsonrpc: '2.0', id, method, params }; return new Promise((resolve, reject) => { this.pendingRequests.set(id, { resolve, reject }); this.transport.send(request).catch(reject); // Timeout after 60 seconds (increased for Docker container startup) setTimeout(() => { if (this.pendingRequests.has(id)) { this.pendingRequests.delete(id); reject(new Error(`Request timeout for method: ${method} (after 60s)`)); } }, 60000); }); } async initialize() { try { // Send initialize request const initResult = await this.sendRequest('initialize', { protocolVersion: '2024-11-05', capabilities: { tools: {} }, clientInfo: { name: 'grok-cli', version: '1.0.0' } }); this.serverInfo = { name: initResult.serverInfo?.name || 'Unknown', version: initResult.serverInfo?.version || 'Unknown', protocolVersion: initResult.protocolVersion || 'Unknown' }; // Send initialized notification await this.sendNotification('notifications/initialized'); // List available tools await this.listTools(); } catch (error) { throw new Error(`MCP initialization failed: ${error}`); } } async sendNotification(method, params) { if (!this.transport.isConnected()) { throw new Error('MCP server not connected'); } const notification = { jsonrpc: '2.0', method, params }; await this.transport.send(notification); } async listTools() { try { const result = await this.sendRequest('tools/list'); this.tools = result.tools || []; return this.tools; } catch (error) { console.warn('Failed to list MCP tools:', error); return []; } } async callTool(name, arguments_) { try { const result = await this.sendRequest('tools/call', { name, arguments: arguments_ }); return result; } catch (error) { throw new Error(`Tool call failed for ${name}: ${error}`); } } getAvailableTools() { return [...this.tools]; } getServerInfo() { return this.serverInfo; } isConnected() { return this.transport.isConnected(); } async disconnect() { // Send shutdown request if still connected if (this.transport.isConnected()) { try { await this.sendRequest('shutdown'); await this.sendNotification('exit'); } catch (error) { // Ignore shutdown errors } } await this.transport.disconnect(); this.pendingRequests.clear(); this.tools = []; this.serverInfo = null; } } exports.McpProtocolClient = McpProtocolClient; //# sourceMappingURL=mcp-protocol-client.js.map