minimax-mcp-tools
Version:
Async MCP server with Minimax API integration for image generation and text-to-speech
97 lines • 3.64 kB
JavaScript
import fetch from 'node-fetch';
import { ConfigManager } from '../config/config-manager.js';
import { API_CONFIG } from '../config/constants.js';
import { ErrorHandler } from '../utils/error-handler.js';
export class MinimaxBaseClient {
config;
baseURL;
timeout;
retryConfig;
constructor(options = {}) {
this.config = ConfigManager.getInstance();
this.baseURL = options.baseURL || API_CONFIG.BASE_URL;
this.timeout = options.timeout || API_CONFIG.TIMEOUT;
this.retryConfig = this.config.getRetryConfig();
}
async makeRequest(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const headers = {
'Authorization': `Bearer ${this.config.getApiKey()}`,
'Content-Type': 'application/json',
...API_CONFIG.HEADERS,
...options.headers
};
const requestOptions = {
method: options.method || 'POST',
headers,
timeout: this.timeout,
...options
};
if (options.body && requestOptions.method !== 'GET') {
requestOptions.body = JSON.stringify(options.body);
}
return this.executeWithRetry(url, requestOptions);
}
async executeWithRetry(url, requestOptions, attempt = 1) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = await fetch(url, {
...requestOptions,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const data = await response.json();
return this.processResponse(data);
}
catch (error) {
const processedError = ErrorHandler.handleAPIError(error);
if (this.shouldRetry(processedError, attempt)) {
await this.delay(this.retryConfig.delay * attempt);
return this.executeWithRetry(url, requestOptions, attempt + 1);
}
throw processedError;
}
}
processResponse(data) {
if (data.base_resp && data.base_resp.status_code !== 0) {
throw ErrorHandler.handleAPIError(new Error('API Error'), data);
}
return data;
}
shouldRetry(error, attempt) {
if (attempt >= this.retryConfig.attempts) {
return false;
}
return (error.code === 'NETWORK_ERROR' ||
error.code === 'TIMEOUT_ERROR' ||
('statusCode' in error && typeof error.statusCode === 'number' && error.statusCode >= 500 && error.statusCode < 600));
}
async delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async get(endpoint, options = {}) {
return this.makeRequest(endpoint, { ...options, method: 'GET' });
}
async post(endpoint, body, options = {}) {
return this.makeRequest(endpoint, { ...options, method: 'POST', body });
}
async healthCheck() {
try {
await this.get('/health');
return { status: 'healthy', timestamp: new Date().toISOString() };
}
catch (error) {
return {
status: 'unhealthy',
error: ErrorHandler.formatErrorForUser(error),
timestamp: new Date().toISOString()
};
}
}
}
//# sourceMappingURL=base-client.js.map