UNPKG

giga-code

Version:

A personal AI CLI assistant powered by Grok for local development.

207 lines 7.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.McpClient = void 0; const child_process_1 = require("child_process"); class McpClient { constructor(server) { this.process = null; this.messageId = 0; this.pendingRequests = new Map(); this.isConnected = false; this.serverInfo = null; this.server = server; } async connect() { return new Promise((resolve, reject) => { try { // Parse command and args const commandParts = this.server.command.split(' '); const command = commandParts[0]; const args = [...commandParts.slice(1), ...(this.server.args || [])]; // Spawn the MCP server process this.process = (0, child_process_1.spawn)(command, args, { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, ...this.server.env }, }); this.process.on('error', (error) => { reject(new Error(`Failed to start MCP server: ${error.message}`)); }); // Set up message handling let buffer = ''; this.process.stdout?.on('data', (data) => { buffer += data.toString(); // Process complete JSON-RPC messages let newlineIndex; while ((newlineIndex = buffer.indexOf('\n')) !== -1) { const line = buffer.slice(0, newlineIndex).trim(); buffer = buffer.slice(newlineIndex + 1); if (line) { try { const message = JSON.parse(line); this.handleMessage(message); } catch (error) { } } } }); this.process.stderr?.on('data', (data) => { // Suppress MCP server stderr logs }); this.process.on('close', (code) => { this.isConnected = false; if (code !== 0) { } }); // Initialize the connection this.initialize().then(() => { this.isConnected = true; resolve(); }).catch(reject); } catch (error) { reject(error); } }); } async initialize() { // Send initialize request const initResponse = await this.sendRequest('initialize', { protocolVersion: '2024-11-05', capabilities: { tools: {}, }, clientInfo: { name: 'giga-code', version: '1.0.0', }, }); this.serverInfo = { name: initResponse.serverInfo?.name || this.server.name, version: initResponse.serverInfo?.version || '1.0.0', }; // Send initialized notification this.sendNotification('initialized', {}); // Get available tools try { const toolsResponse = await this.sendRequest('tools/list', {}); if (toolsResponse.tools) { this.serverInfo.tools = toolsResponse.tools; } } catch (error) { this.serverInfo.tools = []; } // Get available resources try { const resourcesResponse = await this.sendRequest('resources/list', {}); if (resourcesResponse.resources) { this.serverInfo.resources = resourcesResponse.resources; } } catch (error) { // Many MCP servers don't implement resources/list - silently ignore "Method not found" errors const errorMessage = error instanceof Error ? error.message : String(error); if (!errorMessage.includes('Method not found')) { } this.serverInfo.resources = []; } } handleMessage(message) { if (message.id !== undefined && this.pendingRequests.has(message.id)) { // This is a response to a request const { resolve, reject } = this.pendingRequests.get(message.id); this.pendingRequests.delete(message.id); if (message.error) { reject(new Error(message.error.message || 'MCP error')); } else { resolve(message.result); } } else { // This is a notification or request from the server } } sendRequest(method, params) { return new Promise((resolve, reject) => { if (!this.process) { reject(new Error('MCP client process not started')); return; } const id = ++this.messageId; const message = { jsonrpc: '2.0', id, method, params, }; this.pendingRequests.set(id, { resolve, reject }); const messageStr = JSON.stringify(message) + '\n'; this.process.stdin?.write(messageStr); // Set timeout for requests setTimeout(() => { if (this.pendingRequests.has(id)) { this.pendingRequests.delete(id); reject(new Error('MCP request timeout')); } }, 30000); // 30 second timeout }); } sendNotification(method, params) { if (!this.process) { return; } const message = { jsonrpc: '2.0', method, params, }; const messageStr = JSON.stringify(message) + '\n'; this.process.stdin?.write(messageStr); } async callTool(name, arguments_) { try { const response = await this.sendRequest('tools/call', { name, arguments: arguments_, }); return { content: response.content || [], isError: response.isError || false, _meta: response._meta, }; } catch (error) { return { content: [{ type: 'text', text: `Error calling tool: ${error instanceof Error ? error.message : String(error)}`, }], isError: true, }; } } getServerInfo() { return this.serverInfo; } getTools() { return this.serverInfo?.tools || []; } getResources() { return this.serverInfo?.resources || []; } async disconnect() { if (this.process) { this.process.kill(); this.process = null; } this.isConnected = false; this.pendingRequests.clear(); } isConnectedToServer() { return this.isConnected; } } exports.McpClient = McpClient; //# sourceMappingURL=mcp-client.js.map