Skip to main content
Glama
Winds-AI

autonomous-frontend-browser-tools

browser.network.inspect

Debug HTTP failures, analyze request payloads, and inspect network sequences by capturing recent browser network requests, including errors missed by console tools.

Instructions

Inspect recent browser network requests (DevTools-like). Use for debugging HTTP failures (4xx/5xx), payloads, and request sequences. Note: This captures network errors that console tools miss.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlFilterYesSubstring or pattern to filter request URLs. Tips: Use partial matches; try singular/plural variants if empty.
detailsYesFields to include for each entry. 'timestamp' is useful for chronological ordering.
timeOffsetNoRelative window in seconds (e.g., 300 = last 5 minutes, max 86400).
orderByNoSort fieldtimestamp
orderDirectionNoSort directiondesc
limitNoMax entries to return

Implementation Reference

  • MCP server tool registration for 'browser.network.inspect' including description, input schema (zod), and reference to handler function.
    server.tool( "browser.network.inspect", "Inspect recent browser network requests (DevTools-like). Use for debugging HTTP failures (4xx/5xx), payloads, and request sequences. Note: This captures network errors that console tools miss.", { urlFilter: z .string() .describe( "Substring or pattern to filter request URLs. Tips: Use partial matches; try singular/plural variants if empty." ), details: z .array( z.enum([ "url", "method", "status", "timestamp", "requestHeaders", "responseHeaders", "requestBody", "responseBody", ]) ) .min(1) .describe( "Fields to include for each entry. 'timestamp' is useful for chronological ordering." ), timeOffset: z .number() .optional() .describe( "Relative window in seconds (e.g., 300 = last 5 minutes, max 86400)." ), orderBy: z .enum(["timestamp", "url"]) .optional() .default("timestamp") .describe("Sort field"), orderDirection: z .enum(["asc", "desc"]) .optional() .default("desc") .describe("Sort direction"), limit: z.number().optional().default(20).describe("Max entries to return"), }, handleInspectBrowserNetworkActivity );
  • MCP tool handler: processes parameters, builds query for backend /network-request-details endpoint, fetches and formats results, handles empty results with suggestions.
    async function handleInspectBrowserNetworkActivity(params: any) { const { urlFilter, details, timeOffset, orderBy, orderDirection, limit } = params; const currentTime = Date.now(); let finalTimeStart: number | undefined; let finalTimeEnd: number | undefined; if (timeOffset !== undefined) { if (timeOffset <= 0) { throw new Error("timeOffset must be a positive number"); } if (timeOffset > 86400) { throw new Error("timeOffset cannot exceed 24 hours (86400 seconds)"); } finalTimeStart = currentTime - timeOffset * 1000; finalTimeEnd = currentTime; console.log( `Time offset calculation: ${timeOffset}s ago = ${new Date( finalTimeStart ).toISOString()} to ${new Date(finalTimeEnd).toISOString()}` ); } const queryString = `?urlFilter=${encodeURIComponent( urlFilter )}&details=${details.join(",")}&includeTimestamp=true${ finalTimeStart ? `&timeStart=${finalTimeStart}` : "" }${finalTimeEnd ? `&timeEnd=${finalTimeEnd}` : ""}&orderBy=${ orderBy || "timestamp" }&orderDirection=${orderDirection || "desc"}&limit=${limit || 20}`; const targetUrl = `http://${discoveredHost}:${discoveredPort}/network-request-details${queryString}`; console.log(`MCP Tool: Fetching network details from ${targetUrl}`); return await withServerConnection(async () => { try { const response = await fetch(targetUrl); if (!response.ok) { const errorText = await response.text(); throw new Error( `Server returned ${response.status}: ${ errorText || response.statusText }` ); } const json = await response.json(); const results = json; if (Array.isArray(results) && results.length === 0) { const suggestions = generateSearchSuggestions(urlFilter); return { content: [ { type: "text", text: `No API calls found matching '${urlFilter}'. Try these search strategies:\n\n${suggestions.join( "\n" )}`, }, ], } as any; } return { content: [ { type: "text", text: JSON.stringify(results, null, 2), }, ], } as any; } catch (error: any) { console.error("Error fetching network request details:", error); return { content: [ { type: "text", text: `Failed to get network request details: ${error.message}`, }, ], isError: true, } as any; } }); }
  • Backend Express endpoint handler for /network-request-details: parses query params, applies filter/sort/project/limit using helpers from network-activity.ts on cached logs.
    app.get("/network-request-details", (req, res) => { if ((process.env.LOG_LEVEL || "info").toLowerCase() === "debug") { console.log("[debug] /network-request-details hit", req.query); } try { const urlFilter = String(req.query.urlFilter ?? ""); const detailsCsv = String(req.query.details ?? "url,method,status"); const details = detailsCsv .split(",") .filter(Boolean) as any as NetworkFilterParams["details"]; const includeTimestamp = String(req.query.includeTimestamp ?? "true") === "true"; const timeStart = req.query.timeStart ? Number(req.query.timeStart) : undefined; const timeEnd = req.query.timeEnd ? Number(req.query.timeEnd) : undefined; const orderBy = String( req.query.orderBy ?? "timestamp" ) as any as NetworkFilterParams["orderBy"]; const orderDirection = String( req.query.orderDirection ?? "desc" ) as any as NetworkFilterParams["orderDirection"]; const limit = req.query.limit ? Number(req.query.limit) : 20; let results = filterNetworkLogs(detailedNetworkLogCache, { urlFilter, timeStart, timeEnd, }); results = sortNetworkLogs(results, orderBy, orderDirection); const projected = projectNetworkLogDetails( results, details, includeTimestamp ); const limited = limitResults(projected, limit); res.json(limited); } catch (e: any) { res .status(500) .json({ error: e?.message || "Failed to read network details" }); } });
  • Helper functions for network log processing: filtering by URL/time, sorting by timestamp/url, projecting specific details, and limiting results.
    export function filterNetworkLogs< T extends { url?: string; timestamp?: number } >( logs: T[], params: Pick<NetworkFilterParams, "urlFilter" | "timeStart" | "timeEnd"> ): T[] { const term = (params.urlFilter || "").toLowerCase(); return logs.filter((log) => { const urlMatch = term ? (log.url || "").toLowerCase().includes(term) : true; const ts = typeof log.timestamp === "number" ? log.timestamp : undefined; const afterStart = params.timeStart ? ts ? ts >= params.timeStart : false : true; const beforeEnd = params.timeEnd ? ts ? ts <= params.timeEnd : false : true; return urlMatch && afterStart && beforeEnd; }); } /** * Sort logs by timestamp or url with direction. */ export function sortNetworkLogs<T extends { timestamp?: number; url?: string }>( logs: T[], orderBy: OrderByField = "timestamp", orderDirection: OrderDirection = "desc" ): T[] { const sorted = [...logs]; sorted.sort((a, b) => { if (orderBy === "url") { const ua = (a.url || "").toLowerCase(); const ub = (b.url || "").toLowerCase(); const cmp = ua.localeCompare(ub); return orderDirection === "asc" ? cmp : -cmp; } else { const ta = typeof a.timestamp === "number" ? a.timestamp : 0; const tb = typeof b.timestamp === "number" ? b.timestamp : 0; const cmp = ta - tb; return orderDirection === "asc" ? cmp : -cmp; } }); return sorted; } /** * Project only requested details to reduce payload size. */ export function projectNetworkLogDetails( logs: any[], details: DetailKey[], includeTimestamp: boolean = true ): any[] { const want = new Set(details); return logs.map((log) => { const out: any = {}; if (want.has("url")) out.url = log.url; if (want.has("method")) out.method = log.method; if (want.has("status")) out.status = log.status; if (includeTimestamp) out.timestamp = log.timestamp; if (want.has("requestHeaders")) out.requestHeaders = log.requestHeaders; if (want.has("responseHeaders")) out.responseHeaders = log.responseHeaders; if (want.has("requestBody")) out.requestBody = log.requestBody; if (want.has("responseBody")) out.responseBody = log.responseBody; return out; }); } /** * Enforce a hard limit on number of results. */ export function limitResults<T>(logs: T[], limit: number = 20): T[] { if (limit <= 0) return []; return logs.slice(0, limit); }

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/Winds-AI/Frontend-development-MCP-tools-public'

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