browser.navigate
Navigate the active browser tab to a specified URL for automated testing, navigation workflows, or page redirection. Requires a connected Chrome extension.
Instructions
Navigates the current active browser tab to a new URL. Use for automated testing, navigation flows, or redirecting to specific pages. Requires Chrome extension to be connected.
Route Reference: ROUTES_FILE_PATH variable is not set so make sure you know the routes to use
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL to navigate to (must be a valid URL including protocol, e.g., 'https://example.com') |
Implementation Reference
- browser-tools-mcp/mcp-server.ts:1622-1706 (registration)MCP tool registration for 'browser.navigate'. Includes schema validation (url: string), dynamic description, and handler that discovers browser-connector server and POSTs {url} to /navigate-tab endpoint.server.tool( "browser.navigate", generateNavigateToolDescription(), { url: z .string() .describe( `The URL to navigate to (must be a valid URL including protocol, e.g., 'https://example.com')` ), }, async (params) => { return await withServerConnection(async () => { try { const { url } = params; // Validate URL format try { new URL(url); } catch (e) { return { content: [ { type: "text", text: `Invalid URL format: ${url}. Please provide a complete URL including protocol (e.g., 'https://example.com')`, }, ], isError: true, }; } const targetUrl = `http://${discoveredHost}:${discoveredPort}/navigate-tab`; const requestPayload = { url: url, }; console.log(`MCP Tool: Navigating browser tab to ${url}`); const response = await fetch(targetUrl, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(requestPayload), }); const result = await response.json(); if (response.ok && result.success) { return { content: [ { type: "text", text: `✅ Successfully navigated browser tab to: ${url}`, }, ], }; } else { return { content: [ { type: "text", text: `Failed to navigate browser tab: ${ result.error || "Unknown error" }`, }, ], isError: true, }; } } catch (error: any) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Failed to navigate browser tab: ${errorMessage}`, }, ], isError: true, }; } }); } );
- Primary handler for /navigate-tab HTTP POST endpoint. Validates connection, sends 'navigate-tab' WebSocket message to Chrome extension via buildNavigationMessage/parseNavigationResponse helpers, awaits response.async navigateTab( req: express.Request, res: express.Response ): Promise<void> { if ((process.env.LOG_LEVEL || "info").toLowerCase() === "debug") { console.log("[debug] navigateTab handler", req.body); } logInfo("Browser Connector: Received navigateTab request"); logDebug("Browser Connector: Request body:", req.body); const { url } = req.body; if (!url) { res.status(400).json({ error: "Missing URL parameter" }); return; } if (!this.activeConnection) { res.status(503).json({ error: "Chrome extension not connected" }); return; } try { logDebug("Browser Connector: Sending navigation request to extension"); // Create a promise that will resolve when we get the navigation response const navigationPromise = new Promise<{ success: boolean; error?: string; }>((resolve, reject) => { const requestId = Date.now().toString(); // Set up a one-time message handler for this navigation request const messageHandler = ( message: string | Buffer | ArrayBuffer | Buffer[] ) => { try { const data = JSON.parse(message.toString()); // Parse navigation response using tool helper (statically imported) const parsed = parseNavigationResponse(data, requestId); if (parsed) { // Remove this listener once we get a response this.activeConnection?.removeListener("message", messageHandler); if (parsed.success) { resolve({ success: true }); } else { resolve({ success: false, error: parsed.error }); } } } catch (error) { // Ignore parsing errors for other messages } }; // Add temporary message handler this.activeConnection?.on("message", messageHandler); // Send navigation request to extension (using tool builder - statically imported) this.activeConnection?.send(buildNavigationMessage({ url }, requestId)); // Set timeout setTimeout(() => { this.activeConnection?.removeListener("message", messageHandler); reject(new Error("Navigation timeout")); }, 10000); // 10 second timeout }); const result = await navigationPromise; if (result.success) { logInfo("Browser Connector: Navigation completed successfully"); res.json({ success: true, url: url }); } else { console.error( "[error] Browser Connector: Navigation failed:", result.error ); res.status(500).json({ error: result.error || "Navigation failed" }); } } catch (error) { console.error( "[error] Browser Connector: Error during navigation:", error ); res.status(500).json({ error: error instanceof Error ? error.message : "An unknown error occurred during navigation", }); } }
- Helper to build JSON WebSocket payload {type: 'navigate-tab', url, requestId} sent to Chrome extension.export function buildNavigationMessage( req: { url: string }, requestId: string ) { return JSON.stringify({ type: "navigate-tab", url: req.url, requestId, }); }
- Helper to parse 'navigation-response' WebSocket message from extension, matching requestId.export function parseNavigationResponse( data: any, expectedRequestId: string ): NavigationResult | undefined { if ( data && data.type === "navigation-response" && data.requestId === expectedRequestId ) { if (data.success) { return { success: true }; } return { success: false, error: data.error }; } return undefined; }
- chrome-extension/background.js:74-105 (handler)Chrome extension background script handler for NAVIGATE_TAB message: executes chrome.tabs.update to navigate the tab.if (message.type === "NAVIGATE_TAB" && message.url) { console.log("Background: Received navigation request:", message); const targetTabId = message.tabId || chrome.devtools?.inspectedWindow?.tabId; if (!targetTabId) { console.error("Background: No target tab ID available for navigation"); sendResponse({ success: false, error: "No target tab ID available" }); return true; } // Navigate the tab to the specified URL chrome.tabs.update(targetTabId, { url: message.url }, (tab) => { if (chrome.runtime.lastError) { console.error( "Background: Navigation failed:", chrome.runtime.lastError ); sendResponse({ success: false, error: chrome.runtime.lastError.message, }); } else { console.log("Background: Navigation successful to:", message.url); // Update our cache with the new URL tabUrls.set(targetTabId, message.url); sendResponse({ success: true, url: message.url }); } }); return true; // Required to use sendResponse asynchronously }