Google Search MCP Server

by renoscriptdev
Verified
""" Google Search MCP Server A FastMCP server that provides Google Custom Search functionality. This server exposes a tool for performing Google searches and returning formatted results. It requires Google API Key and Custom Search Engine ID stored in environment variables. """ import os from typing import Dict, Any from mcp.server.fastmcp import FastMCP from googleapiclient.discovery import build from googleapiclient.errors import HttpError from dotenv import load_dotenv # Load configuration from .env load_dotenv() GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY') GOOGLE_CSE_ID = os.getenv('GOOGLE_CSE_ID') mcp = FastMCP("GoogleSearch") @mcp.tool() async def search_google(query: str, num_results: int = 5) -> Dict[str, Any]: """ Perform a Google search and return formatted results. This function uses Google Custom Search API to search the web based on the provided query. It formats the results into a consistent structure and handles potential errors. Args: query (str): The search query string num_results (int, optional): Number of search results to return. Defaults to 5. Returns: Dict[str, Any]: A dictionary containing: - success (bool): Whether the search was successful - results (list): List of dictionaries with title, link, and snippet - total_results (str): Total number of results found (when successful) - error (str): Error message (when unsuccessful) """ try: # Initialize Google Custom Search API service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY) # Execute the search # pylint: disable=no-member result = service.cse().list( q=query, cx=GOOGLE_CSE_ID, num=num_results ).execute() # Format the search results formatted_results = [] if "items" in result: for item in result["items"]: formatted_results.append({ "title": item.get("title", ""), "link": item.get("link", ""), "snippet": item.get("snippet", "") }) return { "success": True, "results": formatted_results, "total_results": result.get("searchInformation", {}).get("totalResults", "0") } except HttpError as error: return { "success": False, "error": f"API Error: {str(error)}", "results": [] } except Exception as error: # pylint: disable=broad-exception-caught return { "success": False, "error": str(error), "results": [] } if __name__ == "__main__": mcp.run()