Skip to main content
Glama

Spotify Streamable MCP Server

by iceener
http-client.ts3.44 kB
import { config } from '../config/env.ts'; import { makeConcurrencyGate, makeTokenBucket } from '../utils/limits.ts'; import { logger } from '../utils/logger.ts'; export type HttpClientInput = string | URL | Request; export type HttpClient = ( input: HttpClientInput, init?: RequestInit, ) => Promise<Response>; export interface HttpClientOptions { baseHeaders?: Record<string, string>; timeout?: number; retries?: number; retryDelay?: number; rateLimit?: { rps: number; burst: number }; concurrency?: number; } export function createHttpClient(options: HttpClientOptions = {}): HttpClient { const { baseHeaders = {}, timeout = 30000, retries = 3, retryDelay = 1000, rateLimit = { rps: config.RPS_LIMIT, burst: config.RPS_LIMIT * 2 }, concurrency = config.CONCURRENCY_LIMIT, } = options; const rateLimiter = makeTokenBucket(rateLimit.burst, rateLimit.rps); const gate = makeConcurrencyGate(concurrency); return async (input: HttpClientInput, init?: RequestInit): Promise<Response> => { return gate(async () => { if (!rateLimiter.take()) { await logger.warning('http_client', { message: 'Rate limit exceeded' }); throw new Error('Rate limit exceeded'); } const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : (input as Request).url; const method = init?.method || 'GET'; await logger.debug('http_client', { message: 'HTTP request start', url, method, }); for (let attempt = 1; attempt <= retries; attempt++) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); const response = await fetch(url, { ...init, headers: { ...baseHeaders, ...init?.headers }, signal: controller.signal, }); clearTimeout(timeoutId); if (response.ok || attempt === retries) { await logger.info('http_client', { message: 'HTTP request completed', url, method, status: response.status, attempt, }); return response; } await logger.warning('http_client', { message: 'HTTP request failed, retrying', url, method, status: response.status, attempt, }); const delay = retryDelay * 2 ** (attempt - 1) + Math.random() * 1000; await new Promise((r) => setTimeout(r, delay)); } catch (error) { if (attempt === retries) { await logger.error('http_client', { message: 'HTTP request failed after retries', url, method, error: (error as Error).message, attempts: retries, }); throw error; } await logger.warning('http_client', { message: 'HTTP error, retrying', url, method, error: (error as Error).message, attempt, }); const delay = retryDelay * 2 ** (attempt - 1) + Math.random() * 1000; await new Promise((r) => setTimeout(r, delay)); } } throw new Error('Unexpected end of retry loop'); }); }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/iceener/spotify-streamable-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server