@vibe-kit/grok-cli
Version:
An open-source AI agent that brings the power of Grok directly into your terminal.
152 lines • 6.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.McpClient = void 0;
const settings_1 = require("../utils/settings");
const mcp_protocol_client_1 = require("./mcp-protocol-client");
class McpClient {
constructor() {
this.connections = new Map();
this.initialized = false;
}
async initialize() {
if (this.initialized)
return;
const servers = (0, settings_1.listMcpServers)();
// Connect to servers sequentially to avoid resource conflicts
for (const [name, server] of Object.entries(servers)) {
try {
await this.connectToServer(name, server);
}
catch (error) {
console.warn(`Failed to connect to MCP server '${name}':`, error);
}
}
this.initialized = true;
}
async connectToServer(name, server, retryCount = 0) {
const maxRetries = name === 'github' ? 2 : 1; // Give GitHub extra retries due to Docker startup
try {
// Auto-detect transport based on server configuration
let transport = server.transport;
let url = server.url || server.serverUrl;
// If URL is provided and starts with http, use SSE transport
if (url && (url.startsWith('http://') || url.startsWith('https://'))) {
transport = 'sse';
}
// Default to stdio if no transport specified
if (!transport) {
transport = 'stdio';
}
if (transport === 'stdio' && !server.command) {
throw new Error('Server command is required for stdio transport');
}
if (transport === 'sse' && !url) {
throw new Error('Server URL is required for SSE transport');
}
console.log(`🔌 Connecting to MCP server '${name}'${retryCount > 0 ? ` (retry ${retryCount})` : ''}...`);
// Create MCP protocol client
const client = new mcp_protocol_client_1.McpProtocolClient({
command: server.command,
url: url,
args: server.args || [],
env: server.env || {},
headers: server.headers || {},
transport
});
const connection = {
server,
client,
tools: [],
connected: false
};
// Connect to the server
await client.connect();
// Get available tools
const tools = await client.listTools();
connection.tools = tools;
connection.connected = true;
console.log(`✅ Connected to MCP server '${name}' (${tools.length} tools available)`);
this.connections.set(name, connection);
}
catch (error) {
if (retryCount < maxRetries) {
console.warn(`⚠️ MCP server '${name}' failed (attempt ${retryCount + 1}/${maxRetries + 1}), retrying...`);
// Wait a bit before retrying (especially for Docker)
await new Promise(resolve => setTimeout(resolve, 5000));
return this.connectToServer(name, server, retryCount + 1);
}
else {
console.warn(`❌ Failed to connect to MCP server '${name}' after ${maxRetries + 1} attempts:`, error);
}
// Don't throw - continue with other servers
}
}
async executeTool(toolName, parameters) {
// Find which server has this tool
for (const [serverName, connection] of this.connections) {
if (connection.connected && connection.tools.some(tool => tool.name === toolName)) {
return await this.executeToolOnServer(serverName, toolName, parameters);
}
}
throw new Error(`Tool '${toolName}' not found in any connected MCP server`);
}
async executeToolOnServer(serverName, toolName, parameters) {
const connection = this.connections.get(serverName);
if (!connection || !connection.connected) {
throw new Error(`MCP server '${serverName}' is not connected`);
}
try {
const result = await connection.client.callTool(toolName, parameters);
return {
success: !result.isError,
data: result.content || result.result,
error: result.isError ? result.content?.[0]?.text || 'Tool execution failed' : undefined
};
}
catch (error) {
return {
success: false,
error: error.message
};
}
}
getAvailableTools() {
const tools = [];
for (const connection of this.connections.values()) {
if (connection.connected) {
for (const mcpTool of connection.tools) {
tools.push({
type: 'function',
function: {
name: mcpTool.name,
description: mcpTool.description,
parameters: mcpTool.inputSchema
}
});
}
}
}
return tools;
}
async disconnect() {
const disconnectPromises = [];
for (const connection of this.connections.values()) {
if (connection.connected) {
disconnectPromises.push(connection.client.disconnect());
}
}
await Promise.allSettled(disconnectPromises);
this.connections.clear();
this.initialized = false;
}
getConnectedServers() {
return Array.from(this.connections.entries())
.filter(([_, connection]) => connection.connected)
.map(([name, _]) => name);
}
isInitialized() {
return this.initialized;
}
}
exports.McpClient = McpClient;
//# sourceMappingURL=mcp-client.js.map