TinySearch: self-hosted MCP web research for local LLMs

1 min read
mcpself-hostinglocal-llmrag
View as Markdown
Originally from github.com
View source

My notes

Summary

TinySearch is a self-hosted MCP server that gives local AI agents real web research: it searches, reranks, crawls the best pages, extracts the most relevant chunks, and returns a source-grounded prompt the model answers from with citations. No hosted dashboard, account, analytics or scraped-data cache, just a small stack you run in Docker. It is built for local agents and personal workflows where source-grounded research matters more than a full search product.

Key Insight

  • Grounded-prompt pattern, not an answer engine. TinySearch never answers the question itself. It returns a structured prompt in the MCP tool’s answer field (QUESTION / TODAY / RESULTS with URLs + extracted text / INSTRUCTIONS to cite sources), and your client model writes the cited final response. This keeps citations attached to evidence and avoids dumping whole webpages into context.
  • Pipeline: search (SearXNG default, DuckDuckGo HTML fallback) -> filter HTTP results -> rank with weighted RRF (dense embeddings + BM25) -> parallel crawl via crawl4ai to markdown -> chunk -> rerank combined chunk pool -> dedupe with per-source quotas -> assemble grounded prompt.
  • Three MCP tools only: research(query) to discover URLs, scrape_url(url, query) when a URL is already known, get_current_datetime() before time-sensitive research.
  • Local by default: ONNX embeddings run locally (presets fast = all-MiniLM-L6-v2, balanced = bge-small-en-v1.5, quality = bge-base-en-v1.5), or bring an OpenAI-compatible embedding API. The pipeline requires dense embeddings, it raises if dense weight is 0.
  • Security on user-supplied URLs: only http/https, rejects embedded credentials, and blocks loopback/private/link-local/reserved IPs, rejecting if any resolved address is non-public (DNS-rebinding mitigation). Safety check runs on both initial and final (post-redirect) URL; crawl4ai hides intermediate hops, so strict redirect policy needs an egress proxy.
  • Not a replacement for a commercial search API or persistent crawler, no guaranteed coverage, no large-scale indexing, no long-term caching, no SLA. Lightweight by design.
  • Since v0.2 defaults to SearXNG; note SearXNG ships with JSON output disabled, you must add json to search.formats or TinySearch errors with “SearXNG did not return JSON”. MIT-licensed.