TinySearch: self-hosted MCP web research for local LLMs
1 min read
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
answerfield (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
jsontosearch.formatsor TinySearch errors with “SearXNG did not return JSON”. MIT-licensed.