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);
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it inspects 'recent' network requests (implying a time-bound scope), captures network errors missed by console tools, and is DevTools-like (suggesting detailed network data). However, it lacks details on permissions, rate limits, or whether it's read-only/destructive, leaving some behavioral aspects unclear for a tool with no annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, with two sentences that efficiently convey purpose and usage. Every sentence earns its place: the first states the action and primary use case, and the second adds critical behavioral context about capturing network errors. There is no wasted text or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, no annotations, no output schema), the description is mostly complete. It clearly defines the tool's purpose and usage context, but lacks details on output format, error handling, or authentication needs. However, it compensates somewhat by specifying the debugging focus and network error capture, making it adequate though not fully comprehensive for a tool with no structured behavioral data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description does not add any parameter-specific semantics beyond what the schema provides (e.g., it doesn't explain urlFilter patterns or details field implications). With high schema coverage, the baseline score of 3 is appropriate, as the description doesn't compensate but also doesn't detract from the schema's documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Inspect recent browser network requests') and resource ('browser network requests'), distinguishing it from siblings like browser.console.read or browser.screenshot by focusing on network debugging rather than console output or visual capture. It specifies the DevTools-like nature and debugging context for HTTP failures, payloads, and request sequences.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool ('Use for debugging HTTP failures (4xx/5xx), payloads, and request sequences') and provides a key exclusion ('Note: This captures network errors that console tools miss'), which distinguishes it from browser.console.read. It also implies alternatives by mentioning what console tools might miss, guiding the agent away from using console-based tools for network error inspection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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