Skip to main content
Glama
http.ts2.44 kB
import { request } from 'undici'; import { logger } from './log.js'; export type RequestOptions = { method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; headers?: Record<string, string>; body?: string | Uint8Array; timeoutMs?: number; retries?: number; backoffMs?: number; }; const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); export async function requestJson(url: string, opts: RequestOptions = {}) { const method = opts.method || 'GET'; const headers = { Accept: 'application/json', ...(opts.body ? { 'Content-Type': 'application/json' } : {}), ...(opts.headers || {}), } as Record<string, string>; const timeoutMs = opts.timeoutMs ?? 5000; const retries = opts.retries ?? 2; const baseBackoff = opts.backoffMs ?? 200; let attempt = 0; // eslint-disable-next-line no-constant-condition while (true) { const controller = new AbortController(); const to = setTimeout(() => controller.abort(new Error('Request timeout')), timeoutMs); try { logger.debug('http request', { method, url: tryRedactUrl(url), timeoutMs, attempt: attempt + 1, }); const res = await request(url, { method, headers, body: opts.body, signal: controller.signal }); clearTimeout(to); const data = await res.body.json(); const status = res.statusCode; const hdrs = res.headers; if (status >= 500 || status === 429) { if (attempt < retries) { attempt++; const wait = baseBackoff * Math.pow(2, attempt - 1); logger.warn('http transient error, backing off', { status, waitMs: wait }); await sleep(wait); continue; } } logger.debug('http response', { status }); return { status, headers: hdrs, data }; } catch (err) { clearTimeout(to); if (attempt < retries) { attempt++; const wait = baseBackoff * Math.pow(2, attempt - 1); logger.warn('http error, retrying', { attempt, waitMs: wait, error: (err as Error).message }); await sleep(wait); continue; } logger.error('http request failed', { error: (err as Error).message }); throw err; } } } function tryRedactUrl(u: string) { try { const url = new URL(u); // Drop query to avoid leaking sensitive params url.search = ''; return url.toString(); } catch { return 'invalid-url'; } }

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/ashabbir/multi-mcp'

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