Uber Eats MCP Server
#!/usr/bin/env python3
import asyncio
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP, Context
from browser import run_browser_agent
# Load environment variables from .env file
load_dotenv()
# Initialize FastMCP server
mcp = FastMCP("uber_eats")
# In-memory storage for search results
search_results = {}
@mcp.tool()
async def find_menu_options(search_term: str, context: Context) -> str:
"""Search Uber Eats for restaurants or food items.
Args:
search_term: Food or restaurant to search for
"""
# Create the search task
task = f"""
0. Start by going to: https://www.ubereats.com/se-en/
1. Type "{search_term}" in the global search bar and press enter
2. Go to the first search result (this is the most popular restaurant).
3. When you can see the menu options for the resturant, we need to use the specific search input for the resturant located under the banned (identify it by the placeholder "Search in [restaurant name]"
4. Click the input field and type "{search_term}", then press enter
5. Check for menu options related to "{search_term}"
6. Get the name, url and price of the top 3 items related to "{search_term}". URL is very important
"""
search_results[context.request_id] = f"Search for '{search_term}' in progress. Check back in 30 seconds"
asyncio.create_task(
perform_search(context.request_id, search_term, task, context)
)
return f"Search for '{search_term}' started. Please wait for 2 minutes, then you can retrieve results using the resource URI: resource://search_results/{context.request_id}. Use a terminal sleep statement to wait for 2 minutes."
async def perform_search(request_id: str, search_term: str, task: str, context: Context):
"""Perform the actual search in the background."""
try:
step_count = 0
async def step_handler(*args, **kwargs):
nonlocal step_count
step_count += 1
await context.info(f"Step {step_count} completed")
await context.report_progress(step_count)
result = await run_browser_agent(task=task, on_step=step_handler)
search_results[request_id] = result
except Exception as e:
# Store the error with the request ID
search_results[request_id] = f"Error: {str(e)}"
await context.error(f"Error searching for '{search_term}': {str(e)}")
@mcp.resource(uri="resource://search_results/{request_id}")
async def get_search_results(request_id: str) -> str:
"""Get the search results for a given request ID.
Args:
request_id: The ID of the request to get the search results for
"""
# Check if the results exist
if request_id not in search_results:
return f"No search results found for request ID: {request_id}"
# Return the successful search results
return search_results[request_id]
@mcp.tool()
async def order_food(item_url: str, item_name: str, context: Context) -> str:
"""Order food from a restaurant.
Args:
restaurant_url: URL of the restaurant
item_name: Name of the item to order
"""
task = f"""
1. Go to {item_url}
2. Click "Add to order"
3. Wait 3 seconds
4. Click "Go to checkout"
5. If there are upsell modals, click "Skip"
6. Click "Place order"
"""
# Start the background task for ordering
asyncio.create_task(
perform_order(item_url, item_name, task, context)
)
# Return a message immediately
return f"Order for '{item_name}' started. Your order is being processed."
async def perform_order(restaurant_url: str, item_name: str, task: str, context: Context):
"""Perform the actual food ordering in the background."""
try:
step_count = 0
async def step_handler(*args, **kwargs):
nonlocal step_count
step_count += 1
await context.info(f"Order step {step_count} completed")
await context.report_progress(step_count)
result = await run_browser_agent(task=task, on_step=step_handler)
# Report completion
await context.info(f"Order for '{item_name}' has been placed successfully!")
return result
except Exception as e:
error_msg = f"Error ordering '{item_name}': {str(e)}"
await context.error(error_msg)
return error_msg
if __name__ == "__main__":
mcp.run(transport='stdio')