Content
# OrioSearch self-host — web search + extract, with an MCP server for your agents
A one-command, self-hosted deployment of [OrioSearch](https://github.com/vkfolio/orio-search)
(Tavily-compatible **web search + content extraction** API) bundled with an **MCP
server** so your AI agents (Claude Code, Claude Desktop, Cursor…) get web search as
a native tool.
```
┌── docker compose up -d ────────────────────────────────────────────┐
│ orio-search REST API → http://localhost:8000 (/search /extract)
│ orio-mcp MCP server → http://localhost:7710/mcp (tavily_search, tavily_extract)
│ searxng + redis → internal only (search backend + cache)
└────────────────────────────────────────────────────────────────────┘
```
No LLM, no API account, no cloud — it searches the web via your own SearXNG.
## Requirements
- Docker + Docker Compose v2 (`docker compose version`)
- ~2 GB RAM free, outbound Internet access
## Quick start
```bash
git clone https://github.com/budhaz01/oriosearch-selfhost.git
cd oriosearch-selfhost
# 1. give SearXNG its own secret
sed -i "s/CHANGE_ME_openssl_rand_hex_32/$(openssl rand -hex 32)/" searxng/settings.yml
# 2. build + run (first build clones the upstream engine + builds — a few minutes)
docker compose up -d --build
# 3. check it's healthy
docker compose ps
curl http://localhost:8000/health
```
## Use the REST API
```bash
curl -X POST http://localhost:8000/search \
-H "Content-Type: application/json" \
-d '{"query":"kubernetes best practices 2026","max_results":5}'
curl -X POST http://localhost:8000/extract \
-H "Content-Type: application/json" \
-d '{"urls":["https://example.com"],"format":"markdown"}'
```
Response shape is Tavily-compatible (`{query, answer, results[], images[], response_time}`).
## Use the MCP server (Claude Code, Cursor, Claude Desktop)
The MCP server exposes two tools — `tavily_search` and `tavily_extract`.
**Claude Code (CLI):**
```bash
claude mcp add orio --transport http http://localhost:7710/mcp
```
**Claude Desktop / Cursor (JSON config):**
```json
{
"mcpServers": {
"orio": { "type": "http", "url": "http://localhost:7710/mcp" }
}
}
```
Then your agent can search the web. (On localhost no key is needed — see below to
expose it safely.)
## Configuration
- **`config.yaml`** — the engine: search backend, cache, rate limits, auth, LLM.
- **`searxng/settings.yml`** — the SearXNG backend (engines, secret key).
- **`docker-compose.yml`** — ports, resources.
### Optional: AI answers (`include_answer`)
Search/extract work without any LLM. To get an AI-written summary in the `answer`
field, set `llm.enabled: true` in `config.yaml` and point `base_url` / `api_key` /
`model` at any OpenAI-compatible endpoint (OpenAI, a local Ollama, GLM/Zhipu, …).
## Exposing publicly (read before you do)
By default both ports bind to **127.0.0.1** — only this host can reach them. To
serve other machines or the Internet:
1. **Engine** — set `auth.enabled: true` + add keys under `api_keys` in
`config.yaml` (clients then send `Authorization: Bearer <key>`), then change the
`orio-search` port in `docker-compose.yml` from `127.0.0.1:8000:8000` to
`8000:8000` (or front it with a reverse proxy + TLS).
2. **MCP server** — `orio-mcp` has **no built-in auth**. Do **not** expose it
directly; put it behind a reverse proxy that checks a token (or keep it
localhost / LAN-only).
## Manage
```bash
docker compose logs -f orio-search # logs
docker compose restart orio-search # restart
docker compose pull && docker compose up -d --build # update
docker compose down # stop
```
## Credits
Engine: [vkfolio/orio-search](https://github.com/vkfolio/orio-search). The MCP
server adapts the [Tavily MCP](https://github.com/tavily-ai/tavily-mcp) to call
OrioSearch instead of api.tavily.com.