Skip to main content
Glama
index.jsโ€ข7.93 kB
'use strict'; var protocolHttp = require('@smithy/protocol-http'); var querystringBuilder = require('@smithy/querystring-builder'); var utilBase64 = require('@smithy/util-base64'); function createRequest(url, requestOptions) { return new Request(url, requestOptions); } function requestTimeout(timeoutInMs = 0) { return new Promise((resolve, reject) => { if (timeoutInMs) { setTimeout(() => { const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`); timeoutError.name = "TimeoutError"; reject(timeoutError); }, timeoutInMs); } }); } const keepAliveSupport = { supported: undefined, }; class FetchHttpHandler { config; configProvider; static create(instanceOrOptions) { if (typeof instanceOrOptions?.handle === "function") { return instanceOrOptions; } return new FetchHttpHandler(instanceOrOptions); } constructor(options) { if (typeof options === "function") { this.configProvider = options().then((opts) => opts || {}); } else { this.config = options ?? {}; this.configProvider = Promise.resolve(this.config); } if (keepAliveSupport.supported === undefined) { keepAliveSupport.supported = Boolean(typeof Request !== "undefined" && "keepalive" in createRequest("https://[::1]")); } } destroy() { } async handle(request, { abortSignal, requestTimeout: requestTimeout$1 } = {}) { if (!this.config) { this.config = await this.configProvider; } const requestTimeoutInMs = requestTimeout$1 ?? this.config.requestTimeout; const keepAlive = this.config.keepAlive === true; const credentials = this.config.credentials; if (abortSignal?.aborted) { const abortError = new Error("Request aborted"); abortError.name = "AbortError"; return Promise.reject(abortError); } let path = request.path; const queryString = querystringBuilder.buildQueryString(request.query || {}); if (queryString) { path += `?${queryString}`; } if (request.fragment) { path += `#${request.fragment}`; } let auth = ""; if (request.username != null || request.password != null) { const username = request.username ?? ""; const password = request.password ?? ""; auth = `${username}:${password}@`; } const { port, method } = request; const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path}`; const body = method === "GET" || method === "HEAD" ? undefined : request.body; const requestOptions = { body, headers: new Headers(request.headers), method: method, credentials, }; if (this.config?.cache) { requestOptions.cache = this.config.cache; } if (body) { requestOptions.duplex = "half"; } if (typeof AbortController !== "undefined") { requestOptions.signal = abortSignal; } if (keepAliveSupport.supported) { requestOptions.keepalive = keepAlive; } if (typeof this.config.requestInit === "function") { Object.assign(requestOptions, this.config.requestInit(request)); } let removeSignalEventListener = () => { }; const fetchRequest = createRequest(url, requestOptions); const raceOfPromises = [ fetch(fetchRequest).then((response) => { const fetchHeaders = response.headers; const transformedHeaders = {}; for (const pair of fetchHeaders.entries()) { transformedHeaders[pair[0]] = pair[1]; } const hasReadableStream = response.body != undefined; if (!hasReadableStream) { return response.blob().then((body) => ({ response: new protocolHttp.HttpResponse({ headers: transformedHeaders, reason: response.statusText, statusCode: response.status, body, }), })); } return { response: new protocolHttp.HttpResponse({ headers: transformedHeaders, reason: response.statusText, statusCode: response.status, body: response.body, }), }; }), requestTimeout(requestTimeoutInMs), ]; if (abortSignal) { raceOfPromises.push(new Promise((resolve, reject) => { const onAbort = () => { const abortError = new Error("Request aborted"); abortError.name = "AbortError"; reject(abortError); }; if (typeof abortSignal.addEventListener === "function") { const signal = abortSignal; signal.addEventListener("abort", onAbort, { once: true }); removeSignalEventListener = () => signal.removeEventListener("abort", onAbort); } else { abortSignal.onabort = onAbort; } })); } return Promise.race(raceOfPromises).finally(removeSignalEventListener); } updateHttpClientConfig(key, value) { this.config = undefined; this.configProvider = this.configProvider.then((config) => { config[key] = value; return config; }); } httpHandlerConfigs() { return this.config ?? {}; } } const streamCollector = async (stream) => { if ((typeof Blob === "function" && stream instanceof Blob) || stream.constructor?.name === "Blob") { if (Blob.prototype.arrayBuffer !== undefined) { return new Uint8Array(await stream.arrayBuffer()); } return collectBlob(stream); } return collectStream(stream); }; async function collectBlob(blob) { const base64 = await readToBase64(blob); const arrayBuffer = utilBase64.fromBase64(base64); return new Uint8Array(arrayBuffer); } async function collectStream(stream) { const chunks = []; const reader = stream.getReader(); let isDone = false; let length = 0; while (!isDone) { const { done, value } = await reader.read(); if (value) { chunks.push(value); length += value.length; } isDone = done; } const collected = new Uint8Array(length); let offset = 0; for (const chunk of chunks) { collected.set(chunk, offset); offset += chunk.length; } return collected; } function readToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { if (reader.readyState !== 2) { return reject(new Error("Reader aborted too early")); } const result = (reader.result ?? ""); const commaIndex = result.indexOf(","); const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length; resolve(result.substring(dataOffset)); }; reader.onabort = () => reject(new Error("Read aborted")); reader.onerror = () => reject(reader.error); reader.readAsDataURL(blob); }); } exports.FetchHttpHandler = FetchHttpHandler; exports.keepAliveSupport = keepAliveSupport; exports.streamCollector = streamCollector;

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/consigcody94/office-whisperer'

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