NLQueries

# nlqueries-core [![CI](https://github.com/nlqueries/nlqueries/actions/workflows/ci.yml/badge.svg)](https://github.com/nlqueries/nlqueries/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/nlqueries-core)](https://pypi.org/project/nlqueries-core/) [![Python](https://img.shields.io/pypi/pyversions/nlqueries-core)](https://pypi.org/project/nlqueries-core/) [![License: BSL 1.1](https://img.shields.io/badge/license-BSL%201.1-blue)](LICENSE) [![Visitors](https://visitor-badge.laobi.icu/badge?page_id=nlqueries.nlqueries)](https://github.com/nlqueries/nlqueries) **NLQueries Core** is an open-source natural language to SQL engine — see [nlqueries.com](https://nlqueries.com). It turns plain-English questions into validated SQL, builds a YAML knowledge base from your schema and query history (rebuilt whenever you re-run `export-kb`), and exposes everything as an MCP server your AI assistant can call directly. It also answers questions from your documents (PDF, Word, Excel, Markdown, plain text, Notion, Confluence), with citations. ## Links - **Website** — [nlqueries.com](https://nlqueries.com) - **Documentation** — [nlqueries.com/docs/](https://nlqueries.com/docs/) - **Getting started** — [nlqueries.com/docs/getting-started](https://nlqueries.com/docs/getting-started) - **Supported databases** — [nlqueries.com/databases/](https://nlqueries.com/databases/) - **PyPI** — [nlqueries-core](https://pypi.org/project/nlqueries-core/) - **Docker Hub** — [nlqueries/core](https://hub.docker.com/r/nlqueries/core) --- ## Features | Capability | Description | |---|---| | **Database connectors** | PostgreSQL, Snowflake, BigQuery, Redshift, SQL Server / Azure SQL, DuckDB, SQLite — plus a generic SQLAlchemy connector, driven by a connection URL, for MySQL (`connect mysql`) and any other SQLAlchemy-reachable database | | **Document connectors** | PDF, Word, Excel, Markdown, plain text, Notion, Confluence — ask questions over ingested documents with citations | | **Query pipeline** | Filter, cluster, and parameterize query history into reusable `QueryCapsule` templates | | **Knowledge base** | Auto-generated YAML schema + capsule file, with coverage reporting via `kb-stats` | | **Document Q&A** | `doc-ingest` (or `doc-sync-notion` / `doc-sync-confluence`) chunks, embeds and stores a source in Qdrant; `doc-ask` answers from it with citations | | **Conversational follow-ups** | Carries context across questions so a follow-up like "and by region?" resolves against the previous query — on by default in `nlqueries query`, reset with `--new-session` | | **Semantic cache** | Recognises a question `query` or the MCP `query` tool has answered before, by meaning, and skips the LLM: it replays the stored answer and runs the stored SQL again so the rows are current (not with `--no-execute`). `ask` does not use it. Needs Qdrant | | **Embedding daemon** | Keeps the embedding model resident in memory — ~10 ms per call instead of ~9 s | | **Feedback loop** | Rate an answer with `feedback`, review with `feedback-stats`, and `promote-feedback` the thumbs-up ones — their SQL is re-validated against the current schema and blended into later prompts as verified examples | | **Regression checks** | `eval` re-asks the agent's own mined capsules — and a golden question set too, with `--golden` — then checks the generated SQL parses and references only tables the agent knows | | **dbt import** | `import-dbt` merges dbt model and column descriptions into the knowledge base | | **LLM client** | Anthropic, OpenAI, Amazon Bedrock, or any LiteLLM-supported provider | | **MCP server** | Query execution and schema/knowledge lookup exposed as MCP tools for Claude, Cursor, etc. | | **CLI** | `nlqueries` (or the shorter `nlq` alias) — connect, build, query, and inspect from your terminal | See [docs/architecture.md](docs/architecture.md) (or [read online](https://nlqueries.com/docs/architecture)) for how these pieces fit together. --- ## Quickstart **Prerequisite:** Python 3.11–3.14. ### Option A — Docker (recommended) Pulls the published [`nlqueries/core`](https://hub.docker.com/r/nlqueries/core) image from Docker Hub — no clone required, just the compose file: ```bash curl -O https://raw.githubusercontent.com/nlqueries/nlqueries/main/docker-compose.yml ``` Create a `.env` file next to it with one LLM key, a Qdrant key and an MCP token. All three are required — compose refuses to start without `QDRANT_API_KEY` or `NLQ_MCP_STATIC_TOKEN`: ```bash ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY=sk-... QDRANT_API_KEY=... # any random secret: openssl rand -hex 32 NLQ_MCP_STATIC_TOKEN=... # another one: openssl rand -hex 32 ``` The MCP server is reachable over the network, so it requires that token: an MCP client connects to `http://localhost:8080/sse` and sends `Authorization: Bearer `. The token has full access. To give different people different access, see [docs/mcp-authentication.md](docs/mcp-authentication.md). Then start the stack: ```bash docker compose up ``` This pulls `nlqueries/core:0.3.0` and starts it alongside Qdrant (`:6333`), with the MCP server on `:8080`. Run CLI commands against the running stack from a second terminal: ```bash docker exec -it nlqueries-core nlqueries health ``` The image includes the PostgreSQL, SQLite, Snowflake, BigQuery and DuckDB drivers. It does not include the MySQL, Redshift or SQL Server drivers, or the `docs` and `wiki` extras (PDF / Word / Excel ingestion, Notion / Confluence sync); for those, install with pip (Option B) and add the extra. ### Option B — pip install ```bash pip install nlqueries-core export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY nlqueries health ``` Optional extras for specific connectors: ```bash pip install "nlqueries-core[mysql]" # MySQL (driver for the generic connector) pip install "nlqueries-core[snowflake]" # Snowflake pip install "nlqueries-core[bigquery]" # Google BigQuery pip install "nlqueries-core[redshift]" # Amazon Redshift pip install "nlqueries-core[mssql]" # SQL Server / Azure SQL pip install "nlqueries-core[duckdb]" # DuckDB pip install "nlqueries-core[docs]" # PDF / Word / Excel ingestion pip install "nlqueries-core[wiki]" # Notion / Confluence sync ``` PostgreSQL and SQLite need no extra. The generic `sqlalchemy` connector needs whichever driver its URL names. ### Option C — Clone and install from source No Docker required — for contributing, or to run against unreleased changes: ```bash git clone https://github.com/nlqueries/nlqueries.git cd nlqueries python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1 pip install -e ".[dev]" export ANTHROPIC_API_KEY=sk-ant-... # or OPENAI_API_KEY nlqueries health ``` See [CONTRIBUTING.md](CONTRIBUTING.md#development-setup) for linting and test commands. ### First query ```bash nlqueries connect postgres --host localhost --database mydb --user alice --password secret --alias dev nlqueries process-history dev --days 30 --annotate nlqueries export-kb dev nlqueries query dev "How many orders shipped last month?" nlqueries query dev "and how many were returned?" # follow-up — keeps prior context ``` Follow-up context is on by default; pass `--new-session` to start fresh or `--no-session` to disable it for a one-off question. Full walkthrough: [docs/getting-started.md](docs/getting-started.md) (or [read online](https://nlqueries.com/docs/getting-started)). --- ## Documentation | Doc | Covers | |---|---| | [docs/getting-started.md](docs/getting-started.md) (or [read online](https://nlqueries.com/docs/getting-started)) | Step-by-step setup and your first query | | [docs/cli-reference.md](docs/cli-reference.md) (or [read online](https://nlqueries.com/docs/cli-reference)) | Every command and flag | | [docs/connectors.md](docs/connectors.md) (or [read online](https://nlqueries.com/docs/connectors)) | Database and document connector setup, per-connector notes and caveats | | [docs/configuration.md](docs/configuration.md) (or [read online](https://nlqueries.com/docs/configuration)) | Environment variables | | [docs/troubleshooting.md](docs/troubleshooting.md) (or [read online](https://nlqueries.com/docs/troubleshooting)) | Common warnings and errors explained | | [docs/qdrant-setup.md](docs/qdrant-setup.md) (or [read online](https://nlqueries.com/docs/qdrant-setup)) | Setting up Qdrant (required for embeddings, semantic cache, document search) | | [docs/mcp-authentication.md](docs/mcp-authentication.md) (or [read online](https://nlqueries.com/docs/mcp-authentication)) | Authenticating the MCP server — required to serve it over a network | | [docs/architecture.md](docs/architecture.md) (or [read online](https://nlqueries.com/docs/architecture)) | Module layout and request flow | | [docs/database-hardening.md](docs/database-hardening.md) (or [read online](https://nlqueries.com/docs/database-hardening)) | The read-only role to grant per engine, and exactly what each connector does and does not enforce | | [docs/dependency-locking.md](docs/dependency-locking.md) (or [read online](https://nlqueries.com/docs/dependency-locking)) | The hashed lock file the image builds from, the digest-pinned base image, and how to regenerate both | | [docs/contributing.md](docs/contributing.md) (or [read online](https://nlqueries.com/docs/contributing)) | What a new connector has to implement, and what to open an issue about first | --- ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). All contributors must sign the CLA before a PR can be merged — see [CONTRIBUTOR_LICENSE_AGREEMENT.md](CONTRIBUTOR_LICENSE_AGREEMENT.md). --- ## License [Business Source License 1.1](LICENSE) — converting to Apache 2.0 no later than **June 4, 2030**. The licence sets that date and also converts each version on the fourth anniversary of its own first publication, whichever comes first, so a version first published before June 4, 2026 converts on its own anniversary, ahead of the fixed date. Until then the licence grants production use, including commercially and self-hosted, with one carve-out: you may not offer NLQueries Core to third parties as a hosted or managed service. Individual and non-commercial self-hosted deployments are unrestricted. [LICENSE](LICENSE) is the authority; this paragraph is a summary.