arcade-mcp/toolkits/search/arcade_search/utils.py
Eric Gustin 99ff11d30e
Various Search Toolkits (#285)
1. Add the following tools:
* Google Finance
    - get_stock_summary
    - get_stock_historical_data
* Google Flights
    - search_roundtrip_flights
    - search_one_way_flights
* Google Hotels
    - search_hotels
    
2. Add some common helper functions for serpAPI tools.
2025-03-14 14:23:14 -07:00

74 lines
2.5 KiB
Python

import re
from typing import Any
import serpapi
from arcade.sdk import ToolContext
from arcade.sdk.errors import ToolExecutionError
# ------------------------------------------------------------------------------------------------
# General SerpAPI utils
# ------------------------------------------------------------------------------------------------
def prepare_params(engine: str, **kwargs: Any) -> dict[str, Any]:
"""
Prepares a parameters dictionary for the SerpAPI call.
Parameters:
engine: The engine name (e.g., "google", "google_finance").
kwargs: Any additional parameters to include.
Returns:
A dictionary containing the base parameters plus any extras,
excluding any parameters whose value is None.
"""
params = {"engine": engine}
params.update({k: v for k, v in kwargs.items() if v is not None})
return params
def call_serpapi(context: ToolContext, params: dict) -> dict:
"""
Execute a search query using the SerpAPI client and return the results as a dictionary.
Args:
context: The tool context containing required secrets.
params: A dictionary of parameters for the SerpAPI search.
Returns:
The search results as a dictionary.
"""
api_key = context.get_secret("SERP_API_KEY")
client = serpapi.Client(api_key=api_key)
try:
search = client.search(params)
return search.as_dict() # type: ignore[no-any-return]
except Exception as e:
# SerpAPI error messages sometimes contain the API key, so we need to sanitize it
sanitized_e = re.sub(r"(api_key=)[^ &]+", r"\1***", str(e))
raise ToolExecutionError(
message="Failed to fetch search results",
developer_message=sanitized_e,
)
# ------------------------------------------------------------------------------------------------
# Google Flights utils
# ------------------------------------------------------------------------------------------------
def parse_flight_results(results: dict[str, Any]) -> dict[str, Any]:
"""Parse the flight results from the Google Flights API
Note: Best flights is not always returned from the API.
"""
flight_data = {}
flights = []
if "best_flights" in results:
flights.extend(results["best_flights"])
if "other_flights" in results:
flights.extend(results["other_flights"])
if "price_insights" in results:
flight_data["price_insights"] = results["price_insights"]
flight_data["flights"] = flights
return flight_data