UNPKG

giga-code

Version:

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

211 lines 6.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpMcpClient = void 0; class HttpMcpClient { constructor(server) { this.messageId = 0; this.isConnected = false; this.serverInfo = null; this.server = server; } async connect() { if (this.server.type !== 'http') { throw new Error('HttpMcpClient can only connect to HTTP servers'); } try { // Test connection by calling initialize await this.initialize(); this.isConnected = true; } catch (error) { throw new Error(`Failed to connect to HTTP MCP server ${this.server.name}: ${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 (for HTTP servers that need it) try { await this.sendRequest('initialized', {}); } catch (error) { // Some servers may not implement initialized, ignore errors } // 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) { this.serverInfo.resources = []; } } async sendRequest(method, params) { if (!this.server.httpUrl) { throw new Error('HTTP URL not configured for server'); } const id = ++this.messageId; const request = { jsonrpc: '2.0', id, method, params, }; try { const response = await fetch(this.server.httpUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json, text/event-stream', }, body: JSON.stringify(request), }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } // Handle Server-Sent Events response if (response.headers.get('content-type')?.includes('text/event-stream')) { return await this.parseServerSentEvents(response); } // Handle regular JSON response const jsonResponse = await response.json(); if (jsonResponse.error) { throw new Error(`JSON-RPC Error: ${jsonResponse.error.message}`); } return jsonResponse.result; } catch (error) { if (error instanceof Error) { throw error; } throw new Error(`Request failed: ${String(error)}`); } } async parseServerSentEvents(response) { const reader = response.body?.getReader(); if (!reader) { throw new Error('No response body available'); } const decoder = new TextDecoder(); let buffer = ''; let result = null; try { while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); // Process complete events const lines = buffer.split('\n'); buffer = lines.pop() || ''; // Keep incomplete line in buffer for (const line of lines) { if (line.startsWith('data: ')) { try { const data = JSON.parse(line.slice(6)); if (data.jsonrpc === '2.0') { if (data.error) { throw new Error(`JSON-RPC Error: ${data.error.message}`); } result = data.result; } } catch (error) { } } } } } finally { reader.releaseLock(); } return result; } 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 HTTP MCP 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() { this.isConnected = false; this.serverInfo = null; } isConnectedToServer() { return this.isConnected; } async healthCheck() { if (!this.server.httpUrl) { return false; } try { const response = await fetch(this.server.httpUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'ping', params: {}, }), }); return response.ok; } catch (error) { return false; } } } exports.HttpMcpClient = HttpMcpClient; //# sourceMappingURL=http-mcp-client.js.map