Fact-check retrieval service for Faktenforum. Hybrid semantic plus full-text search over fact-checks, exposed as REST API, MCP tools, and a Nuxt 4 admin UI.
- Hybrid retrieval: pgvector embeddings plus language-aware PostgreSQL full-text search with RRF; explicit language per query (e.g. de, en; auto not yet supported).
- Admin UI: Nuxt 4 dashboard for searching fact-checks, browsing claims, inspecting chunks, and managing imports.
- MCP integration: First-class Model Context Protocol server with tools for search, detail lookup, and category listing.
- Import pipeline: JSON dump importer with background jobs, progress tracking, cancellation, and re-import of changed claims only.
- PostgreSQL + pgvector: Typed core library for database access, chunking, embeddings, and statistics.
This repository is a Bun workspace with three packages:
| Package | Description |
|---|---|
core |
Shared TypeScript library with config, database access, chunking, embeddings, search, import, and statistics. See core/README.md. |
frontend |
Nuxt 4 admin UI and Nitro server that exposes /api/v1/**, /health, and /mcp. See frontend/README.md. |
mcp |
Reusable MCP server wiring and tools, used by the Nitro route and embeddable in other hosts. See mcp/README.md. |
You can run Search without the full LibreChat stack.
-
Environment
Copy.env.exampleto.envin the repo root. At minimum set:SEARCH_EMBEDDING_API_KEY- embedding provider API keySEARCH_POSTGRES_PASSWORD- database passwordSEARCH_SESSION_SECRET- random 32+ char secret (openssl rand -hex 32)SEARCH_BOOTSTRAP_ADMIN_EMAIL+SEARCH_BOOTSTRAP_ADMIN_PASSWORD- initial admin login
-
Start services
From the repo root:
docker compose up --build
-
Default endpoints
- Admin UI:
http://localhost:3020(search, claims, import, stats) - Health:
GET http://localhost:3020/health - REST API (served by Nuxt Nitro, backed by
@search/core):/api/v1/search,/api/v1/claims,/api/v1/import,/api/v1/stats,/api/v1/categories,/api/v1/rating-labels(requires login orAuthorization: Bearer <key>) - MCP endpoint:
POST http://localhost:3020/mcp(HTTP/SSE, requires Bearer key withmcp:usepermission)
For full request/response shapes, environment variables, and internal search design, see the package READMEs (core/README.md, frontend/README.md, mcp/README.md).
-
Install dependencies (from repo root):
bun install
-
Type-check all packages:
bun run check
-
Run Nuxt dev server only (without Docker, PostgreSQL must be reachable):
cd frontend bun run devBy default this listens on
SEARCH_PORT(or3020).
graph TB
subgraph clients [Clients]
LibreChat["LibreChat (MCP)"]
AdminUI["Admin UI (Nuxt 4)"]
ExtAPI["External REST clients"]
end
subgraph service [Search]
Nuxt["Nuxt 4 Nitro server<br/>(/api, /mcp, /health)"]
Core["@search/core<br/>(DB, chunking, embeddings, search, import)"]
Mcp["@search/mcp<br/>MCP tools (search_factchecks, get_factcheck, list_categories)"]
end
subgraph storage [Storage]
PG["PostgreSQL + pgvector"]
end
AdminUI -->|"HTTP"| Nuxt
ExtAPI -->|"REST /api/v1/**"| Nuxt
LibreChat -->|"/mcp (MCP HTTP/SSE)"| Nuxt
Nuxt --> Core
Nuxt --> Mcp
Core --> PG
The previous standalone backend code was consolidated into the core, frontend, and mcp packages. All HTTP traffic now terminates at the Nuxt Nitro server, which delegates to @search/core for data access and search, and to @search/mcp for MCP sessions and tools.