UNPKG

@grebyn/toolflow-mcp-server

Version:

MCP server for managing other MCP servers - discover, install, organize into bundles, and automate with workflows. Uses StreamableHTTP transport with dual OAuth/API key authentication.

105 lines 3.76 kB
/** * API Client for proxying requests to ToolFlow backend * * This client forwards authenticated requests to your Vercel API, * which handles all Supabase operations with proper credentials. */ import { getServerConfig } from '../config/server-config.js'; export class ApiClient { static apiEndpoint = getServerConfig().apiEndpoint; /** * Make an authenticated request to the ToolFlow API proxy */ static async proxyRequest(operation, params, context) { const url = `${this.apiEndpoint}/proxy`; const headers = { 'Content-Type': 'application/json', }; // Add authentication - prioritize API key over OAuth token if (context?.apiKey) { headers['Authorization'] = `Bearer ${context.apiKey}`; } else if (context?.token) { headers['Authorization'] = `Bearer ${context.token}`; } else { throw new Error('No authentication token or API key provided'); } const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify({ operation, params }) }); if (!response.ok) { const error = await response.text(); throw new Error(`API request failed (${response.status}): ${error}`); } return response.json(); } /** * Bundle operations */ static async searchBundles(params, context) { return this.proxyRequest('searchBundles', params, context); } static async createBundle(data, context) { return this.proxyRequest('createBundle', data, context); } static async updateBundle(bundleId, updates, context) { return this.proxyRequest('updateBundle', { bundleId, ...updates }, context); } static async getBundleConfig(bundleId, context) { return this.proxyRequest('getBundleConfig', { bundleId }, context); } /** * Workflow operations */ static async searchWorkflows(params, context) { return this.proxyRequest('searchWorkflows', params, context); } static async createWorkflow(data, context) { return this.proxyRequest('createWorkflow', data, context); } static async updateWorkflow(workflowId, updates, context) { return this.proxyRequest('updateWorkflow', { workflowId, ...updates }, context); } static async getWorkflow(workflowId, context) { return this.proxyRequest('getWorkflow', { workflowId }, context); } /** * Log MCP tool execution */ static async logExecution(logData, context) { try { const url = `${this.apiEndpoint}/mcp/logs`; const headers = { 'Content-Type': 'application/json', }; // Add authentication if (context?.apiKey) { headers['Authorization'] = `Bearer ${context.apiKey}`; } else if (context?.token) { headers['Authorization'] = `Bearer ${context.token}`; } else { console.error('No authentication for logging'); return; } // Fire and forget - don't await fetch(url, { method: 'POST', headers, body: JSON.stringify(logData) }).catch(error => { // Silently fail - logging should never break tool execution console.error('Failed to send log:', error); }); } catch (error) { // Silently fail - logging should never break tool execution console.error('Logging error:', error); } } } //# sourceMappingURL=api-client.js.map