Skip to main content
Glama
arben-adm

Brave Search MCP Server

brave_local_search

Find nearby businesses and locations using Brave Search. Enter location terms to get relevant local results.

Instructions

Search for local businesses and places

        Args:
            query: Location terms
            count: Results (1-20
        

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
countNo

Implementation Reference

  • Main handler for the 'brave_local_search' tool. Decorated with @self.mcp.tool() for registration. Implements local business search logic: queries Brave API for locations, paginates if needed, fetches POI/details, formats output, falls back to web search.
    @self.mcp.tool() 
    async def brave_local_search(
        query: str,
        count: Optional[int] = 20  # Changed default from 5 to 20
    ) -> str:
        """Search for local businesses and places
        
        Args:
            query: Location terms
            count: Results (1-20
        """
        self.rate_limit.check()
    
        # Initial location search
        params = {
            "q": query,
            "search_lang": "en",
            "result_filter": "locations",
            "count": 20  # Always request maximum results
        }
    
        client = self.get_client()
        response = await client.get(
            f"{self.base_url}/web/search",
            params=params
        )
        response.raise_for_status()
        data = response.json()
    
        location_ids = self._extract_location_ids(data)
        if not location_ids:
            # If no local results found, fallback to web search
            # with minimum 10 results
            return await brave_web_search(query, 20)
    
        # If we have less than 10 location IDs, try to get more
        offset = 0
        while len(location_ids) < 10 and offset < 40:
            offset += 20
            additional_response = await client.get(
                f"{self.base_url}/web/search",
                params={
                    "q": query,
                    "search_lang": "en",
                    "result_filter": "locations",
                    "count": 20,
                    "offset": offset
                }
            )
            additional_data = additional_response.json()
            location_ids.extend(self._extract_location_ids(additional_data))
    
        # Get details for at least 10 locations
        pois, descriptions = await self._get_location_details(
            location_ids[:max(10, len(location_ids))]
        )
        return self._format_local_results(pois, descriptions)
  • Helper function to fetch detailed POI (points of interest) and description data for location IDs using parallel asyncio.gather calls to Brave API.
    async def _get_location_details(
        self,
        ids: List[str]
    ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
        """Fetch POI and description data for locations"""
        client = self.get_client()
        pois_response, desc_response = await asyncio.gather(
            client.get(
                f"{self.base_url}/local/pois",
                params={"ids": ids}
            ),
            client.get(
                f"{self.base_url}/local/descriptions",
                params={"ids": ids}
            )
        )
        return (
            pois_response.json(),
            desc_response.json()
        )
  • Helper to extract location IDs from the initial web search response filtered by 'locations'.
    def _extract_location_ids(self, data: Dict) -> List[str]:
        """Extract location IDs from search response"""
        return [
            result["id"] 
            for result in data.get("locations", {}).get("results", [])
            if "id" in result
        ]
  • Helper to format the retrieved POI data and descriptions into a readable multi-line string output separated by ---.
    def _format_local_results(
        self,
        pois: Dict[str, Any],
        descriptions: Dict[str, Any]
    ) -> str:
        """Format local search results with details"""
        results = []
        for poi in pois.get("results", []):
            location = {
                "name": poi.get("name", "N/A"),
                "address": self._format_address(poi.get("address", {})),
                "phone": poi.get("phone", "N/A"),
                "rating": self._format_rating(poi.get("rating", {})),
                "price": poi.get("priceRange", "N/A"),
                "hours": ", ".join(poi.get("openingHours", [])) or "N/A",
                "description": descriptions.get("descriptions", {}).get(
                    poi["id"], "No description available"
                )
            }
            
            results.append(
                f"Name: {location['name']}\n"
                f"Address: {location['address']}\n"
                f"Phone: {location['phone']}\n"
                f"Rating: {location['rating']}\n"
                f"Price Range: {location['price']}\n"
                f"Hours: {location['hours']}\n"
                f"Description: {location['description']}"
            )
  • Helper utility to format address dictionary into a comma-separated string.
    def _format_address(self, addr: Dict) -> str:
        """Format address components"""
        components = [
            addr.get("streetAddress", ""),
            addr.get("addressLocality", ""),
            addr.get("addressRegion", ""),
            addr.get("postalCode", "")
        ]
        return ", ".join(filter(None, components)) or "N/A"
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/arben-adm/brave-mcp-search'

If you have feedback or need assistance with the MCP directory API, please join our Discord server