Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from typing import Mapping | |
| from dotenv import load_dotenv | |
| from backend.api.mcp_clients.web_client import WebClient | |
| from backend.mcp_server.common.tenant import TenantContext | |
| from backend.mcp_server.common.utils import ToolValidationError, tool_handler | |
| load_dotenv() | |
| _web_client = WebClient() | |
| async def web_search(context: TenantContext, payload: Mapping[str, object]) -> dict[str, object]: | |
| """ | |
| Perform a Google Custom Search query with basic max-results and region controls. | |
| """ | |
| query = payload.get("query") | |
| if not isinstance(query, str) or not query.strip(): | |
| raise ToolValidationError("query must be a non-empty string") | |
| max_results = payload.get("max_results", 5) | |
| try: | |
| max_results_value = max(1, min(int(max_results), 10)) | |
| except (TypeError, ValueError): | |
| raise ToolValidationError("max_results must be an integer between 1 and 10") | |
| region = str(payload.get("region", "us")) | |
| metadata = { | |
| "max_results": max_results_value, | |
| "region": region, | |
| "source": "google", | |
| } | |
| try: | |
| results = await _web_client.search(query, max_results=max_results_value, region=region) | |
| except RuntimeError as exc: | |
| metadata["error"] = str(exc) | |
| return {"query": query, "results": [], "metadata": metadata} | |
| return { | |
| "query": query, | |
| "results": [ | |
| { | |
| "title": item.get("title"), | |
| "snippet": item.get("snippet"), | |
| "url": item.get("link"), | |
| } | |
| for item in results | |
| ], | |
| "metadata": metadata, | |
| } | |