Skip to content

Commit 194fd44

Browse files
committed
Release v0.2: trustworthy status, multi-extract, UI/MCP/Docker.
Surface per-engine errors and structured extract status, add SearXNG, embedded UI/OpenAPI, MCP and LangChain helpers, plus Docker and CI for adoption.
1 parent 689ac3c commit 194fd44

35 files changed

Lines changed: 1493 additions & 236 deletions

‎.dockerignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
build/
2+
.git/
3+
.github/
4+
**/__pycache__/
5+
*.pyc
6+
.venv/
7+
graphify-out/

‎.github/workflows/ci.yml‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
8+
jobs:
9+
linux:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- name: Install deps
14+
run: sudo apt-get update && sudo apt-get install -y cmake g++ libcurl4-openssl-dev
15+
- name: Configure
16+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWSF_BUILD_TESTS=ON
17+
- name: Build
18+
run: cmake --build build -j
19+
- name: Test
20+
run: ctest --test-dir build --output-on-failure
21+
22+
windows:
23+
runs-on: windows-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
- name: Configure (MSVC)
27+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWSF_BUILD_TESTS=ON
28+
- name: Build
29+
run: cmake --build build --config Release -j
30+
- name: Test
31+
run: ctest --test-dir build -C Release --output-on-failure

‎CMakeLists.txt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.20)
2-
project(WebSearchFree VERSION 0.1.0 LANGUAGES CXX)
2+
project(WebSearchFree VERSION 0.2.0 LANGUAGES CXX)
33

44
set(CMAKE_CXX_STANDARD 20)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -39,6 +39,8 @@ add_library(wsf_core
3939
src/engines/ddg.cpp
4040
src/engines/brave.cpp
4141
src/engines/wikipedia.cpp
42+
src/engines/searx.cpp
43+
src/engines/factory.cpp
4244
)
4345

