Skip to content

browserless/browserless-agno

Repository files navigation

Browserless × Agno

Runnable Python examples for the Browserless MCP server, using Agno's first-party MCPTools.

The hosted endpoint at https://mcp.browserless.io/mcp exposes 10 tools. Browser sessions are pinned by Mcp-Session-Id, so multi-turn browserless_agent flows preserve browser state across calls without any extra configuration on the Agno side — Agno's MCPTools is an async context manager that owns one MCP ClientSession for the lifetime of the async with block.

Stateless tools (8) Stateful tools (2)
smartscraper, search, map, crawl, export, performance, function, download agent, skill
Use case Single-shot scraping, research, data extraction Multi-turn browser automation, multi-step browser flows with persistent browser state

Setup

uv pip install -r requirements.txt
export BROWSERLESS_TOKEN=<your-token>
export ANTHROPIC_API_KEY=<your-key>

Get a Browserless token at account.browserless.io.

Scripts

Script What it shows Tier
quickstart.py Connect, list tools, call browserless_smartscraper directly, run an Agno Agent with stateless tools 1 (stateless)
research_agent.py Multi-step search → scrape → summarize using stateless tools 1 (stateless)
browser_agent.py Multi-turn browserless_agent: navigate → snapshot → click → re-snapshot → extract 2 (stateful)

Run

uv run --with-requirements requirements.txt python quickstart.py
uv run --with-requirements requirements.txt python research_agent.py
uv run --with-requirements requirements.txt python browser_agent.py

Quick connect

import asyncio
import os

from agno.tools.mcp import MCPTools, StreamableHTTPClientParams

async def main():
    async with MCPTools(
        url="https://mcp.browserless.io/mcp",
        transport="streamable-http",
        timeout_seconds=120,
        server_params=StreamableHTTPClientParams(
            url="https://mcp.browserless.io/mcp",
            headers={
                "Authorization": f"Bearer {os.environ['BROWSERLESS_TOKEN']}",
            },
        ),
    ) as mcp_tools:
        listed = await mcp_tools.session.list_tools()
        print([t.name for t in listed.tools])  # 10 tools

asyncio.run(main())

Why no _run_session() workaround?

Unlike Python's langchain-mcp-adapters and llama-index-tools-mcp (both of which open a fresh MCP ClientSession per tool.invoke() call by default), Agno's MCPTools keeps one session alive for the whole async with block. State is preserved automatically as long as the agent loop runs inside that block. See sister cookbooks for the Python frameworks that need workarounds: browserless/browserless-langchain, browserless/browserless-llamaindex. Mastra (browserless/mastra-cookbook) is the TypeScript equivalent of this convenience.

Links

About

Agno (Python) examples for the Browserless MCP server

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages