- This repo is an MCP server exposing web search tools backed by Serper.dev.
- Entry point is
main.py, which wires FastMCP tools, middleware, and lifecycle cleanup.
main.py: defines MCP tools (search_web,search_web_ui,extract_webpage) and/healthroute.search/serper.py: Serper API integration and shared async HTTP client (SerperClient).search/ui.py: builds raw HTML carousel UI and wraps it asUIResource.middleware.py: request logging + optional bearer auth (skips auth for MCPinitialize).config.py: env-driven settings, cached viaget_config().
- Text search flow:
search_web_tool->google_search()-> POSThttps://google.serper.dev/search-> formatted text. - UI search flow:
search_web_ui_tool->google_search_raw()->create_search_results_ui()->UIResourcelist. - Extraction flow:
extract_webpage_tool->extract_page_content()-> POSThttps://scrape.serper.dev/.
- Tool functions use
@mcp.tool(...)andAnnotated[..., Field(...)]for parameter schemas. search_web_uireturnslist[UIResource], not plain strings.- UI HTML in
search/ui.pyposts:ui-size-changefor dynamic iframe sizing.toolmessage callingextract_webpagewhen user clicks Extract.
create_search_results_ui()uses timestampedui://mcp-search/...URIs to avoid UI caching.
- External services:
- Serper Search API (
google.serper.dev/search) - Serper Scrape API (
scrape.serper.dev) - Google favicon endpoint used in UI cards.
- Serper Search API (
- Internal boundary: keep transport/middleware/tool registration in
main.py; keep external API calling logic insearch/serper.py.
- Reuse
SerperClient.get_client(); do not create per-requesthttpx.AsyncClientinstances. - Surface API failures via
SerperAPIErrorstyle used insearch/serper.py. - Keep auth semantics intact (do not require auth for MCP
initialize). - If adding UI tools, match existing postMessage contract and return
UIResourceobjects.