The MCP (Model Context Protocol) client allows browser-use agents to connect to external MCP servers, automatically exposing their tools as actions.

MCP is an open protocol for integrating LLMs with external data sources and tools. Learn more at modelcontextprotocol.io.

Looking to expose browser-use as an MCP server instead? See MCP Server.

Installation

uv pip install "browser-use[cli]"

Quick Start

import os
from browser_use import Agent, Controller
from browser_use.mcp.client import MCPClient

# Create controller
controller = Controller()

# Connect to MCP server
mcp_client = MCPClient(
    server_name="filesystem",
    command="npx",
    args=["@modelcontextprotocol/server-filesystem", "/path/to/files"]
)

# Connect and register
await mcp_client.connect()
await mcp_client.register_to_controller(controller)

# Agent can now use filesystem tools
agent = Agent(
    task="Read the README.md file",
    controller=controller
)
await agent.run()

# Clean up
await mcp_client.disconnect()

API Reference

MCPClient

class MCPClient:
    def __init__(
        self,
        server_name: str,
        command: str,
        args: list[str] | None = None,
        env: dict[str, str] | None = None,
    ) -> None

Parameters:

  • server_name: Name of the MCP server (for logging)
  • command: Command to start the server (e.g., "npx")
  • args: Arguments for the command
  • env: Environment variables for the server

Key Methods:

# Connect to server
await mcp_client.connect()

# Register tools to controller
await mcp_client.register_to_controller(
    controller,
    tool_filter=['read_file', 'write_file'],  # Optional
    prefix='fs_'  # Optional prefix
)

# Disconnect
await mcp_client.disconnect()

Context Manager Usage

async with MCPClient(
    server_name="github",
    command="npx",
    args=["@modelcontextprotocol/server-github"],
    env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
) as client:
    await client.register_to_controller(controller)
    await agent.run()
# Automatically disconnected

Common MCP Servers

Filesystem

MCPClient(
    server_name="filesystem",
    command="npx",
    args=["@modelcontextprotocol/server-filesystem", "/path"]
)

PostgreSQL

MCPClient(
    server_name="postgres",
    command="npx",
    args=["@modelcontextprotocol/server-postgres", "postgresql://localhost/db"]
)

GitHub

MCPClient(
    server_name="github",
    command="npx",
    args=["@modelcontextprotocol/server-github"],
    env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
)

Multiple Servers

Connect multiple servers with prefixes to avoid conflicts:

# Filesystem server
fs_client = MCPClient(
    server_name="filesystem",
    command="npx",
    args=["@modelcontextprotocol/server-filesystem", "."]
)
await fs_client.connect()
await fs_client.register_to_controller(controller, prefix="fs_")

# GitHub server
gh_client = MCPClient(
    server_name="github",
    command="npx",
    args=["@modelcontextprotocol/server-github"],
    env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
)
await gh_client.connect()
await gh_client.register_to_controller(controller, prefix="gh_")

# Agent can use both
agent = Agent(
    task="Read README.md and create a GitHub issue",
    controller=controller
)
await agent.run()

# Clean up
await fs_client.disconnect()
await gh_client.disconnect()

Tool Filtering

Register only specific tools:

await mcp_client.register_to_controller(
    controller,
    tool_filter=['read_file', 'list_directory']
)

Custom MCP Server

Create your own MCP server:

# my_server.py
import mcp.server.stdio
import mcp.types as types
from mcp.server import Server

server = Server("custom-tools")

@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="calculate",
            description="Perform calculation",
            inputSchema={
                "type": "object",
                "properties": {
                    "expression": {"type": "string"}
                },
                "required": ["expression"]
            }
        )
    ]

@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
    if name == "calculate":
        result = eval(arguments["expression"])
        return [types.TextContent(type="text", text=str(result))]
    return []

# Run server
async def main():
    async with mcp.server.stdio.stdio_server() as (read, write):
        await server.run(read, write, ...)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Connect custom server:

custom_client = MCPClient(
    server_name="custom",
    command="python",
    args=["my_server.py"]
)

Best Practices

  1. Always disconnect when done
  2. Use prefixes when connecting multiple servers
  3. Filter tools to limit capabilities
  4. Use context managers for automatic cleanup

See Also