We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/code-and-relax/robloxstudio-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import { v4 as uuidv4 } from 'uuid';
export class BridgeService {
pendingRequests = new Map();
requestTimeout = 30000;
_pollWaiters = [];
async sendRequest(endpoint, data) {
const requestId = uuidv4();
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
if (this.pendingRequests.has(requestId)) {
this.pendingRequests.delete(requestId);
reject(new Error('Request timeout'));
}
}, this.requestTimeout);
const request = {
id: requestId,
endpoint,
data,
timestamp: Date.now(),
resolve,
reject,
timeoutId,
claimed: false
};
this.pendingRequests.set(requestId, request);
this._notifyWaiters();
});
}
getPendingRequest() {
let oldestRequest = null;
for (const request of this.pendingRequests.values()) {
if (request.claimed) continue;
if (!oldestRequest || request.timestamp < oldestRequest.timestamp) {
oldestRequest = request;
}
}
if (oldestRequest) {
oldestRequest.claimed = true;
return {
requestId: oldestRequest.id,
request: {
endpoint: oldestRequest.endpoint,
data: oldestRequest.data
}
};
}
return null;
}
waitForRequest(timeout = 25000) {
const existing = this.getPendingRequest();
if (existing) {
return Promise.resolve(existing);
}
return new Promise((resolve) => {
const timer = setTimeout(() => {
const idx = this._pollWaiters.indexOf(waiter);
if (idx !== -1) this._pollWaiters.splice(idx, 1);
resolve(null);
}, timeout);
const waiter = { resolve, timer };
this._pollWaiters.push(waiter);
});
}
_notifyWaiters() {
while (this._pollWaiters.length > 0) {
const waiter = this._pollWaiters.shift();
clearTimeout(waiter.timer);
const request = this.getPendingRequest();
if (request) {
waiter.resolve(request);
return;
} else {
waiter.resolve(null);
}
}
}
unclaimRequest(requestId) {
const request = this.pendingRequests.get(requestId);
if (request) {
request.claimed = false;
this._notifyWaiters();
}
}
resolveRequest(requestId, response) {
const request = this.pendingRequests.get(requestId);
if (request) {
clearTimeout(request.timeoutId);
this.pendingRequests.delete(requestId);
request.resolve(response);
}
}
rejectRequest(requestId, error) {
const request = this.pendingRequests.get(requestId);
if (request) {
clearTimeout(request.timeoutId);
this.pendingRequests.delete(requestId);
request.reject(error);
}
}
cleanupOldRequests() {
const now = Date.now();
for (const [id, request] of this.pendingRequests.entries()) {
if (now - request.timestamp > this.requestTimeout) {
clearTimeout(request.timeoutId);
this.pendingRequests.delete(id);
request.reject(new Error('Request timeout'));
}
}
}
clearAllPendingRequests() {
for (const [, request] of this.pendingRequests.entries()) {
clearTimeout(request.timeoutId);
request.reject(new Error('Connection closed'));
}
this.pendingRequests.clear();
while (this._pollWaiters.length > 0) {
const waiter = this._pollWaiters.shift();
clearTimeout(waiter.timer);
waiter.resolve(null);
}
}
}