search_web
Run a web search and retrieve the top results as clean Markdown, combining search and reading to get fresh information in one call.
Instructions
Run a web search and return the top-k result pages already converted to clean Markdown. Use this whenever you need fresh information from the public web — it combines search and read in one call.
Args: q: The user's query (free text). k: How many results to fetch (1–10, default 5). max_tokens: Optional per-result soft cap on the returned Markdown.
Returns:
A list of {url, title, snippet, ok, markdown, word_count, error?}
result objects. Use title and snippet to decide which results are
worth citing, then drop the markdown field into your prompt.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | ||
| k | No | ||
| max_tokens | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The async handler function for the search_web tool. Takes a search query string 'q', optional 'k' (number of results, default 5), and optional 'max_tokens'. Makes a GET request to the SEARCH_URL /search endpoint with these params and returns the 'results' list from the JSON response.
@mcp.tool() async def search_web(q: str, k: int = 5, max_tokens: Optional[int] = None) -> list[dict]: """Run a web search and return the top-k result pages already converted to clean Markdown. Use this whenever you need fresh information from the public web — it combines search and read in one call. Args: q: The user's query (free text). k: How many results to fetch (1–10, default 5). max_tokens: Optional per-result soft cap on the returned Markdown. Returns: A list of `{url, title, snippet, ok, markdown, word_count, error?}` result objects. Use `title` and `snippet` to decide which results are worth citing, then drop the `markdown` field into your prompt. """ params: dict[str, str | int] = {"q": q, "k": k} if max_tokens: params["max_tokens"] = max_tokens async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client: resp = await client.get(f"{SEARCH_URL}/search", params=params) resp.raise_for_status() return resp.json().get("results", []) - src/ai_first_scraper_mcp/server.py:84-84 (registration)The tool is registered as an MCP tool using the @mcp.tool() decorator on the search_web function. The FastMCP instance 'mcp' is created on line 32.
@mcp.tool() - The input schema is defined through type hints in the function signature: q (str), k (int, default 5), max_tokens (Optional[int]). The return type is list[dict], documented to contain keys: url, title, snippet, ok, markdown, word_count, error?.
@mcp.tool() - The SEARCH_URL config constant used by search_web to determine the upstream search API endpoint. Defaults to https://ai-first-search.onrender.com and can be overridden via the SEARCH_URL environment variable.
SCRAPER_URL = os.getenv("SCRAPER_URL", "https://ai-first-scraper.onrender.com").rstrip("/") SEARCH_URL = os.getenv("SEARCH_URL", "https://ai-first-search.onrender.com").rstrip("/") DEFAULT_TIMEOUT = float(os.getenv("AFS_TIMEOUT", "45"))