crawl_google_serp
Search Google for a keyword and retrieve search engine results pages (SERPs) with optional country targeting. Uses the Hubble API to crawl Google SERP data.
Instructions
구글 SERP API 요청
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | ||
| gl | No | kr |
Implementation Reference
- data_api.py:381-401 (handler)The main handler function for the 'crawl_google_serp' MCP tool. It sends a POST request to the Hubble API's /google_serp endpoint with a keyword and geolocation parameter, returning the SERP results as text.
@mcp.tool() @async_retry(exceptions=(Exception), tries=2, delay=0.3) async def crawl_google_serp( keyword: str, gl: Literal['kr', 'us', 'jp'] = "kr") -> dict[SerpResponse, Any] | None: ''' 구글 SERP API 요청 ''' async with httpx.AsyncClient() as client: payload = { "keyword": keyword, "gl": gl } headers = {"X-API-Key": HUBBLE_API_KEY} response = await client.post( f"{HUBBLE_API_URL}/google_serp", headers=headers, json=payload, timeout=30.0) response.raise_for_status() return response.text - data_api.py:272-278 (schema)The SerpResponse Pydantic model defining the response schema for SERP API responses, including request details, cost, remaining credits, and data payload.
class SerpResponse(BaseResponse): """SERP 응답 형식 """ request_detail: SerpParameters = Field(description="요청 받았던 파라미터") cost: int = Field(default=0, title="", description="") remain_credits: int = Field(default=-1, title="", description="") data: Optional[List[dict]] = Field(default=None, title="", description="") - data_api.py:249-266 (schema)The SerpParameters Pydantic model defining the input/request parameters for the SERP API (keyword, geolocation, result count, device).
class SerpParameters(BaseModel): """SERP 요청 형식 """ keyword: str = Field(min_length=1, title="요청 키워드") gl: Optional[Literal["kr", "jp", "us"]] = Field( default="kr", title="geo location", ) num: Optional[Literal[10, 20]] = Field( default=20, title="result num", description="SERP 에 표출할 결과 개수", ) device: Optional[Literal["mobile"]] = Field( default="mobile", title="device", description="(Deprecated) 요청 환경. mobile만 지원합니다.", ) - data_api.py:381-381 (registration)Registration of 'crawl_google_serp' as an MCP tool via the @mcp.tool() decorator on the FastMCP server instance 'mcp'.
@mcp.tool() - data_api.py:19-38 (helper)The async_retry decorator helper used by crawl_google_serp to retry the API call up to 2 times with a 0.3s delay on failure.
def async_retry(exceptions=(Exception), tries=3, delay=0.3, logger=None): def wrapper(func): @wraps(func) async def wrapped(*args, **kwargs): Tries = [] for i in range(tries): try: return await func(*args, **kwargs) except exceptions as ex: ex_msg = f"Tries({ex.__class__.__name__}) Cnt: {i+1}, {ex}" Tries.append(ex_msg) if logger: logger.warning(ex_msg) else: print(ex_msg) if delay: await asyncio.sleep(delay) raise TooManyTriesException(Tries) return wrapped return wrapper