knowledge-rag 3.9.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +382 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
### Your docs, your machine, zero cloud. Claude Code searches them natively.
|
|
18
18
|
|
|
19
19
|
Drop your PDFs, markdown, code, notebooks — **1800+ files, 39K chunks, indexed in under 3 minutes.**<br/>
|
|
20
|
-
Hybrid search (BM25 + semantic vectors + cross-encoder reranking) through
|
|
20
|
+
Hybrid search (BM25 + semantic vectors + cross-encoder reranking) through 13 MCP tools.<br/>
|
|
21
21
|
Everything runs locally via ONNX. No Docker, no Ollama, no API keys, no data leaves your machine.
|
|
22
22
|
|
|
23
23
|
```
|
|
@@ -26,19 +26,68 @@ pip install knowledge-rag → restart Claude Code → search_knowledge("your que
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
**
|
|
29
|
+
**13 MCP Tools** | **Hybrid Search + Reranking** | **20 File Formats** | **Optional NVIDIA GPU** | **100% Local**
|
|
30
30
|
|
|
31
|
-
[What's New](#whats-new-in-
|
|
31
|
+
[What's New](#whats-new-in-v420) | [Supported Formats](#supported-formats) | [Installation](#installation) | [Configuration](#configuration) | [API Reference](#api-reference) | [Architecture](#architecture)
|
|
32
32
|
|
|
33
33
|
</div>
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## Star History
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
|
|
41
|
+
<a href="https://www.star-history.com/?repos=lyonzin%2Fknowledge-rag&type=date&legend=top-left">
|
|
42
|
+
<picture>
|
|
43
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=lyonzin/knowledge-rag&type=date&theme=dark&legend=top-left" />
|
|
44
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=lyonzin/knowledge-rag&type=date&legend=top-left" />
|
|
45
|
+
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=lyonzin/knowledge-rag&type=date&legend=top-left" />
|
|
46
|
+
</picture>
|
|
47
|
+
</a>
|
|
48
|
+
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## What's New in v4.2.0
|
|
54
|
+
|
|
55
|
+
### Search Performance & Output Quality (v4.2.0)
|
|
56
|
+
|
|
57
|
+
**128× faster BM25 search** — replaced `rank-bm25` full-corpus scan with a custom **inverted-index** implementation. Only documents containing query terms are scored, using `numpy.argpartition` for O(n) top-k selection. Adjacent chunk fetching now uses a single batched ChromaDB call instead of N round-trips, and an O(1) reverse lookup (`_source_to_docid`) eliminates linear scans.
|
|
58
|
+
|
|
59
|
+
**Smarter output** — two new parameters on `search_knowledge`:
|
|
60
|
+
- **`snippet_mode`** (default: `true`) — truncates content to ~500 characters at natural break points, reducing token consumption by ~72%. Adds `content_length` field with original size; use `get_document()` for full content.
|
|
61
|
+
- **`min_score`** — filters results below a normalized relevance threshold (0.0–1.0). Eliminates low-quality noise from results. Response includes `filtered_by_score` count for transparency.
|
|
62
|
+
|
|
63
|
+
Both parameters are fully backwards-compatible (existing callers see no change in behavior).
|
|
64
|
+
|
|
65
|
+
### Enterprise Concurrent Access — SSE/HTTP Transport (v4.0.0)
|
|
66
|
+
|
|
67
|
+
The server now supports **SSE** and **streamable-http** transport modes. Instead of spawning a separate process per client (stdio), a single server process serves all clients with shared resources — 1 embedding model, 1 ChromaDB, 1 query cache.
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
# config.yaml
|
|
71
|
+
server:
|
|
72
|
+
transport: "sse" # "stdio" | "sse" | "streamable-http"
|
|
73
|
+
host: "127.0.0.1"
|
|
74
|
+
port: 8179
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or via CLI: `knowledge-rag --transport sse`
|
|
78
|
+
|
|
79
|
+
**Optional enterprise features** (all disabled by default):
|
|
80
|
+
- **Rate limiting**: Sliding-window counter, configurable RPM and burst
|
|
81
|
+
- **Prometheus metrics**: `/metrics` endpoint on separate port
|
|
82
|
+
- **Bearer auth**: Token validation for SSE/HTTP connections
|
|
83
|
+
|
|
84
|
+
All 13 MCP tools are instrumented with `@rate_limited` and `@instrument` decorators — zero overhead when features are disabled. Default transport remains **stdio** for full backwards compatibility.
|
|
85
|
+
|
|
86
|
+
> **Migration**: Existing users need zero changes. SSE mode is opt-in via `server.transport: "sse"` in config.yaml. See [Configuration](#configuration) for details.
|
|
38
87
|
|
|
39
88
|
### Quality Gate — 7-Pillar PR Validation
|
|
40
89
|
|
|
41
|
-
|
|
90
|
+
Every PR (including dependabot bumps and one-line fixes) is now evaluated against **35+ automated checks** spread across 7 pillars before any human review:
|
|
42
91
|
|
|
43
92
|
| Pillar | What it enforces | Tools |
|
|
44
93
|
|---|---|---|
|
|
@@ -86,6 +135,7 @@ All methods produce the same MCP server. See [Installation](#installation) for f
|
|
|
86
135
|
|
|
87
136
|
### Recent Highlights
|
|
88
137
|
|
|
138
|
+
- **v4.0.0** — **Enterprise concurrent access**: SSE/HTTP transport (1 server → N clients), thread-safe shared state, optional rate limiting + Prometheus metrics, ChromaDB WAL mode, `--transport` CLI
|
|
89
139
|
- **v3.9.0** — **Quality Gate** activated: 35+ automated PR checks across 7 pillars (Security, Stability, Memory Leak, Versatility, Scalability, Versioning, Quality) + nightly resilience suite (chaos, soak, determinism, mutation)
|
|
90
140
|
- **v3.8.1** — Critical hotfix: loud-fail embeddings (no more silent zero-vector corruption); Windows CI flake erradicated (HF_HUB_OFFLINE + shell:bash + atexit wrapper)
|
|
91
141
|
- **v3.8.0** — Lazy-load embeddings, opt-in single-instance guard, version sync across PyPI/NPM/Docker
|
|
@@ -155,7 +205,7 @@ See [Changelog](#changelog) for full history.
|
|
|
155
205
|
| **MMR Diversification** | Maximal Marginal Relevance reduces redundant results |
|
|
156
206
|
| **Persistent Model Cache** | Embedding models cached in `models_cache/` — survives reboots |
|
|
157
207
|
| **Auto-Migration** | Detects embedding dimension mismatch and rebuilds automatically |
|
|
158
|
-
| **
|
|
208
|
+
| **13 MCP Tools** | Full CRUD + search + evaluation via Claude Code |
|
|
159
209
|
|
|
160
210
|
---
|
|
161
211
|
|
|
@@ -167,14 +217,14 @@ See [Changelog](#changelog) for full history.
|
|
|
167
217
|
flowchart TB
|
|
168
218
|
subgraph MCP["MCP SERVER (FastMCP)"]
|
|
169
219
|
direction TB
|
|
170
|
-
TOOLS["
|
|
220
|
+
TOOLS["13 MCP Tools<br/>search | get | add | update | remove<br/>reindex | reindex_status | list | stats | url | similar | evaluate"]
|
|
171
221
|
end
|
|
172
222
|
|
|
173
223
|
subgraph SEARCH["HYBRID SEARCH ENGINE"]
|
|
174
224
|
direction LR
|
|
175
225
|
ROUTER["Keyword Router<br/>(word boundaries)"]
|
|
176
226
|
SEMANTIC["Semantic Search<br/>(ChromaDB)"]
|
|
177
|
-
BM25["BM25 Keyword<br/>(
|
|
227
|
+
BM25["BM25 Keyword<br/>(inverted-index + expansion)"]
|
|
178
228
|
RRF["Reciprocal Rank<br/>Fusion (RRF)"]
|
|
179
229
|
RERANK["Cross-Encoder<br/>Reranker"]
|
|
180
230
|
|
|
@@ -238,15 +288,23 @@ flowchart TB
|
|
|
238
288
|
subgraph HYBRID["Hybrid Search"]
|
|
239
289
|
direction LR
|
|
240
290
|
SEMANTIC["Semantic Search<br/>(ChromaDB embeddings)<br/>Conceptual similarity"]
|
|
241
|
-
BM25["BM25
|
|
291
|
+
BM25["BM25 Inverted-Index<br/>(posting lists + numpy top-k)<br/>Exact term matching"]
|
|
242
292
|
end
|
|
243
293
|
|
|
244
294
|
subgraph FUSION["Result Fusion + Reranking"]
|
|
245
295
|
RRF["Reciprocal Rank Fusion<br/>score = alpha * 1/(k+rank_sem)<br/>+ (1-alpha) * 1/(k+rank_bm25)"]
|
|
246
296
|
RERANK["Cross-Encoder Reranker<br/>Re-scores top 3x candidates<br/>query+doc pair scoring"]
|
|
247
297
|
SORT["Sort by Reranker Score<br/>Normalize to 0-1"]
|
|
298
|
+
ADJ["Adjacent Chunk Expansion<br/>(batch fetch ±1 chunk)"]
|
|
299
|
+
|
|
300
|
+
RRF --> RERANK --> SORT --> ADJ
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
subgraph OUTPUT["Output Processing"]
|
|
304
|
+
MINSCORE["min_score Filter<br/>(discard below threshold)"]
|
|
305
|
+
SNIPPET["snippet_mode Truncation<br/>(~500 chars at natural break)"]
|
|
248
306
|
|
|
249
|
-
|
|
307
|
+
MINSCORE --> SNIPPET
|
|
250
308
|
end
|
|
251
309
|
|
|
252
310
|
CATEGORY --> HYBRID
|
|
@@ -254,7 +312,8 @@ flowchart TB
|
|
|
254
312
|
SEMANTIC --> RRF
|
|
255
313
|
BM25 --> RRF
|
|
256
314
|
|
|
257
|
-
|
|
315
|
+
ADJ --> MINSCORE
|
|
316
|
+
SNIPPET --> RESULTS["Results<br/>search_method: hybrid|semantic|keyword<br/>score + filtered_by_score + content_length"]
|
|
258
317
|
```
|
|
259
318
|
|
|
260
319
|
### Document Ingestion Flow
|
|
@@ -331,8 +390,55 @@ flowchart LR
|
|
|
331
390
|
|
|
332
391
|
- Python 3.11+
|
|
333
392
|
- Claude Code CLI
|
|
393
|
+
- *…or any other MCP client (Claude Desktop, Cursor, VS Code, Antigravity, opencode, Windsurf) — see [Use with other MCP clients](#use-with-other-mcp-clients)*
|
|
334
394
|
- ~200MB disk for model cache (auto-downloaded on first run)
|
|
335
|
-
- *Optional:* NVIDIA GPU + CUDA for accelerated embeddings (
|
|
395
|
+
- *Optional:* NVIDIA GPU + CUDA 12 for accelerated embeddings (see [GPU Acceleration](#gpu-acceleration) below)
|
|
396
|
+
|
|
397
|
+
### GPU Acceleration
|
|
398
|
+
|
|
399
|
+
GPU mode accelerates embedding generation during indexing and search. It requires an NVIDIA GPU with CUDA 12 support. No GPU? No problem — the server runs on CPU by default and GPU is entirely optional.
|
|
400
|
+
|
|
401
|
+
**Requirements:**
|
|
402
|
+
|
|
403
|
+
| Component | Minimum | How to check / get it |
|
|
404
|
+
|-----------|---------|----------------------|
|
|
405
|
+
| NVIDIA GPU (Turing+) | RTX 20xx / 30xx / 40xx / 50xx, or Tesla T4+ | `nvidia-smi` |
|
|
406
|
+
| NVIDIA Driver | ≥ 525 | `nvidia-smi` — [nvidia.com/drivers](https://www.nvidia.com/drivers) |
|
|
407
|
+
| CUDA 12 runtime | Provided by pip packages below | Automatic |
|
|
408
|
+
|
|
409
|
+
**Setup (2 steps):**
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
# 1. Install GPU dependencies (onnxruntime-gpu + all CUDA 12 runtime DLLs)
|
|
413
|
+
pip install knowledge-rag[gpu]
|
|
414
|
+
|
|
415
|
+
# 2. Enable in config.yaml
|
|
416
|
+
# models:
|
|
417
|
+
# embedding:
|
|
418
|
+
# gpu: true
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
The `[gpu]` extra installs `onnxruntime-gpu` plus 7 NVIDIA CUDA 12 packages (`cublas`, `cudnn`, `cuda-runtime`, `cufft`, `cusparse`, `cusolver`, `curand`, `nvjitlink`) so you don't need a full CUDA Toolkit install.
|
|
422
|
+
|
|
423
|
+
**Verify GPU is active:**
|
|
424
|
+
|
|
425
|
+
On server startup, look for the GPU status banner:
|
|
426
|
+
```
|
|
427
|
+
============================================================
|
|
428
|
+
GPU STATUS: ACTIVE
|
|
429
|
+
Provider: CUDAExecutionProvider
|
|
430
|
+
Device: NVIDIA GeForce RTX 3080 Ti
|
|
431
|
+
VRAM: 12.0 GB
|
|
432
|
+
============================================================
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Or programmatically:
|
|
436
|
+
```bash
|
|
437
|
+
python -c "import onnxruntime; print(onnxruntime.get_available_providers())"
|
|
438
|
+
# Should include: 'CUDAExecutionProvider'
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
> **Fallback**: If CUDA is unavailable at runtime (wrong driver, missing DLLs, no GPU), the server falls back to CPU automatically with a `[WARN]` log — it never crashes. The `gpu: true` config is a preference, not a requirement.
|
|
336
442
|
|
|
337
443
|
### Install Methods
|
|
338
444
|
|
|
@@ -446,6 +552,94 @@ Add to `~/.claude.json`:
|
|
|
446
552
|
> Replace `YOUR_USER` with your username, or use the full path from `echo $HOME`.
|
|
447
553
|
</details>
|
|
448
554
|
|
|
555
|
+
#### Option F: SSE Server Mode (multi-agent)
|
|
556
|
+
|
|
557
|
+
For multi-agent setups where multiple clients query the same knowledge base simultaneously:
|
|
558
|
+
|
|
559
|
+
```bash
|
|
560
|
+
pip install knowledge-rag[server] # Adds uvicorn for SSE/HTTP
|
|
561
|
+
knowledge-rag --transport sse # Starts on http://127.0.0.1:8179
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
Then configure each MCP client to connect via SSE:
|
|
565
|
+
|
|
566
|
+
```json
|
|
567
|
+
{
|
|
568
|
+
"mcpServers": {
|
|
569
|
+
"knowledge-rag": {
|
|
570
|
+
"type": "sse",
|
|
571
|
+
"url": "http://127.0.0.1:8179/sse"
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
One server process serves all agents — shared embedding model, shared cache, shared ChromaDB. See [Configuration > Server](#server) for rate limiting, metrics, and auth options.
|
|
578
|
+
|
|
579
|
+
### Use with other MCP clients
|
|
580
|
+
|
|
581
|
+
`knowledge-rag` supports both **stdio** (default, 1:1) and **SSE** (1:N) transport modes. In stdio mode, it works with any MCP-compatible client, not only Claude Code. The launch command is the same everywhere (the `python -m mcp_server.server` from whichever install method you picked); only the **config file location** and **JSON shape** differ per client.
|
|
582
|
+
|
|
583
|
+
#### Clients using the standard `mcpServers` format
|
|
584
|
+
|
|
585
|
+
For **Claude Desktop, Cursor, Antigravity, and Windsurf**, use the same block — only the file location changes:
|
|
586
|
+
|
|
587
|
+
```json
|
|
588
|
+
{
|
|
589
|
+
"mcpServers": {
|
|
590
|
+
"knowledge-rag": {
|
|
591
|
+
"command": "/home/YOUR_USER/knowledge-rag/venv/bin/python",
|
|
592
|
+
"args": ["-m", "mcp_server.server"]
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
> **Windows**: set `command` to the full path of `venv\Scripts\python.exe`.
|
|
599
|
+
|
|
600
|
+
| Client | Config file | Notes |
|
|
601
|
+
|---|---|---|
|
|
602
|
+
| **Claude Code** | use `claude mcp add …` (see install methods above) | The CLI writes `~/.claude.json` for you — manual edits to it aren't reliably picked up. |
|
|
603
|
+
| **Claude Desktop** | macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` · Windows: `%APPDATA%\Claude\claude_desktop_config.json` | Easiest: **Settings → Developer → Edit Config** opens the correct file (avoids the Windows Store/MSIX path quirk). |
|
|
604
|
+
| **Cursor** | `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project) | — |
|
|
605
|
+
| **Antigravity** | macOS/Linux: `~/.gemini/antigravity/mcp_config.json` · Windows: `%USERPROFILE%\.gemini\antigravity\mcp_config.json` | Open via Agent panel → **"…" → Manage MCP Servers → View raw config**. |
|
|
606
|
+
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json` (global only) | Easiest: Cascade panel → MCP → **View raw config**. |
|
|
607
|
+
|
|
608
|
+
#### VS Code — uses a `servers` key
|
|
609
|
+
|
|
610
|
+
VS Code (Copilot MCP) nests servers under **`servers`**, not `mcpServers`. Put this in `.vscode/mcp.json` (workspace) or the file opened by the **MCP: Open User Configuration** command:
|
|
611
|
+
|
|
612
|
+
```json
|
|
613
|
+
{
|
|
614
|
+
"servers": {
|
|
615
|
+
"knowledge-rag": {
|
|
616
|
+
"type": "stdio",
|
|
617
|
+
"command": "/home/YOUR_USER/knowledge-rag/venv/bin/python",
|
|
618
|
+
"args": ["-m", "mcp_server.server"]
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
#### opencode — uses an `mcp` key
|
|
625
|
+
|
|
626
|
+
opencode nests servers under **`mcp`**, takes `command` as a single **array**, and uses `environment` instead of `env`. Put this in `opencode.json` (project root) or `~/.config/opencode/opencode.json` (global):
|
|
627
|
+
|
|
628
|
+
```jsonc
|
|
629
|
+
{
|
|
630
|
+
"$schema": "https://opencode.ai/config.json",
|
|
631
|
+
"mcp": {
|
|
632
|
+
"knowledge-rag": {
|
|
633
|
+
"type": "local",
|
|
634
|
+
"command": ["/home/YOUR_USER/knowledge-rag/venv/bin/python", "-m", "mcp_server.server"],
|
|
635
|
+
"enabled": true
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
> **Any other MCP client**: point it at the same command + args (`…/venv/bin/python -m mcp_server.server`). If it speaks stdio MCP, knowledge-rag works — only the config file's location and key naming differ. Check your client's docs for the exact path.
|
|
642
|
+
|
|
449
643
|
### Verify
|
|
450
644
|
|
|
451
645
|
```bash
|
|
@@ -515,7 +709,7 @@ search_knowledge("lateral movement strategies", hybrid_alpha=1.0)
|
|
|
515
709
|
|
|
516
710
|
### Indexing
|
|
517
711
|
|
|
518
|
-
Documents are automatically indexed on first startup.
|
|
712
|
+
Documents are automatically indexed on first startup. All reindex operations run **in background** — they return immediately and you poll progress via `get_reindex_status()`:
|
|
519
713
|
|
|
520
714
|
```python
|
|
521
715
|
# Incremental: only re-index changed files (fast)
|
|
@@ -526,6 +720,10 @@ reindex_documents(force=True)
|
|
|
526
720
|
|
|
527
721
|
# Nuclear rebuild: delete everything, re-embed all (use after model change)
|
|
528
722
|
reindex_documents(full_rebuild=True)
|
|
723
|
+
|
|
724
|
+
# Poll progress (lightweight, no full stats computation)
|
|
725
|
+
get_reindex_status()
|
|
726
|
+
# → {"reindex": {"active": true, "percent": 56, "progress": "2090/3734", ...}}
|
|
529
727
|
```
|
|
530
728
|
|
|
531
729
|
### Evaluating Retrieval Quality
|
|
@@ -554,6 +752,8 @@ Hybrid search combining semantic search + BM25 keyword search with cross-encoder
|
|
|
554
752
|
| `max_results` | int | 5 | Maximum results to return (1-20) |
|
|
555
753
|
| `category` | string | null | Filter by category |
|
|
556
754
|
| `hybrid_alpha` | float | 0.3 | Balance: 0.0 = keyword only, 1.0 = semantic only |
|
|
755
|
+
| `min_score` | float | 0.0 | Minimum relevance score (0.0-1.0) to include a result. Use 0.2-0.4 to cut noise |
|
|
756
|
+
| `snippet_mode` | bool | true | Truncate content to ~500 chars at natural break points. Adds `content_length` field |
|
|
557
757
|
|
|
558
758
|
**Returns:**
|
|
559
759
|
|
|
@@ -563,6 +763,7 @@ Hybrid search combining semantic search + BM25 keyword search with cross-encoder
|
|
|
563
763
|
"query": "mimikatz credential dump",
|
|
564
764
|
"hybrid_alpha": 0.5,
|
|
565
765
|
"result_count": 3,
|
|
766
|
+
"filtered_by_score": 2,
|
|
566
767
|
"cache_hit_rate": "0.0%",
|
|
567
768
|
"results": [
|
|
568
769
|
{
|
|
@@ -604,14 +805,39 @@ Retrieve the full content of a specific document.
|
|
|
604
805
|
|
|
605
806
|
#### `reindex_documents`
|
|
606
807
|
|
|
607
|
-
Index or reindex all documents in the knowledge base.
|
|
808
|
+
Index or reindex all documents in the knowledge base. **Runs in background** — returns immediately. Poll progress via `get_reindex_status()`.
|
|
608
809
|
|
|
609
810
|
| Parameter | Type | Default | Description |
|
|
610
811
|
|-----------|------|---------|-------------|
|
|
611
812
|
| `force` | bool | false | Smart reindex: detects changes, rebuilds BM25. Fast. |
|
|
612
813
|
| `full_rebuild` | bool | false | Nuclear rebuild: deletes everything, re-embeds all documents. Use after model change. |
|
|
613
814
|
|
|
614
|
-
**Returns:**
|
|
815
|
+
**Returns:** `{"status": "started", "operation": "..."}` immediately. If already running, returns `{"status": "already_running", "progress": "1200/3734"}`.
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
#### `get_reindex_status`
|
|
820
|
+
|
|
821
|
+
Get the current status of a background reindex operation. Lightweight — does not compute full index statistics.
|
|
822
|
+
|
|
823
|
+
**Returns (active):**
|
|
824
|
+
```json
|
|
825
|
+
{
|
|
826
|
+
"status": "success",
|
|
827
|
+
"reindex": {
|
|
828
|
+
"active": true,
|
|
829
|
+
"operation": "nuclear_rebuild",
|
|
830
|
+
"progress": "1200/3734",
|
|
831
|
+
"percent": 32,
|
|
832
|
+
"indexed": 1200,
|
|
833
|
+
"skipped": 0,
|
|
834
|
+
"errors": 0,
|
|
835
|
+
"started_at": "2026-06-17T18:29:49"
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
**Returns (idle):** `{"status": "success", "reindex": {"active": false}}`
|
|
615
841
|
|
|
616
842
|
---
|
|
617
843
|
|
|
@@ -660,7 +886,6 @@ Get statistics about the knowledge base index.
|
|
|
660
886
|
"stats": {
|
|
661
887
|
"total_documents": 75,
|
|
662
888
|
"total_chunks": 9256,
|
|
663
|
-
"unique_content_hashes": 9100,
|
|
664
889
|
"categories": {"security": 52, "development": 8},
|
|
665
890
|
"supported_formats": [".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv", ".ipynb"],
|
|
666
891
|
"embedding_model": "BAAI/bge-small-en-v1.5",
|
|
@@ -842,6 +1067,21 @@ query_expansions:
|
|
|
842
1067
|
privesc:
|
|
843
1068
|
- privilege escalation
|
|
844
1069
|
- privesc
|
|
1070
|
+
|
|
1071
|
+
# Server — enterprise features (new in v4.0.0)
|
|
1072
|
+
server:
|
|
1073
|
+
transport: "stdio" # "stdio" | "sse" | "streamable-http"
|
|
1074
|
+
host: "127.0.0.1" # Bind address (SSE/HTTP only)
|
|
1075
|
+
port: 8179 # Bind port (SSE/HTTP only)
|
|
1076
|
+
auth:
|
|
1077
|
+
bearer_token: "" # Set a secret to enable auth (SSE/HTTP only)
|
|
1078
|
+
rate_limit:
|
|
1079
|
+
enabled: false
|
|
1080
|
+
requests_per_minute: 60
|
|
1081
|
+
burst: 10
|
|
1082
|
+
metrics:
|
|
1083
|
+
enabled: false
|
|
1084
|
+
port: 9179 # Separate port for Prometheus scraping
|
|
845
1085
|
```
|
|
846
1086
|
|
|
847
1087
|
> See `config.example.yaml` for the fully documented template with explanations for every field.
|
|
@@ -861,6 +1101,22 @@ Pre-built configurations for common use cases:
|
|
|
861
1101
|
|
|
862
1102
|
### Configuration Reference
|
|
863
1103
|
|
|
1104
|
+
#### Server
|
|
1105
|
+
|
|
1106
|
+
| Field | Default | Description |
|
|
1107
|
+
|-------|---------|-------------|
|
|
1108
|
+
| `server.transport` | `"stdio"` | Transport protocol: `"stdio"`, `"sse"`, or `"streamable-http"` |
|
|
1109
|
+
| `server.host` | `"127.0.0.1"` | Bind address for SSE/HTTP mode |
|
|
1110
|
+
| `server.port` | `8179` | Bind port for SSE/HTTP mode |
|
|
1111
|
+
| `server.auth.bearer_token` | `""` (disabled) | Bearer token for SSE/HTTP auth. Empty = no auth |
|
|
1112
|
+
| `server.rate_limit.enabled` | `false` | Enable per-client rate limiting |
|
|
1113
|
+
| `server.rate_limit.requests_per_minute` | `60` | Max requests per minute |
|
|
1114
|
+
| `server.rate_limit.burst` | `10` | Burst allowance above steady rate |
|
|
1115
|
+
| `server.metrics.enabled` | `false` | Enable Prometheus `/metrics` endpoint |
|
|
1116
|
+
| `server.metrics.port` | `9179` | Port for metrics scraping |
|
|
1117
|
+
|
|
1118
|
+
In stdio mode (default), server settings are ignored. SSE/HTTP mode auto-enables the single-instance lock.
|
|
1119
|
+
|
|
864
1120
|
#### Paths
|
|
865
1121
|
|
|
866
1122
|
| Field | Default | Description |
|
|
@@ -890,7 +1146,7 @@ For `.md` files, chunking splits at `##` and `###` header boundaries first. Sect
|
|
|
890
1146
|
|-------|---------|-------------|
|
|
891
1147
|
| `models.embedding.model` | `BAAI/bge-small-en-v1.5` | Embedding model (ONNX, runs locally) |
|
|
892
1148
|
| `models.embedding.dimensions` | 384 | Vector dimensions (must match model) |
|
|
893
|
-
| `models.embedding.gpu` | false | Enable CUDA GPU acceleration.
|
|
1149
|
+
| `models.embedding.gpu` | false | Enable CUDA GPU acceleration. See [GPU Acceleration](#gpu-acceleration) for full setup |
|
|
894
1150
|
| `models.reranker.enabled` | true | Enable cross-encoder reranking |
|
|
895
1151
|
| `models.reranker.model` | `Xenova/ms-marco-MiniLM-L-6-v2` | Reranker model |
|
|
896
1152
|
| `models.reranker.top_k_multiplier` | 3 | Fetch N*multiplier candidates for reranking |
|
|
@@ -957,6 +1213,22 @@ query_expansions:
|
|
|
957
1213
|
|
|
958
1214
|
Set `query_expansions: {}` for no expansion.
|
|
959
1215
|
|
|
1216
|
+
`query_expansions` is directional: only the key on the left triggers the terms on the right. If you need mutual expansion without duplicating entries, use `query_expansion_groups`.
|
|
1217
|
+
|
|
1218
|
+
```yaml
|
|
1219
|
+
query_expansion_groups:
|
|
1220
|
+
- ["triple barrier", "tb", "trip_barr"]
|
|
1221
|
+
- ["profit factor", "pf"]
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
Each group is interpreted symmetrically, so every term expands to the rest of the group. The final internal expansion table is built by merging both sources:
|
|
1225
|
+
|
|
1226
|
+
1. `query_expansions` entries are loaded as-is.
|
|
1227
|
+
2. `query_expansion_groups` adds reciprocal links for every term in each group.
|
|
1228
|
+
3. Overlaps are merged by union with duplicate terms removed.
|
|
1229
|
+
|
|
1230
|
+
This keeps backward compatibility while allowing concise synonym groups.
|
|
1231
|
+
|
|
960
1232
|
### Hybrid Search Tuning
|
|
961
1233
|
|
|
962
1234
|
| hybrid_alpha | Behavior | Best For |
|
|
@@ -1098,10 +1370,59 @@ export KNOWLEDGE_RAG_SINGLE_INSTANCE=1
|
|
|
1098
1370
|
|
|
1099
1371
|
A second instance exits immediately with code 75. Default is OFF (multi-client friendly). Full guide: [docs/single-instance.md](docs/single-instance.md). Sample MCP config: [examples/mcp-config-single-instance.json](examples/mcp-config-single-instance.json).
|
|
1100
1372
|
|
|
1373
|
+
### SSE server won't start
|
|
1374
|
+
|
|
1375
|
+
```bash
|
|
1376
|
+
# Check if port 8179 is already in use
|
|
1377
|
+
# Windows:
|
|
1378
|
+
netstat -aon | findstr :8179
|
|
1379
|
+
# Linux/macOS:
|
|
1380
|
+
lsof -i :8179
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
If `uvicorn` is not found, install the server extras: `pip install knowledge-rag[server]`
|
|
1384
|
+
|
|
1385
|
+
### Can't connect to SSE server
|
|
1386
|
+
|
|
1387
|
+
Verify the server is running and the URL is correct:
|
|
1388
|
+
|
|
1389
|
+
```bash
|
|
1390
|
+
curl http://127.0.0.1:8179/sse
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
Common issues:
|
|
1394
|
+
- Wrong URL: must end with `/sse` (not just the port)
|
|
1395
|
+
- Firewall blocking the port
|
|
1396
|
+
- Server started with a different host/port than configured in the MCP client
|
|
1397
|
+
|
|
1101
1398
|
---
|
|
1102
1399
|
|
|
1103
1400
|
## Changelog
|
|
1104
1401
|
|
|
1402
|
+
### v4.0.0 (2026-06-09) — Enterprise Concurrent Access
|
|
1403
|
+
|
|
1404
|
+
- **NEW**: SSE and streamable-http transport modes — 1 server serves N clients (`server.transport: "sse"` in config.yaml or `--transport sse` CLI).
|
|
1405
|
+
- **NEW**: Thread-safe shared state for concurrent queries — QueryCache locking, BM25 build lock, orchestrator double-checked locking.
|
|
1406
|
+
- **NEW**: ChromaDB WAL mode enabled automatically in SSE/HTTP mode for concurrent read performance.
|
|
1407
|
+
- **NEW**: Optional rate limiting — sliding-window counter, configurable RPM and burst, disabled by default.
|
|
1408
|
+
- **NEW**: Optional Prometheus metrics endpoint — tool call counts, latency histograms, separate port, disabled by default.
|
|
1409
|
+
- **NEW**: All 13 MCP tools instrumented with `@rate_limited` and `@instrument` decorators (zero-cost when disabled).
|
|
1410
|
+
- **NEW**: `--transport` CLI override for Docker/systemd deployments.
|
|
1411
|
+
- **NEW**: `pip install knowledge-rag[server]` optional dependency for SSE/HTTP (uvicorn).
|
|
1412
|
+
- **CHANGED**: SSE/HTTP mode auto-enables single-instance lock (port collision prevention).
|
|
1413
|
+
- **CHANGED**: `mcp` dependency bumped to `>=1.6.0` (SSE/streamable-http support).
|
|
1414
|
+
- **MIGRATION**: Default transport remains `stdio` — existing users need zero changes. See config.example.yaml for SSE setup.
|
|
1415
|
+
|
|
1416
|
+
### v3.9.1 (2026-06-08)
|
|
1417
|
+
|
|
1418
|
+
- **FIX**: Expand `~` in `config.yaml` path values (`documents_dir`, `data_dir`, `models_cache_dir`) via `expanduser()` on all platforms (#86).
|
|
1419
|
+
- **FIX**: Warn when `documents_dir` resolves to a non-existent path instead of silently indexing zero files.
|
|
1420
|
+
- **FIX**: File watcher now uses accumulate-mode debounce — bulk file copies no longer starve the reindex trigger.
|
|
1421
|
+
- **FIX**: Concurrent `index_all()` calls are serialized via `_index_lock` to prevent ChromaDB SQLite corruption.
|
|
1422
|
+
- **FIX**: `collection.add()` is batched (500 chunks/call) to cap memory usage during large reindex operations.
|
|
1423
|
+
- **NEW**: `KNOWLEDGE_RAG_WATCHER_DISABLED=1` env var to disable the file watcher for troubleshooting.
|
|
1424
|
+
- **NEW**: Progress logging every 10% for reindex operations with >100 documents.
|
|
1425
|
+
|
|
1105
1426
|
### v3.9.0 (2026-05-10) — Quality Gate
|
|
1106
1427
|
|
|
1107
1428
|
**Major governance + CI hardening release. No runtime behavior change in `mcp_server/`. Public API surface unchanged from v3.8.1.**
|
|
@@ -1145,6 +1466,50 @@ A second instance exits immediately with code 75. Default is OFF (multi-client f
|
|
|
1145
1466
|
|
|
1146
1467
|
### Unreleased
|
|
1147
1468
|
|
|
1469
|
+
### v4.3.0 (2026-06-17) — Async Reindex, GPU CUDA 12, 13th MCP Tool
|
|
1470
|
+
|
|
1471
|
+
- **NEW**: `get_reindex_status` MCP tool — lightweight reindex progress polling without computing full index stats. Returns active/idle status, percent, processed/total, errors, and last result.
|
|
1472
|
+
- **NEW**: `reindex_documents` now runs in background via daemon thread — returns immediately with `{"status": "started"}`. Eliminates MCP timeout on large document sets (5K+ files). Concurrent calls return `already_running` with current progress.
|
|
1473
|
+
- **NEW**: GPU acceleration with full CUDA 12 support — `onnxruntime-gpu` + 7 NVIDIA pip packages (`cublas`, `cudnn`, `cuda-runtime`, `cufft`, `cusparse`, `cusolver`, `curand`, `nvjitlink`). Server auto-detects GPU on startup with 4-step verification (providers, DLLs, nvidia-smi, session creation). Falls back to CPU gracefully.
|
|
1474
|
+
- **NEW**: `_setup_cuda_dll_paths()` adds NVIDIA pip package DLL directories to `PATH` automatically on Windows — onnxruntime finds CUDA 12 DLLs without a full CUDA Toolkit install.
|
|
1475
|
+
- **DEPS**: `[gpu]` extra expanded from 3 to 8 packages (added `cufft`, `cusparse`, `cusolver`, `curand`, `nvjitlink`).
|
|
1476
|
+
- **FIX**: GPU status reporting now uses actual ONNX session creation test instead of just checking `get_available_providers()` — prevents false "GPU ACTIVE" when CUDA DLLs are missing.
|
|
1477
|
+
- **DOCS**: GPU Acceleration section rewritten with complete requirements table, setup steps, verification instructions, and fallback behavior.
|
|
1478
|
+
- **DOCS**: Tool reference updated — `reindex_documents` async behavior documented, `get_reindex_status` reference added.
|
|
1479
|
+
- **TEST**: Backwards-compat baseline updated for 13 MCP tools.
|
|
1480
|
+
|
|
1481
|
+
### v4.2.0 (2026-06-17) — Search Performance & Output Quality
|
|
1482
|
+
|
|
1483
|
+
- **PERF**: Custom inverted-index BM25 replaces `rank-bm25` full-corpus scan — 128× faster keyword search on 50K+ chunk corpora. Only documents containing query terms are scored via posting lists.
|
|
1484
|
+
- **PERF**: `numpy.argpartition` for O(n) top-k selection instead of O(n log n) sort.
|
|
1485
|
+
- **PERF**: Batched adjacent chunk fetch — single ChromaDB `collection.get()` call replaces N round-trips per result.
|
|
1486
|
+
- **PERF**: O(1) reverse lookup via `_source_to_docid` dict eliminates linear scans of `_indexed_docs` in `search_similar`, `update_document`, `remove_document`, and `_expand_with_adjacent_chunks`.
|
|
1487
|
+
- **NEW**: `snippet_mode` parameter on `search_knowledge` (default: `true`) — truncates content to ~500 chars at natural break points with `content_length` field. Reduces token consumption by ~72%.
|
|
1488
|
+
- **NEW**: `min_score` parameter on `search_knowledge` (default: `0.0`) — filters results below a normalized relevance threshold. Response includes `filtered_by_score` count.
|
|
1489
|
+
- **NEW**: `filtered_by_score` field in search response JSON for transparency.
|
|
1490
|
+
- **DEPS**: `numpy` added as direct dependency (was transitive via fastembed); `rank-bm25` import removed from server.py.
|
|
1491
|
+
- **TEST**: 6 new tests for `min_score` filtering and `snippet_mode` truncation.
|
|
1492
|
+
- **TEST**: Updated backwards-compat baseline to include new `search_knowledge` parameters.
|
|
1493
|
+
|
|
1494
|
+
### v4.1.2 (2026-06-17)
|
|
1495
|
+
|
|
1496
|
+
- **FIX**: `_save_metadata` dict snapshot prevents concurrent modification crash during file watcher events.
|
|
1497
|
+
- **STYLE**: ruff format applied to server.py.
|
|
1498
|
+
|
|
1499
|
+
### v4.1.1 (2026-06-17)
|
|
1500
|
+
|
|
1501
|
+
- **FIX**: All `_indexed_docs` iterations now use `list()` snapshot, preventing `dictionary changed size during iteration` crash when FileWatcher modifies the index concurrently with MCP tool calls (affects `search_knowledge`, `search_similar`, `update_document`, `remove_document`, `evaluate_retrieval`, `list_categories`, `list_documents`)
|
|
1502
|
+
|
|
1503
|
+
### v4.1.0 (2026-06-17)
|
|
1504
|
+
|
|
1505
|
+
- **Added:** `query_expansion_groups` config for symmetric synonym expansion (#92)
|
|
1506
|
+
- **Improved:** `expand_query()` now returns deterministic expansion order (set → ordered list with dedup)
|
|
1507
|
+
|
|
1508
|
+
### v4.0.1 (2026-06-16)
|
|
1509
|
+
|
|
1510
|
+
- **FIX**: Orphan cleanup now runs before indexing loop, preventing chunk loss when files are moved (#90).
|
|
1511
|
+
- **FIX**: Chunk deduplication is now per-document instead of global, preventing cross-document chunk deletion (#91).
|
|
1512
|
+
- **FIX**: Added `on_moved` handler to `DocumentWatcher` for proper file move detection.
|
|
1148
1513
|
- **FIX**: Startup preflight probes ChromaDB in a child process and moves crashing persistent indexes to `data/backups/auto-repair-*` before MCP initialization.
|
|
1149
1514
|
- **FIX**: Reranker load failures now fall back to RRF ordering instead of failing `search_knowledge` on offline machines.
|
|
1150
1515
|
- **FIX**: Virtualenv project-root detection now handles Python symlinks that resolve to the system interpreter.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knowledge-rag",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking +
|
|
3
|
+
"version": "4.3.0",
|
|
4
|
+
"description": "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 13 MCP Tools + 20 Format Parsers. Zero external servers.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"knowledge-rag": "./bin/cli.js"
|
|
7
7
|
},
|