Skip to main content
Glama

Puppeteer Real Browser MCP Server

by withLinda
system-utils.ts•6.41 kB
// Removed duplicate import - using standard setTimeout // Generic error handling wrapper export async function withErrorHandling<T>( operation: () => Promise<T>, errorMessage: string ): Promise<T> { try { return await operation(); } catch (error) { console.error(`${errorMessage}:`, error); throw new Error(`${errorMessage}: ${error instanceof Error ? error.message : String(error)}`); } } // Generic retry wrapper with exponential backoff (browser-agnostic version) export async function withRetry<T>( operation: () => Promise<T>, options: { maxRetries?: number; delay?: number; context?: string; shouldRetry?: (error: Error, attempt: number) => boolean; } = {} ): Promise<T> { const { maxRetries = 3, delay = 1000, context = 'unknown', shouldRetry = () => true } = options; let lastError: Error; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); console.error(`Attempt ${attempt}/${maxRetries} failed in context ${context}:`, lastError.message); // Check if we should retry this error if (!shouldRetry(lastError, attempt) || attempt === maxRetries) { break; } // Wait before retry with exponential backoff const waitTime = delay * Math.pow(2, attempt - 1); await new Promise(resolve => setTimeout(resolve, waitTime)); } } throw lastError!; } // Platform detection utilities export function getPlatform(): NodeJS.Platform { return process.platform; } export function isWindows(): boolean { return process.platform === 'win32'; } export function isMacOS(): boolean { return process.platform === 'darwin'; } export function isLinux(): boolean { return process.platform === 'linux'; } // Environment variable utilities export function getEnvVar(name: string, defaultValue?: string): string | undefined { return process.env[name] || defaultValue; } export function requireEnvVar(name: string): string { const value = process.env[name]; if (!value) { throw new Error(`Required environment variable ${name} is not set`); } return value; } // Process management utilities export async function executeCommand( command: string, args: string[] = [], options: { timeout?: number; encoding?: BufferEncoding; stdio?: 'ignore' | 'inherit' | 'pipe'; } = {} ): Promise<string> { const { execSync } = require('child_process'); const { timeout = 5000, encoding = 'utf8', stdio = 'pipe' } = options; try { const result = execSync(`${command} ${args.join(' ')}`, { encoding, timeout, stdio }); return result.toString(); } catch (error) { throw new Error(`Command execution failed: ${error instanceof Error ? error.message : String(error)}`); } } // Sleep/delay utility export async function sleep(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } // Timeout wrapper for any async operation export async function withTimeout<T>( operation: () => Promise<T>, timeoutMs: number, context: string = 'unknown' ): Promise<T> { return new Promise<T>((resolve, reject) => { const timer = setTimeout(() => { reject(new Error(`Operation timed out after ${timeoutMs}ms in context: ${context}`)); }, timeoutMs); operation() .then((result) => { clearTimeout(timer); resolve(result); }) .catch((error) => { clearTimeout(timer); reject(error); }); }); } // Generic validation utilities export function validateRequired<T>(value: T | undefined | null, fieldName: string): T { if (value === undefined || value === null) { throw new Error(`Required field '${fieldName}' is missing`); } return value; } export function validateString(value: unknown, fieldName: string): string { if (typeof value !== 'string') { throw new Error(`Field '${fieldName}' must be a string, got ${typeof value}`); } return value; } export function validateNumber(value: unknown, fieldName: string): number { if (typeof value !== 'number' || isNaN(value)) { throw new Error(`Field '${fieldName}' must be a valid number, got ${typeof value}`); } return value; } export function validateBoolean(value: unknown, fieldName: string): boolean { if (typeof value !== 'boolean') { throw new Error(`Field '${fieldName}' must be a boolean, got ${typeof value}`); } return value; } // Object utilities export function deepClone<T>(obj: T): T { if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()) as unknown as T; } if (Array.isArray(obj)) { return obj.map(item => deepClone(item)) as unknown as T; } const cloned = {} as T; for (const key in obj) { if (obj.hasOwnProperty(key)) { cloned[key] = deepClone(obj[key]); } } return cloned; } export function isEmptyObject(obj: object): boolean { return Object.keys(obj).length === 0; } // String utilities export function escapeRegExp(string: string): string { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); } export function slugify(str: string): string { return str .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, ''); } // Array utilities export function unique<T>(array: T[]): T[] { return [...new Set(array)]; } export function chunk<T>(array: T[], size: number): T[][] { const chunks: T[][] = []; for (let i = 0; i < array.length; i += size) { chunks.push(array.slice(i, i + size)); } return chunks; } // Type guards export function isString(value: unknown): value is string { return typeof value === 'string'; } export function isNumber(value: unknown): value is number { return typeof value === 'number' && !isNaN(value); } export function isBoolean(value: unknown): value is boolean { return typeof value === 'boolean'; } export function isObject(value: unknown): value is Record<string, unknown> { return typeof value === 'object' && value !== null && !Array.isArray(value); } export function isArray<T>(value: unknown): value is T[] { return Array.isArray(value); }

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/withLinda/puppeteer-real-browser-mcp-server'

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