Skip to main content
Glama
Leviathangk

Playwright MCP Server

by Leviathangk
network-capture.ts4.14 kB
import { Request, Response } from 'playwright'; /** * Network request data structure */ export interface NetworkRequest { id: string; timestamp: number; url: string; method: string; resourceType: string; request: { headers: Record<string, string>; postData?: string; }; response?: { status: number; statusText: string; headers: Record<string, string>; body?: string; }; } /** * Network capture manager for a session */ export class NetworkCapture { private requests: NetworkRequest[] = []; private maxRequests: number; private requestCounter = 0; constructor(maxRequests: number = 1000) { this.maxRequests = maxRequests; } /** * Add a request to the capture */ addRequest(request: Request): string { const requestId = `req-${++this.requestCounter}`; const networkRequest: NetworkRequest = { id: requestId, timestamp: Date.now(), url: request.url(), method: request.method(), resourceType: request.resourceType(), request: { headers: request.headers(), postData: request.postData() || undefined, }, }; this.requests.push(networkRequest); // Limit the number of stored requests if (this.requests.length > this.maxRequests) { this.requests.shift(); // Remove oldest request } return requestId; } /** * Update request with response data */ async updateResponse(requestId: string, response: Response): Promise<void> { const request = this.requests.find(r => r.id === requestId); if (!request) return; try { const body = await response.body(); request.response = { status: response.status(), statusText: response.statusText(), headers: response.headers(), body: body.toString('utf-8'), }; } catch (error) { // Response body might not be available request.response = { status: response.status(), statusText: response.statusText(), headers: response.headers(), }; } } /** * Get all requests */ getRequests(): NetworkRequest[] { return this.requests; } /** * Clear all requests */ clear(): void { this.requests = []; } /** * Search requests by keyword (supports regex) */ searchRequests( keyword: string, searchIn: ('url' | 'request' | 'response')[], isRegex: boolean = false ): NetworkRequest[] { const pattern = isRegex ? new RegExp(keyword, 'i') : null; return this.requests.filter(req => { for (const field of searchIn) { if (field === 'url') { if (this.matchText(req.url, keyword, pattern)) return true; } else if (field === 'request') { const requestData = JSON.stringify(req.request); if (this.matchText(requestData, keyword, pattern)) return true; } else if (field === 'response' && req.response) { const responseData = JSON.stringify(req.response); if (this.matchText(responseData, keyword, pattern)) return true; } } return false; }); } /** * Match text against keyword or regex pattern */ private matchText(text: string, keyword: string, pattern: RegExp | null): boolean { if (pattern) { return pattern.test(text); } return text.toLowerCase().includes(keyword.toLowerCase()); } /** * Convert request to curl command */ toCurl(request: NetworkRequest): string { const parts: string[] = ['curl']; // Method if (request.method !== 'GET') { parts.push(`-X ${request.method}`); } // URL parts.push(`'${request.url}'`); // Headers for (const [key, value] of Object.entries(request.request.headers)) { // Skip some headers that curl adds automatically if (['host', 'content-length'].includes(key.toLowerCase())) continue; parts.push(`-H '${key}: ${value}'`); } // Body if (request.request.postData) { const body = request.request.postData.replace(/'/g, "'\\''"); parts.push(`-d '${body}'`); } return parts.join(' \\\n '); } }

Latest Blog Posts

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/Leviathangk/PlaywrightMCPForCrawler'

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