Engineering
Add Web Search to a Local LLM: Open WebUI and TinySearch
To give a local LLM web search, connect its chat client to a search tool and use a model capable of calling tools. In this walkthrough, Open WebUI calls TinySearch over MCP; TinySearch finds and reads web pages; your selected model writes the answer from the returned evidence.
The steps below assume Open WebUI and TinySearch run as native processes on the same machine. A Docker address table follows for existing container installations. No paid search API key is required for TinySearch’s default DDGS backend. Web queries still go to external search providers, and reading a page contacts that website.
Before you start
You need:
- Open WebUI with a working local model connection, such as Ollama. If you cannot chat with the model yet, complete the Open WebUI quick start first.
- An administrator account in Open WebUI to add an MCP connection.
- A version of Open WebUI supporting native MCP over Streamable HTTP, available from v0.6.31.
- uv on the machine that will run TinySearch.
- A model with native tool-calling support and enough memory and context capacity for its own requirements.
MCP makes tools available; it does not teach an unsuitable model to use them. Start with a model that already handles tool calls reliably in your client.
1. Prepare TinySearch
Check that uv is available, then download TinySearch’s browser and local embedding dependencies:
uv --versionuvx --python 3.12 --from "tinysuite-search[server]" tinysearch setupCheck readiness using the same environment:
uvx --python 3.12 --from "tinysuite-search[server]" tinysearch doctorResolve missing dependencies reported by doctor before continuing. On Linux, the installation troubleshooting guide covers Chromium system libraries. Preloading avoids placing browser and model downloads on your first scrape request.
2. Start the HTTP MCP server
Run this in a terminal and leave it open:
uvx --python 3.12 --from "tinysuite-search[server]" tinysearch serveTinySearch serves Streamable HTTP at /mcp on port 8000. For Open WebUI running natively on the same machine, the connection URL is:
http://localhost:8000/mcpThe command without serve starts a stdio server for clients that launch their own subprocesses. Open WebUI’s native MCP connection uses HTTP instead. A browser visit to /mcp is not an MCP handshake and is not a sufficient connection test.
If Open WebUI or TinySearch runs in Docker
Choose the address from the Open WebUI backend’s point of view:
| Deployment | TinySearch URL entered in Open WebUI |
|---|---|
| Both native on the same machine | http://localhost:8000/mcp |
| Open WebUI in Docker, TinySearch on the host | http://host.docker.internal:8000/mcp |
Both on the same Docker network, service named tinysearch |
http://tinysearch:8000/mcp |
| Native Open WebUI, TinySearch container published on host port 8000 | http://localhost:8000/mcp |
On Linux, the host-address option requires the host.docker.internal:host-gateway mapping in the Open WebUI container. TinySearch must also listen on an interface reachable from that container. Keep the endpoint on a trusted local network; configure authentication at your gateway before exposing it beyond that network. For a complete TinySearch container setup, use the Docker quick start.
3. Add TinySearch in Open WebUI
Open Settings → Admin → Integrations, then add an External Tool Server. Set its type to MCP (Streamable HTTP) and use the address from the table. Name the connection TinySearch. For this local setup, select authentication None; use your actual credentials if you have placed the server behind an authenticated gateway.
Save the connection and follow any restart prompt. In a new chat, enable TinySearch under Integrations → Tools. Menu labels can differ between releases; the Open WebUI MCP guide documents the current connection flow.
Select your local model and use Native function calling. Check that the available tools include get_current_datetime, search and scrape_urls. TinySearch also exposes browser tools when its browser backend is enabled. This first check only needs search and page reading.
4. Verify a search and a page read
Send a question that requires reading a specific source:
Use TinySearch to find the official SearXNG Search API documentation. Read the page and explain how to request JSON results and what happens when that output format is disabled. Cite the documentation URL. If a tool fails, report the error instead of guessing.
Inspect the tool activity, not just the final prose. A successful run should include:
- A TinySearch
searchcall returning a relevant documentation URL. - A
scrape_urlscall reading that URL with a focused query. - An answer grounded in the returned page, with a source link you can open.
For this question, the documentation describes format=json and a 403 response when the requested format is not enabled. Check that the retrieved text supports the model’s answer. A fluent answer without those tool calls does not demonstrate that the connection works.
For a second test, ask about a recent software release and have the model check the current date before searching. The answer should reflect retrieved release information, not only the model’s training data.
Troubleshooting
| Problem | What to check |
|---|---|
| No MCP connection type | Use an admin account and an Open WebUI release supporting native MCP |
| Connection refused | Keep tinysearch serve running; verify port 8000 and the backend’s network address |
| Connection hangs after setup | Confirm the type is MCP, the path is /mcp, and local auth is None rather than an empty Bearer token |
| Tools are connected but unused | Enable them for this chat and check Native tool calling and model support |
| First page read is slow | Run setup, then doctor, in the same environment as the server |
| Search works but a page cannot be read | Inspect the scrape error; a blocked or unavailable page is different from a broken MCP connection |
| Search returns backend errors | Inspect DDGS availability or configure a SearXNG instance using the linked guide |
Keep the evidence manageable
search finds candidate URLs without starting the browser or embedding model. scrape_urls reads selected pages; with a focused query, it ranks passages and returns evidence within configured budgets. Your client model still decides how to use and cite that evidence. See the MCP tool reference for the current arguments and output shapes.
Once the connection works, choose between DDGS and SearXNG for your search workload and tune the configuration limits. Keep inference and embeddings local if that is your goal, while accounting separately for the external requests required to search and read the web.