Skip to main content
Glama

interceptor_chrome_navigate

Navigate Chrome tabs for proxy traffic capture by specifying target instances and URLs, ensuring accurate interception when monitoring network activity.

Instructions

Navigate a tab in a specific Chrome instance launched by interceptor_chrome_launch using that instance's CDP target WebSocket. Prevents cross-instance mistakes when proxy capture is required.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
target_idYesTarget ID from interceptor_chrome_launch
urlYesDestination URL
page_target_idNoOptional page target ID from interceptor_chrome_cdp_info targets
wait_for_proxy_captureNoWait for matching proxy traffic after navigate (default: true)
timeout_msNoMax wait for CDP response and proxy capture (default: 5000ms)
poll_interval_msNoPolling interval while waiting for proxy capture (default: 200ms)

Implementation Reference

  • The handler function for "interceptor_chrome_navigate" which performs the navigation and optionally waits for proxy traffic.
    async ({ target_id, url, page_target_id, wait_for_proxy_capture, timeout_ms, poll_interval_ms }) => {
      try {
        const chrome = interceptorManager.get("chrome");
        if (!chrome) {
          return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: "Chrome interceptor not registered." }) }] };
        }
    
        const meta = await chrome.getMetadata();
        const target = meta.activeTargets.find((t) => t.id === target_id);
        if (!target) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ status: "error", error: `Chrome target '${target_id}' not found. Is it still running?` }),
            }],
          };
        }
    
        // Chrome interceptor stores CDP port in details.port
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const details: any = target.details ?? {};
        const port = details.port;
        if (typeof port !== "number" || !Number.isFinite(port) || port <= 0) {
          return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: `Chrome target '${target_id}' has no valid CDP port.` }) }] };
        }
    
        await waitForCdpVersion(port, {
          timeoutMs: timeout_ms,
          intervalMs: Math.max(50, Math.min(500, poll_interval_ms)),
          requestTimeoutMs: Math.min(1000, Math.max(100, poll_interval_ms)),
        });
    
        const cdpTargets = await getCdpTargets(port, { timeoutMs: Math.min(timeout_ms, 2000) });
        const pageTargets = cdpTargets.filter((t) => t.type === "page");
        if (pageTargets.length === 0) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({ status: "error", error: `No page targets available on Chrome target '${target_id}'.` }),
            }],
          };
        }
    
        let selectedTarget: Record<string, unknown> | undefined;
        if (page_target_id) {
          selectedTarget = pageTargets.find((t) => t.id === page_target_id);
          if (!selectedTarget) {
            return {
              content: [{
                type: "text",
                text: JSON.stringify({
                  status: "error",
                  error: `Page target '${page_target_id}' not found on Chrome target '${target_id}'.`,
                }),
              }],
            };
          }
        } else {
          selectedTarget = pageTargets.find((t) => {
            const tUrl = typeof t.url === "string" ? t.url.toLowerCase() : "";
            return tUrl.length > 0 && !tUrl.startsWith("devtools://") && !tUrl.startsWith("chrome://");
          }) ?? pageTargets[0];
        }
    
        const pageTargetWs = selectedTarget.webSocketDebuggerUrl;
        if (typeof pageTargetWs !== "string" || pageTargetWs.length === 0) {
          return {
            content: [{
              type: "text",
              text: JSON.stringify({
                status: "error",
                error: `Selected page target has no webSocketDebuggerUrl on Chrome target '${target_id}'.`,
              }),
            }],
          };
        }
    
        const beforeCount = proxyManager.getTraffic().length;
        const cdpResult = await sendCdpCommand(
          pageTargetWs,
          "Page.navigate",
          { url },
          { timeoutMs: timeout_ms },
        );
    
        const destinationHost = normalizeHostname(url);
        let matchedExchangeIds: string[] = [];
        let sawAnyNewTraffic = false;
        let waitedMs = 0;
    
        if (wait_for_proxy_capture) {
          const startedAt = Date.now();
          while (Date.now() - startedAt <= timeout_ms) {
            const delta = proxyManager.getTraffic().slice(beforeCount);
            if (delta.length > 0) {
              sawAnyNewTraffic = true;
            }
            if (destinationHost) {
              const matches = delta
                .filter((x) => {
                  const host = x.request.hostname.toLowerCase();
                  return host === destinationHost || host.endsWith(`.${destinationHost}`);
                })
                .map((x) => x.id);
              if (matches.length > 0) {
                matchedExchangeIds = matches;
                break;
              }
            } else if (delta.length > 0) {
              matchedExchangeIds = delta.map((x) => x.id);
              break;
            }
            await sleep(Math.max(50, poll_interval_ms));
            waitedMs = Date.now() - startedAt;
          }
        }
    
        const delta = proxyManager.getTraffic().slice(beforeCount);
        const response: Record<string, unknown> = {
          status: "success",
          target_id,
          url,
          selected_page_target_id: selectedTarget.id ?? null,
          selected_page_url: selectedTarget.url ?? null,
          cdpResult,
          traffic: {
            beforeCount,
            afterCount: beforeCount + delta.length,
            deltaCount: delta.length,
            destinationHost,
            matchedHostExchangeCount: matchedExchangeIds.length,
            matchedHostExchangeIds: matchedExchangeIds,
            waitedMs,
          },
        };
    
        if (wait_for_proxy_capture && destinationHost && matchedExchangeIds.length === 0) {
          response.warning = sawAnyNewTraffic
            ? `Navigation succeeded but no '${destinationHost}' traffic was captured within ${timeout_ms}ms.`
            : `No new proxy traffic observed within ${timeout_ms}ms after navigation.`;
        }
    
        return {
          content: [{
            type: "text",
            text: truncateResult(response),
          }],
        };
      } catch (e) {
        return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: errorToString(e) }) }] };
      }
    },
  • The MCP tool registration for "interceptor_chrome_navigate".
    server.tool(
      "interceptor_chrome_navigate",
      "Navigate a tab in a specific Chrome instance launched by interceptor_chrome_launch using that instance's CDP target WebSocket. Prevents cross-instance mistakes when proxy capture is required.",
      {
        target_id: z.string().describe("Target ID from interceptor_chrome_launch"),
        url: z.string().describe("Destination URL"),
        page_target_id: z.string().optional().describe("Optional page target ID from interceptor_chrome_cdp_info targets"),
        wait_for_proxy_capture: z.boolean().optional().default(true)
          .describe("Wait for matching proxy traffic after navigate (default: true)"),
        timeout_ms: z.number().optional().default(5000).describe("Max wait for CDP response and proxy capture (default: 5000ms)"),
        poll_interval_ms: z.number().optional().default(200).describe("Polling interval while waiting for proxy capture (default: 200ms)"),
      },

Tool Definition Quality

Score is being calculated. Check back soon.

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/yfe404/proxy-mcp'

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