This release adds internal hostnames to the browser. Give a Browser Run browser hostnames such as preview.internal, and its requests to them go to your agent instead of the internet, so the model can open a dev server, a workspace folder or another Worker in the same browser it uses for the web.
Highlights
- Internal hostnames: pass up to 8 hostnames to
browserRun()asinternalHosts. Serve each one from afetchfunction on your agent or from another Worker. See Internal hostnames. - Hosts the model points: give a host a
targetschema, and the model chooses what it serves withbrowser.assignHost(), such as a container port or a folder in its workspace. Without a target, a host always serves the same thing. - Lighter installs without MCP servers:
@modelcontextprotocol/sdkand@modelcontextprotocol/serverare now optional peer dependencies, so apps that don't serve MCP no longer install them. - Stable models:
agents/models/ai-sdkandagents/models/pi-aiare no longer experimental. See Models. - Other changes:
createMcpHandlerpasses the verified token from@cloudflare/workers-oauth-provider1.x to tool callbacks ascontext.http.authInfo.createAIfromagents/models/pi-aisends pi-ai's Anthropic betas for catalog Claude models.PiWhenBusyaccepts"reject". browserToolimprovements: the model's code runs in its own Dynamic Worker instead of on codemode, and is stopped from outside that Worker if it overruns its timeout. It can no longer close the browser or create a Live View link.this.browser.session()lets your own code drive the same browser.createBrowserTools,createBrowserRuntime,BrowserConnectorand the Quick Action helpers are deprecated in favour ofbrowserTool.
Upgrading
You only need to make changes if you serve MCP or use browserTool.
If you serve MCP or use agents/x402 or agents/experimental/webmcp:
-
Add the MCP packages to your
package.jsonat the versions this release expects, since your package manager no longer installs them. Until you do, builds fail with an unresolved import.agents/mcp(McpAgent,WorkerTransport,createLegacyMcpHandler) andagents/x402:@modelcontextprotocol/sdk@1.32.1and@modelcontextprotocol/server@2.3.1agents/mcp/server(createMcpHandler):@modelcontextprotocol/server@2.3.1agents/experimental/webmcp:@modelcontextprotocol/sdk@1.32.1
-
Import client helpers such as
RPCClientTransportfromagents/mcp/clientinstead ofagents/mcp. MCP client code needs neither package.
If you use browserTool:
-
Remove the
CodemodeRuntimeexport from your Worker unlesscreateBrowserToolsstill uses it, and removectxfrombrowserTool's options. Keep theLOADERbinding and keep@cloudflare/codemodeinstalled for now. -
Update instructions of your own that mention
cdp.send, such as a system prompt. The tool's description already teaches the new call:- await cdp.send({ method: "Page.navigate", params: { url }, sessionId: "active" }); + await browser.cdp({ method: "Page.navigate", params: { url }, sessionId: "active" });
-
Read
noticeinstead ofrestarted,newTabsandcallsif your code inspects results.noticesays in sentences whether the browser restarted, the page opened tabs, or another chat closed or shares the tab.PiBrowserToolDetailsnow has onlyexecutionIdandstatus.
Minor Changes
-
#2673
865a57eThanks @ben-reitz! - AddinternalHoststobrowserRun()provider: set internal hostnames the browser can reach through your agent. Allow the model to point these hostnames at specific targets like container ports or workspace folders withbrowser.assignHost(). See Internal hostnames. -
#2667
03b4609Thanks @ben-reitz! -browserToolnow runs the model's code in its own Dynamic Worker instead of on codemode, so it needs noctxorCodemodeRuntimeexport (keep@cloudflare/codemodeinstalled for now) and its output has nocallslog;browser.session()gives your own code the same connection to the browser. See Persistent browser. -
#2634
565e37cThanks @mattzcarey! -@modelcontextprotocol/sdkand@modelcontextprotocol/serverare now optional peer dependencies, so add them to yourpackage.jsonif you useagents/mcp,agents/mcp/server,agents/x402oragents/experimental/webmcp. See Upgrading an existingMcpAgentserver.
Patch Changes
-
#2668
183c141Thanks @ben-reitz! -browserTool's model code now calls abrowserglobal (browser.cdp(...),browser.spec({ domain })) instead ofcdp.send(...), and the result'snoticereplaces therestartedandnewTabsfields. See Persistent browser. -
#2666
57c7813Thanks @ben-reitz! -createBrowserTools,createBrowserRuntimeandBrowserConnectorare deprecated; usebrowserTool. See Persistent browser. The Quick Action helpers (createQuickActionTools,runQuickAction,browserMarkdownand the rest) are deprecated too and will not change. -
#2743
f049ee1Thanks @mattzcarey! -agents/models/ai-sdkandagents/models/pi-aiare no longer experimental. See Models. -
#2718
916c0e3Thanks @ben-reitz! -createAIfromagents/models/pi-ainow sends pi-ai'sbetasas theanthropic-betaheader for catalog Claude models on/run, as it already did on the provider-native path. See #2714. -
#2717
4d7734aThanks @ben-reitz! -PiWhenBusyaccepts"reject", whichPiHarness.submit()already passed through to pi-durable. See Pi harness. -
#2680
2a25d88Thanks @mattzcarey! -createMcpHandlernow reads the verified token that@cloudflare/workers-oauth-provider1.x sets asctx.auth, so tool callbacks receivecontext.http.authInfo(token, client ID, scopes, expiry and resource) behindOAuthProviderandOAuthResourceServer.getMcpAuthContext().propsis unchanged.