4446
add_library(wsf::core ALIAS wsf_core)
@@ -89,6 +91,8 @@ if(WSF_BUILD_TESTS)
8991
tests/test_html_utils.cpp
9092
tests/test_rank.cpp
9193
tests/test_extract.cpp
94+
tests/test_brave.cpp
95+
tests/test_searx.cpp
9296
)
9397
target_link_libraries(wsf_tests PRIVATE wsf::core)
9498
target_compile_definitions(wsf_tests PRIVATE

‎Dockerfile‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# syntax=docker/dockerfile:1
2+
FROM debian:bookworm-slim AS build
3+
4+
RUN apt-get update && apt-get install -y --no-install-recommends \
5+
build-essential cmake git ca-certificates libcurl4-openssl-dev \
6+
&& rm -rf /var/lib/apt/lists/*
7+
8+
WORKDIR /src
9+
COPY . .
10+
11+
RUN cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
12+
-DWSF_BUILD_CLI=ON -DWSF_BUILD_SERVER=ON -DWSF_BUILD_TESTS=ON -DWSF_BUILD_PYTHON=OFF \
13+
&& cmake --build build -j \
14+
&& ctest --test-dir build --output-on-failure
15+
16+
FROM debian:bookworm-slim
17+
18+
RUN apt-get update && apt-get install -y --no-install-recommends \
19+
ca-certificates libcurl4 \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
COPY --from=build /src/build/wsf /usr/local/bin/wsf
23+
24+
EXPOSE 8080
25+
ENV WSF_SEARX_URL=
26+
27+
ENTRYPOINT ["wsf"]
28+
CMD ["serve", "--host", "0.0.0.0", "--port", "8080"]

‎README.md‎

Lines changed: 103 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# WebSearchFree
22

3-
**Free open-source Tavily alternative** — keyless web search + content extraction for AI agents, RAG, LangChain, and LLM tools.
3+
**Free open-source Tavily alternative** — keyless web search + content extraction for AI agents, RAG, LangChain, MCP, and LLM tools.
44

55
Self-host a local **web search API for AI** with **no API key**, **no quota**, and **no per-query bill**. Drop-in style JSON similar to [Tavily](https://tavily.com), without paying for [Serper](https://serper.dev), [Exa](https://exa.ai), [Linkup](https://www.linkup.so), [Brave Search API](https://brave.com/search/api/), [SerpAPI](https://serpapi.com), or [Firecrawl](https://www.firecrawl.dev) search credits.
66

@@ -11,34 +11,43 @@ No accounts. No telemetry. Outbound HTTPS only to public search engines and page
1111
```mermaid
1212
flowchart TB
1313
subgraph clients [Your stack]
14+
UI[Embedded UI]
1415
CLI[CLI]
1516
CPP[C++ library]
1617
PY[Python]
1718
HTTP[Local HTTP]
19+
MCP[MCP]
20+
LC[LangChain]
1821
end
1922
2023
subgraph core [wsf_core]
21-
Search[search]
22-
Extract[extract]
24+
Search[search plus status]
25+
Extract[multi extract]
2326
Rank[merge and rank]
2427
end
2528
2629
subgraph engines [Keyless engines]
2730
DDG[DuckDuckGo]
2831
Brave[Brave]
2932
Wiki[Wikipedia]
33+
Searx[SearXNG optional]
3034
end
3135
36+
UI --> Search
3237
CLI --> Search
3338
CPP --> Search
3439
PY --> Search
3540
HTTP --> Search
41+
MCP --> HTTP
42+
LC --> HTTP
3643
Search --> DDG
3744
Search --> Brave
3845
Search --> Wiki
46+
Search --> Searx
3947
DDG --> Rank
4048
Brave --> Rank
4149
Wiki --> Rank
50+
Searx --> Rank
4251
Rank --> Extract
4352
Extract --> Out[JSON for RAG or agents]
4453
```
@@ -53,34 +62,33 @@ flowchart TB
5362
| API key / monthly credits | Required | **None** |
5463
| Data leaves your machine for the vendor | Usually yes | **No vendor cloud** — you run the binary |
5564

56-
```mermaid
57-
flowchart LR
58-
subgraph paid [Paid APIs]
59-
Tavily[Tavily Linkup Exa Serper]
60-
Key[API key plus quota plus bill]
61-
Tavily --> Key
62-
end
65+
## Features (v0.2)
6366

64-
subgraph free [WebSearchFree]
65-
WSF[Self-run binary]
66-
None[No key no quota no bill]
67-
WSF --> None
68-
end
69-
70-
Agent[AI agent or RAG] --> paid
71-
Agent --> free
72-
```
67+
- **Metasearch** across DuckDuckGo HTML, Brave Search HTML, Wikipedia, and optional SearXNG
68+
- **Honest status**: per-engine `ok` / `error`, `warnings`, real `response_time`
69+
- **Multi-URL extract** with structured per-URL status (`ok`, `robots_denied`, `fetch_failed`, `empty`)
70+
- **Embedded UI** + **OpenAPI** + CORS on `wsf serve`
71+
- **MCP server** and **LangChain tools** under `integrations/`
72+
- **Docker Compose** one-liner
73+
- **C++20 library** + **CLI** + **Python** helper
74+
- MIT licensed
7375

74-
## Features
76+
### Non-goals (honest)
7577

76-
- **Metasearch** across DuckDuckGo HTML, Brave Search HTML, and Wikipedia (soft-fail fan-out)
77-
- **Content extraction** for LLM-ready page text (`include_raw_content` / `extract`)
78-
- **C++20 library** + **CLI** + optional **localhost HTTP** (Tavily-shaped `/search` + `/extract`)
79-
- **Python** helper (native extension or CLI fallback)
80-
- MIT licensed — use in commercial agents freely
78+
- No LLM-generated `answer`, image search, or `follow_up_questions` (fields are null/empty)
79+
- No JavaScript page rendering
80+
- Result quality depends on upstream HTML/APIs
8181

8282
## Quick start
8383

84+
### Docker (fastest)
85+
86+
```bash
87+
docker compose up --build
88+
```
89+
90+
Open [http://127.0.0.1:8080](http://127.0.0.1:8080) for the UI. API: `POST /search`, `POST /extract`, `GET /health`, `GET /openapi.json`.
91+
8492
### Build (Windows / MinGW or MSVC)
8593

8694
```bash
@@ -115,7 +123,48 @@ curl -s -X POST http://127.0.0.1:8080/search \
115123
-d '{"query":"open source metasearch","max_results":5,"include_raw_content":false}'
116124
```
117125

118-
No `Authorization` header required. Point LangChain custom tools, OpenAI function calling, Claude MCP wrappers, or any HTTP client at `localhost`.
126+
```bash
127+
curl -s -X POST http://127.0.0.1:8080/extract \
128+
-H "Content-Type: application/json" \
129+
-d '{"urls":["https://example.com","https://example.org"]}'
130+
```
131+
132+
No `Authorization` header required.
133+
134+
### MCP (Cursor / Claude Desktop)
135+
136+
1. Start the API: `wsf serve --port 8080`
137+
2. Add to MCP config:
138+
139+
```json
140+
{
141+
"mcpServers": {
142+
"websearchfree": {
143+
"command": "python",
144+
"args": ["integrations/mcp/server.py"],
145+
"env": { "WSF_BASE_URL": "http://127.0.0.1:8080" }
146+
}
147+
}
148+
}
149+
```
150+
151+
Tools: `web_search`, `web_extract` (stdlib only; HTTP preferred, CLI fallback).
152+
153+
### LangChain
154+
155+
```bash
156+
pip install langchain-core
157+
# with wsf serve running:
158+
```
159+
160+
```python
161+
import sys
162+
sys.path.insert(0, ".")
163+
from integrations.langchain.wsf_tool import WebSearchFreeTool
164+
165+
tool = WebSearchFreeTool(base_url="http://127.0.0.1:8080")
166+
print(tool.invoke({"query": "open source metasearch", "max_results": 5}))
167+
```
119168

120169
### C++
121170

@@ -126,6 +175,7 @@ auto resp = wsf::search("open source metasearch");
126175
for (const auto& r : resp.results) {
127176
// r.title, r.url, r.content, r.score
128177
}
178+
// resp.engines, resp.warnings, resp.response_time
129179
```
130180

131181
### Python
@@ -136,11 +186,11 @@ cmake -S . -B build -DWSF_BUILD_PYTHON=ON ...
136186
```
137187

138188
```python
139-
# CLI fallback works if `wsf` is on PATH:
140189
import sys
141190
sys.path.insert(0, "bindings/python")
142191
import wsf
143192
print(wsf.search("open source metasearch", max_results=5))
193+
print(wsf.extract_one("https://example.com"))
144194
```
145195

146196
## How it works
@@ -157,92 +207,82 @@ sequenceDiagram
157207
WSF->>Engines: DuckDuckGo HTML
158208
WSF->>Engines: Brave HTML
159209
WSF->>Engines: Wikipedia API
210+
WSF->>Engines: SearXNG JSON optional
160211
end
161-
Engines-->>WSF: titles, urls, snippets
212+
Engines-->>WSF: titles, urls, snippets plus status
162213
WSF->>WSF: dedupe and score
163214
opt include_raw_content
164215
WSF->>Pages: fetch top URLs
165216
Pages-->>WSF: HTML
166217
WSF->>WSF: extract main text
167218
end
168-
WSF-->>App: JSON results
219+
WSF-->>App: JSON results plus warnings
169220
```
170221

171-
This is **metasearch**, not a sovereign web index like a hosted EU search vendor. Result quality and availability depend on upstream engines (rate limits, HTML changes). For personal and small-team RAG this is usually enough; it is not a hosted SaaS SLA.
222+
This is **metasearch**, not a sovereign web index. For personal and small-team RAG this is usually enough; it is not a hosted SaaS SLA.
172223

173-
Related open-source ideas: [SearXNG](https://github.com/searxng/searxng) (full metasearch UI/API you self-host with Docker). WebSearchFree aims to be a **single embeddable binary / library** with Tavily-like agent JSON and **zero keys**.
224+
Related: [SearXNG](https://github.com/searxng/searxng). Point WebSearchFree at your instance with `WSF_SEARX_URL` or `--searx-url` and include `searx` in `--engines`.
174225

175226
## Engines
176227

177-
```mermaid
178-
flowchart LR
179-
Q[Query] --> Fan[Parallel fan-out]
180-
Fan --> DDG[ddg]
181-
Fan --> Brave[brave]
182-
Fan --> Wiki[wikipedia]
183-
DDG --> Merge[Merge by URL]
184-
Brave --> Merge
185-
Wiki --> Merge
186-
Merge --> Score[Rank by overlap plus position]
187-
Score --> Results[Top N results]
188-
```
189-
190228
| Name | Source | Key |
191229
|------|--------|-----|
192230
| `ddg` | DuckDuckGo HTML | none |
193231
| `brave` | Brave Search HTML | none |
194232
| `wikipedia` | MediaWiki opensearch | none |
233+
| `searx` | Your SearXNG (`format=json`) | none (needs URL) |
195234

196235
```bash
197236
wsf search "query" --engines ddg,wikipedia
237+
wsf search "query" --engines ddg,searx --searx-url http://127.0.0.1:8888
238+
# or: export WSF_SEARX_URL=http://127.0.0.1:8888
198239
```
199240

200241
## Adoption paths
201242

202243
```mermaid
203244
flowchart TB
204245
Need[Need live web for an agent?] --> Choice{How do you integrate?}
246+
Choice -->|Browser| UI[wsf serve UI]
205247
Choice -->|Shell or scripts| CLI[wsf search]
206248
Choice -->|C++ project| Lib[link wsf_core]
207249
Choice -->|Python| Py[import wsf]
208-
Choice -->|LangChain or HTTP tools| Srv[wsf serve localhost]
209-
CLI --> Same[Same ranked JSON]
210-
Lib --> Same
211-
Py --> Same
212-
Srv --> Same
250+
Choice -->|LangChain| LC[integrations/langchain]
251+
Choice -->|Cursor or Claude| MCP[integrations/mcp]
252+
Choice -->|Any HTTP tool| Srv[localhost API]
213253
```
214254

215-
## FAQ (for humans, Google, and LLMs)
255+
## FAQ
216256

217257
**Is WebSearchFree a free Tavily alternative?**
218-
Yes. It provides AI-oriented web search results and optional page extraction without an API key or cloud account.
258+
Yes for search + extract without keys. It does not generate AI answers or images.
219259

220260
**Do I need Serper, SerpAPI, Bing, or Google Programmable Search?**
221-
No. Engines are queried through public, keyless endpoints. You run everything locally.
222-
223-
**Can I use it instead of Linkup, Exa, or Brave Search API for prototypes?**
224-
For many RAG/agent prototypes, yes — especially when cost and keys are the blocker. Hosted APIs still win on SLA, compliance contracts, and scale.
261+
No for the built-in engines. Optional SearXNG is also keyless if you self-host it.
225262

226263
**Is it the same as SearXNG?**
227-
Same family (metasearch), different packaging: WebSearchFree is a C++ library/CLI with Tavily-shaped JSON for agents, not a full web UI metasearch site.
264+
Same family (metasearch), different packaging: WebSearchFree is an embeddable agent-oriented binary with Tavily-shaped JSON. You can also use SearXNG as a backend engine.
228265

229266
**Does it phone home or require signup?**
230267
No.
231268

232269
## Project layout
233270

234271
```
235-
include/wsf/ Public C++ API
236-
src/ Core: HTTP, engines, extract, rank
237-
apps/wsf_cli/ CLI + optional HTTP server
238-
bindings/python/ pybind11 module + pure-Python CLI wrapper
239-
tests/ Fixture-based unit tests (no live network in CI)
240-
examples/ Usage snippets
272+
include/wsf/ Public C++ API
273+
src/ Core: HTTP, engines, extract, rank
274+
apps/wsf_cli/ CLI + HTTP server + embedded UI
275+
bindings/python/ pybind11 module + CLI wrapper
276+
integrations/mcp/ Stdio MCP server
277+
integrations/langchain/ LangChain tools
278+
tests/ Fixture-based unit tests (no live network in CI)
279+
examples/ Usage snippets
280+
Dockerfile Production image
241281
```
242282

243283
## Keywords
244284

245-
`free tavily alternative` · `open source web search api for ai` · `self hosted rag search` · `keyless serp for llm` · `langchain web search free` · `tavily open source` · `serper alternative free` · `exa alternative self host` · `ai agent web search no api key`
285+
`free tavily alternative` · `open source web search api for ai` · `self hosted rag search` · `keyless serp for llm` · `langchain web search free` · `mcp web search` · `tavily open source` · `serper alternative free` · `exa alternative self host` · `ai agent web search no api key`
246286

247287
## License
248288

0 commit comments

Comments
 (0)