ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
Advanced example: Using multiple MCP servers together.
|
||||
|
||||
This example demonstrates how to:
|
||||
1. Connect multiple MCP servers (Gmail + Filesystem) to browser-use
|
||||
2. Sign up for a new account on a website
|
||||
3. Save registration details to a file
|
||||
4. Retrieve the verification link from Gmail
|
||||
5. Complete the verification process
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from browser_use import Agent, Tools
|
||||
from browser_use.llm.openai.chat import ChatOpenAI
|
||||
from browser_use.mcp.client import MCPClient
|
||||
|
||||
|
||||
async def main():
|
||||
"""Sign up for account, save details, and verify via Gmail."""
|
||||
|
||||
# Initialize tools
|
||||
tools = Tools()
|
||||
|
||||
# Connect to Gmail MCP Server
|
||||
# Requires Gmail API credentials - see: https://github.com/GongRzhe/Gmail-MCP-Server#setup
|
||||
gmail_env = {}
|
||||
if client_id := os.getenv('GMAIL_CLIENT_ID'):
|
||||
gmail_env['GMAIL_CLIENT_ID'] = client_id
|
||||
if client_secret := os.getenv('GMAIL_CLIENT_SECRET'):
|
||||
gmail_env['GMAIL_CLIENT_SECRET'] = client_secret
|
||||
if refresh_token := os.getenv('GMAIL_REFRESH_TOKEN'):
|
||||
gmail_env['GMAIL_REFRESH_TOKEN'] = refresh_token
|
||||
|
||||
gmail_client = MCPClient(server_name='gmail', command='npx', args=['gmail-mcp-server'], env=gmail_env)
|
||||
|
||||
# Connect to Filesystem MCP Server for saving registration details
|
||||
filesystem_client = MCPClient(
|
||||
server_name='filesystem',
|
||||
command='npx',
|
||||
args=['-y', '@modelcontextprotocol/server-filesystem', os.path.expanduser('~/Desktop')],
|
||||
)
|
||||
|
||||
# Connect and register tools from both servers
|
||||
print('Connecting to Gmail MCP server...')
|
||||
await gmail_client.connect()
|
||||
await gmail_client.register_to_tools(tools)
|
||||
|
||||
print('Connecting to Filesystem MCP server...')
|
||||
await filesystem_client.connect()
|
||||
await filesystem_client.register_to_tools(tools)
|
||||
|
||||
# Create agent with extended system prompt for using multiple MCP servers
|
||||
agent = Agent(
|
||||
task='Sign up for a new Anthropic account using the email example@gmail.com, save the registration details to a file',
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
tools=tools,
|
||||
extend_system_message="""
|
||||
You have access to both Gmail and Filesystem tools through MCP servers. When signing up for accounts:
|
||||
|
||||
1. Fill out registration forms with the provided email address
|
||||
2. Use the filesystem tools to create a file called 'anthropic_registration.txt' on the Desktop containing:
|
||||
- Email used for registration
|
||||
- Timestamp of registration
|
||||
- Any username or account details
|
||||
3. After submitting the registration, use the Gmail MCP tools to check for verification emails
|
||||
4. Search for recent emails (within the last 5 minutes) from the service you're signing up for
|
||||
5. Look for verification links or codes in those emails
|
||||
6. Append the verification details to the registration file
|
||||
7. Use any verification links or codes found to complete the account setup
|
||||
8. Update the file with the final account status
|
||||
|
||||
Available tools include:
|
||||
Gmail tools:
|
||||
- search_emails: Search for emails by query (e.g., "from:noreply@anthropic.com")
|
||||
- get_email: Get full email content by ID
|
||||
- list_emails: List recent emails
|
||||
|
||||
Filesystem tools:
|
||||
- read_file: Read content from a file
|
||||
- write_file: Write content to a file
|
||||
- list_directory: List files in a directory
|
||||
|
||||
Always wait a few seconds after submitting a form before checking Gmail to allow the email to arrive.
|
||||
""",
|
||||
)
|
||||
|
||||
# Run the agent
|
||||
result = await agent.run()
|
||||
|
||||
print('\nTask completed!')
|
||||
print(f'Result: {result}')
|
||||
|
||||
# Disconnect both MCP clients
|
||||
await gmail_client.disconnect()
|
||||
await filesystem_client.disconnect()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Prerequisites:
|
||||
# 1. Install both MCP servers:
|
||||
# npm install -g gmail-mcp-server
|
||||
# npm install -g @modelcontextprotocol/server-filesystem
|
||||
# 2. Set up Gmail API credentials following: https://github.com/GongRzhe/Gmail-MCP-Server#setup
|
||||
# 3. Set these environment variables:
|
||||
# export GMAIL_CLIENT_ID="your-client-id"
|
||||
# export GMAIL_CLIENT_SECRET="your-client-secret"
|
||||
# export GMAIL_REFRESH_TOKEN="your-refresh-token"
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,324 @@
|
||||
"""
|
||||
Advanced example of building an AI assistant that uses browser-use MCP server.
|
||||
|
||||
This example shows how to build a more sophisticated MCP client that:
|
||||
- Connects to multiple MCP servers (browser-use + filesystem)
|
||||
- Orchestrates complex multi-step workflows
|
||||
- Handles errors and retries
|
||||
- Provides a conversational interface
|
||||
|
||||
Prerequisites:
|
||||
1. Install required packages:
|
||||
pip install 'browser-use[cli]'
|
||||
|
||||
2. Start the browser-use MCP server:
|
||||
uvx 'browser-use[cli]' --mcp
|
||||
|
||||
3. Run this example:
|
||||
python advanced_server.py
|
||||
|
||||
This demonstrates real-world usage patterns for the MCP protocol.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from mcp import ClientSession, StdioServerParameters
|
||||
from mcp.client.stdio import stdio_client
|
||||
from mcp.types import TextContent, Tool
|
||||
|
||||
|
||||
@dataclass
|
||||
class TaskResult:
|
||||
"""Result of executing a task."""
|
||||
|
||||
success: bool
|
||||
data: Any
|
||||
error: str | None = None
|
||||
timestamp: datetime | None = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.timestamp is None:
|
||||
self.timestamp = datetime.now()
|
||||
|
||||
|
||||
class AIAssistant:
|
||||
"""An AI assistant that uses MCP servers to perform complex tasks."""
|
||||
|
||||
def __init__(self):
|
||||
self.servers: dict[str, ClientSession] = {}
|
||||
self.tools: dict[str, Tool] = {}
|
||||
self.history: list[TaskResult] = []
|
||||
|
||||
async def connect_server(self, name: str, command: str, args: list[str], env: dict[str, str] | None = None):
|
||||
"""Connect to an MCP server and discover its tools."""
|
||||
print(f'\n🔌 Connecting to {name} server...')
|
||||
|
||||
server_params = StdioServerParameters(command=command, args=args, env=env or {})
|
||||
|
||||
try:
|
||||
# Create connection
|
||||
read, write = await stdio_client(server_params).__aenter__()
|
||||
session = ClientSession(read, write)
|
||||
await session.__aenter__()
|
||||
await session.initialize()
|
||||
|
||||
# Store session
|
||||
self.servers[name] = session
|
||||
|
||||
# Discover tools
|
||||
tools_result = await session.list_tools()
|
||||
tools = tools_result.tools
|
||||
for tool in tools:
|
||||
# Prefix tool names with server name to avoid conflicts
|
||||
prefixed_name = f'{name}.{tool.name}'
|
||||
self.tools[prefixed_name] = tool
|
||||
print(f' ✓ Discovered: {prefixed_name}')
|
||||
|
||||
print(f'✅ Connected to {name} with {len(tools)} tools')
|
||||
|
||||
except Exception as e:
|
||||
print(f'❌ Failed to connect to {name}: {e}')
|
||||
raise
|
||||
|
||||
async def disconnect_all(self):
|
||||
"""Disconnect from all MCP servers."""
|
||||
for name, session in self.servers.items():
|
||||
try:
|
||||
await session.__aexit__(None, None, None)
|
||||
print(f'📴 Disconnected from {name}')
|
||||
except Exception as e:
|
||||
print(f'⚠️ Error disconnecting from {name}: {e}')
|
||||
|
||||
async def call_tool(self, tool_name: str, arguments: dict[str, Any]) -> TaskResult:
|
||||
"""Call a tool on the appropriate MCP server."""
|
||||
# Parse server and tool name
|
||||
if '.' not in tool_name:
|
||||
return TaskResult(False, None, "Invalid tool name format. Use 'server.tool'")
|
||||
|
||||
server_name, actual_tool_name = tool_name.split('.', 1)
|
||||
|
||||
# Check if server is connected
|
||||
if server_name not in self.servers:
|
||||
return TaskResult(False, None, f"Server '{server_name}' not connected")
|
||||
|
||||
# Call the tool
|
||||
try:
|
||||
session = self.servers[server_name]
|
||||
result = await session.call_tool(actual_tool_name, arguments)
|
||||
|
||||
# Extract text content
|
||||
text_content = [c.text for c in result.content if isinstance(c, TextContent)]
|
||||
data = text_content[0] if text_content else str(result.content)
|
||||
|
||||
task_result = TaskResult(True, data)
|
||||
self.history.append(task_result)
|
||||
return task_result
|
||||
|
||||
except Exception as e:
|
||||
error_result = TaskResult(False, None, str(e))
|
||||
self.history.append(error_result)
|
||||
return error_result
|
||||
|
||||
async def search_and_save(self, query: str, output_file: str) -> TaskResult:
|
||||
"""Search for information and save results to a file."""
|
||||
print(f'\n🔍 Searching for: {query}')
|
||||
|
||||
# Step 1: Navigate to search engine
|
||||
print(' 1️⃣ Opening DuckDuckGo...')
|
||||
nav_result = await self.call_tool('browser.browser_navigate', {'url': f'https://duckduckgo.com/?q={query}'})
|
||||
if not nav_result.success:
|
||||
return nav_result
|
||||
|
||||
await asyncio.sleep(2) # Wait for page load
|
||||
|
||||
# Step 2: Get search results
|
||||
print(' 2️⃣ Extracting search results...')
|
||||
extract_result = await self.call_tool(
|
||||
'browser.browser_extract_content',
|
||||
{'query': 'Extract the top 5 search results with titles and descriptions', 'extract_links': True},
|
||||
)
|
||||
if not extract_result.success:
|
||||
return extract_result
|
||||
|
||||
# Step 3: Save to file (if filesystem server is connected)
|
||||
if 'filesystem' in self.servers:
|
||||
print(f' 3️⃣ Saving results to {output_file}...')
|
||||
save_result = await self.call_tool(
|
||||
'filesystem.write_file',
|
||||
{'path': output_file, 'content': f'Search Query: {query}\n\nResults:\n{extract_result.data}'},
|
||||
)
|
||||
if save_result.success:
|
||||
print(f' ✅ Results saved to {output_file}')
|
||||
else:
|
||||
print(' ⚠️ Filesystem server not connected, skipping save')
|
||||
|
||||
return extract_result
|
||||
|
||||
async def monitor_page_changes(self, url: str, duration: int = 10, interval: int = 2):
|
||||
"""Monitor a webpage for changes over time."""
|
||||
print(f'\n📊 Monitoring {url} for {duration} seconds...')
|
||||
|
||||
# Navigate to page
|
||||
await self.call_tool('browser.browser_navigate', {'url': url})
|
||||
await asyncio.sleep(2)
|
||||
|
||||
changes = []
|
||||
start_time = datetime.now()
|
||||
|
||||
while (datetime.now() - start_time).seconds < duration:
|
||||
# Get current state
|
||||
state_result = await self.call_tool('browser.browser_get_state', {'include_screenshot': False})
|
||||
|
||||
if state_result.success:
|
||||
state = json.loads(state_result.data)
|
||||
changes.append(
|
||||
{
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'title': state.get('title', ''),
|
||||
'element_count': len(state.get('interactive_elements', [])),
|
||||
}
|
||||
)
|
||||
print(f' 📸 Captured state at {changes[-1]["timestamp"]}')
|
||||
|
||||
await asyncio.sleep(interval)
|
||||
|
||||
return TaskResult(True, changes)
|
||||
|
||||
async def fill_form_workflow(self, form_url: str, form_data: dict[str, str]):
|
||||
"""Navigate to a form and fill it out."""
|
||||
print(f'\n📝 Form filling workflow for {form_url}')
|
||||
|
||||
# Step 1: Navigate to form
|
||||
print(' 1️⃣ Navigating to form...')
|
||||
nav_result = await self.call_tool('browser.browser_navigate', {'url': form_url})
|
||||
if not nav_result.success:
|
||||
return nav_result
|
||||
|
||||
await asyncio.sleep(2)
|
||||
|
||||
# Step 2: Get form elements
|
||||
print(' 2️⃣ Analyzing form elements...')
|
||||
state_result = await self.call_tool('browser.browser_get_state', {'include_screenshot': False})
|
||||
|
||||
if not state_result.success:
|
||||
return state_result
|
||||
|
||||
state = json.loads(state_result.data)
|
||||
|
||||
# Step 3: Fill form fields
|
||||
print(' 3️⃣ Filling form fields...')
|
||||
filled_fields = []
|
||||
|
||||
for element in state.get('interactive_elements', []):
|
||||
# Look for input fields
|
||||
if element.get('tag') in ['input', 'textarea']:
|
||||
# Try to match field by placeholder or nearby text
|
||||
for field_name, field_value in form_data.items():
|
||||
element_text = str(element).lower()
|
||||
if field_name.lower() in element_text:
|
||||
print(f' ✏️ Filling {field_name}...')
|
||||
type_result = await self.call_tool(
|
||||
'browser.browser_type', {'index': element['index'], 'text': field_value}
|
||||
)
|
||||
if type_result.success:
|
||||
filled_fields.append(field_name)
|
||||
await asyncio.sleep(0.5)
|
||||
break
|
||||
|
||||
return TaskResult(True, {'filled_fields': filled_fields, 'form_data': form_data, 'url': form_url})
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main demonstration of advanced MCP client usage."""
|
||||
print('Browser-Use MCP Client - Advanced Example')
|
||||
print('=' * 50)
|
||||
|
||||
assistant = AIAssistant()
|
||||
|
||||
try:
|
||||
# Connect to browser-use MCP server
|
||||
await assistant.connect_server(name='browser', command='uvx', args=['browser-use[cli]', '--mcp'])
|
||||
|
||||
# Optionally connect to filesystem server
|
||||
# Note: Uncomment to enable file operations
|
||||
# await assistant.connect_server(
|
||||
# name="filesystem",
|
||||
# command="npx",
|
||||
# args=["@modelcontextprotocol/server-filesystem", "."]
|
||||
# )
|
||||
|
||||
print('\n' + '=' * 50)
|
||||
print('Starting demonstration workflows...')
|
||||
print('=' * 50)
|
||||
|
||||
# Demo 1: Search and extract
|
||||
print('\n📌 Demo 1: Web Search and Extraction')
|
||||
search_result = await assistant.search_and_save(query='MCP protocol browser automation', output_file='search_results.txt')
|
||||
print(f'Search completed: {"✅" if search_result.success else "❌"}')
|
||||
|
||||
# Demo 2: Multi-tab comparison
|
||||
print('\n📌 Demo 2: Multi-tab News Comparison')
|
||||
news_sites = [('BBC News', 'https://bbc.com/news'), ('CNN', 'https://cnn.com'), ('Reuters', 'https://reuters.com')]
|
||||
|
||||
for i, (name, url) in enumerate(news_sites):
|
||||
print(f'\n 📰 Opening {name}...')
|
||||
await assistant.call_tool('browser.browser_navigate', {'url': url, 'new_tab': i > 0})
|
||||
await asyncio.sleep(2)
|
||||
|
||||
# List all tabs
|
||||
tabs_result = await assistant.call_tool('browser.browser_list_tabs', {})
|
||||
if tabs_result.success:
|
||||
tabs = json.loads(tabs_result.data)
|
||||
print(f'\n 📑 Opened {len(tabs)} news sites:')
|
||||
for tab in tabs:
|
||||
print(f' - Tab {tab["index"]}: {tab["title"]}')
|
||||
|
||||
# Demo 3: Form filling
|
||||
print('\n📌 Demo 3: Automated Form Filling')
|
||||
form_result = await assistant.fill_form_workflow(
|
||||
form_url='https://httpbin.org/forms/post',
|
||||
form_data={
|
||||
'custname': 'AI Assistant',
|
||||
'custtel': '555-0123',
|
||||
'custemail': 'ai@example.com',
|
||||
'comments': 'Testing MCP browser automation',
|
||||
},
|
||||
)
|
||||
if form_result.success:
|
||||
print(f' ✅ Filled {len(form_result.data["filled_fields"])} fields')
|
||||
|
||||
# Demo 4: Page monitoring
|
||||
print('\n📌 Demo 4: Dynamic Page Monitoring')
|
||||
monitor_result = await assistant.monitor_page_changes(url='https://time.is/', duration=10, interval=3)
|
||||
if monitor_result.success:
|
||||
print(f' 📊 Collected {len(monitor_result.data)} snapshots')
|
||||
|
||||
# Summary
|
||||
print('\n' + '=' * 50)
|
||||
print('📊 Session Summary')
|
||||
print('=' * 50)
|
||||
|
||||
success_count = sum(1 for r in assistant.history if r.success)
|
||||
total_count = len(assistant.history)
|
||||
|
||||
print(f'Total operations: {total_count}')
|
||||
print(f'Successful: {success_count}')
|
||||
print(f'Failed: {total_count - success_count}')
|
||||
print(f'Success rate: {success_count / total_count * 100:.1f}%')
|
||||
|
||||
except Exception as e:
|
||||
print(f'\n❌ Fatal error: {e}')
|
||||
|
||||
finally:
|
||||
# Always disconnect
|
||||
print('\n🧹 Cleaning up...')
|
||||
await assistant.disconnect_all()
|
||||
print('✨ Demo complete!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
Simple example of using MCP client with browser-use.
|
||||
|
||||
This example shows how to connect to an MCP server and use its tools with an agent.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from browser_use import Agent, Tools
|
||||
from browser_use.llm.openai.chat import ChatOpenAI
|
||||
from browser_use.mcp.client import MCPClient
|
||||
|
||||
|
||||
async def main():
|
||||
# Initialize tools
|
||||
tools = Tools()
|
||||
|
||||
# Connect to a filesystem MCP server
|
||||
# This server provides tools to read/write files in a directory
|
||||
mcp_client = MCPClient(
|
||||
server_name='filesystem', command='npx', args=['@modelcontextprotocol/server-filesystem', os.path.expanduser('~/Desktop')]
|
||||
)
|
||||
|
||||
# Connect and register MCP tools
|
||||
await mcp_client.connect()
|
||||
await mcp_client.register_to_tools(tools)
|
||||
|
||||
# Create agent with MCP-enabled tools
|
||||
agent = Agent(
|
||||
task='List all files on the Desktop and read the content of any .txt files you find',
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
tools=tools,
|
||||
)
|
||||
|
||||
# Run the agent - it now has access to filesystem tools
|
||||
await agent.run()
|
||||
|
||||
# Disconnect when done
|
||||
await mcp_client.disconnect()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,138 @@
|
||||
"""
|
||||
Simple example of connecting to browser-use MCP server as a client.
|
||||
|
||||
This example demonstrates how to use the MCP client library to connect to
|
||||
a running browser-use MCP server and call its browser automation tools.
|
||||
|
||||
Prerequisites:
|
||||
1. Install required packages:
|
||||
pip install 'browser-use[cli]'
|
||||
|
||||
2. Start the browser-use MCP server in a separate terminal:
|
||||
uvx browser-use --mcp
|
||||
|
||||
3. Run this client example:
|
||||
python simple_server.py
|
||||
|
||||
This shows the actual MCP protocol flow between a client and the browser-use server.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from mcp import ClientSession, StdioServerParameters
|
||||
from mcp.client.stdio import stdio_client
|
||||
from mcp.types import TextContent
|
||||
|
||||
|
||||
async def run_simple_browser_automation():
|
||||
"""Connect to browser-use MCP server and perform basic browser automation."""
|
||||
|
||||
# Create connection parameters for the browser-use MCP server
|
||||
server_params = StdioServerParameters(command='uvx', args=['browser-use', '--mcp'], env={})
|
||||
|
||||
async with stdio_client(server_params) as (read, write):
|
||||
async with ClientSession(read, write) as session:
|
||||
# Initialize the connection
|
||||
await session.initialize()
|
||||
|
||||
print('✅ Connected to browser-use MCP server')
|
||||
|
||||
# List available tools
|
||||
tools_result = await session.list_tools()
|
||||
tools = tools_result.tools
|
||||
print(f'\n📋 Available tools: {len(tools)}')
|
||||
for tool in tools:
|
||||
print(f' - {tool.name}: {tool.description}')
|
||||
|
||||
# Example 1: Navigate to a website
|
||||
print('\n🌐 Navigating to example.com...')
|
||||
result = await session.call_tool('browser_navigate', arguments={'url': 'https://example.com'})
|
||||
# Handle different content types
|
||||
content = result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
print(f'Result: {content.text}')
|
||||
else:
|
||||
print(f'Result: {content}')
|
||||
|
||||
# Example 2: Get the current browser state
|
||||
print('\n🔍 Getting browser state...')
|
||||
result = await session.call_tool('browser_get_state', arguments={'include_screenshot': False})
|
||||
# Handle different content types
|
||||
content = result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
state = json.loads(content.text)
|
||||
else:
|
||||
state = json.loads(str(content))
|
||||
print(f'Page title: {state["title"]}')
|
||||
print(f'URL: {state["url"]}')
|
||||
print(f'Interactive elements found: {len(state["interactive_elements"])}')
|
||||
|
||||
# Example 3: Open a new tab
|
||||
print('\n📑 Opening Python.org in a new tab...')
|
||||
result = await session.call_tool('browser_navigate', arguments={'url': 'https://python.org', 'new_tab': True})
|
||||
# Handle different content types
|
||||
content = result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
print(f'Result: {content.text}')
|
||||
else:
|
||||
print(f'Result: {content}')
|
||||
|
||||
# Example 4: List all open tabs
|
||||
print('\n📋 Listing all tabs...')
|
||||
result = await session.call_tool('browser_list_tabs', arguments={})
|
||||
# Handle different content types
|
||||
content = result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
tabs = json.loads(content.text)
|
||||
else:
|
||||
tabs = json.loads(str(content))
|
||||
for tab in tabs:
|
||||
print(f' Tab {tab["index"]}: {tab["title"]} - {tab["url"]}')
|
||||
|
||||
# Example 5: Click on an element
|
||||
print('\n👆 Looking for clickable elements...')
|
||||
state_result = await session.call_tool('browser_get_state', arguments={'include_screenshot': False})
|
||||
# Handle different content types
|
||||
content = state_result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
state = json.loads(content.text)
|
||||
else:
|
||||
state = json.loads(str(content))
|
||||
|
||||
# Find a link to click
|
||||
link_element = None
|
||||
for elem in state['interactive_elements']:
|
||||
if elem['tag'] == 'a' and elem.get('href'):
|
||||
link_element = elem
|
||||
break
|
||||
|
||||
if link_element:
|
||||
print(f'Clicking on link: {link_element.get("text", "unnamed")[:50]}...')
|
||||
result = await session.call_tool('browser_click', arguments={'index': link_element['index']})
|
||||
# Handle different content types
|
||||
content = result.content[0]
|
||||
if isinstance(content, TextContent):
|
||||
print(f'Result: {content.text}')
|
||||
else:
|
||||
print(f'Result: {content}')
|
||||
|
||||
print('\n✨ Simple browser automation demo complete!')
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main entry point."""
|
||||
print('Browser-Use MCP Client - Simple Example')
|
||||
print('=' * 50)
|
||||
print('\nConnecting to browser-use MCP server...\n')
|
||||
|
||||
try:
|
||||
await run_simple_browser_automation()
|
||||
except Exception as e:
|
||||
print(f'\n❌ Error: {e}')
|
||||
print('\nMake sure the browser-use MCP server is running:')
|
||||
print(" uvx 'browser-use[cli]' --mcp")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user