knowledge-rag 3.8.1 → 4.2.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 +334 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|

|
|
12
12
|
[](https://github.com/lyonzin/knowledge-rag/actions/workflows/ci.yml)
|
|
13
13
|
[](https://github.com/lyonzin/knowledge-rag/actions/workflows/security.yml)
|
|
14
|
+
[](https://github.com/lyonzin/knowledge-rag/actions/workflows/quality-gate.yml)
|
|
14
15
|
[](https://glama.ai/mcp/servers/lyonzin/knowledge-rag)
|
|
15
16
|
|
|
16
17
|
### Your docs, your machine, zero cloud. Claude Code searches them natively.
|
|
@@ -27,19 +28,90 @@ pip install knowledge-rag → restart Claude Code → search_knowledge("your que
|
|
|
27
28
|
|
|
28
29
|
**12 MCP Tools** | **Hybrid Search + Reranking** | **20 File Formats** | **Optional NVIDIA GPU** | **100% Local**
|
|
29
30
|
|
|
30
|
-
[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)
|
|
31
32
|
|
|
32
33
|
</div>
|
|
33
34
|
|
|
34
35
|
---
|
|
35
36
|
|
|
36
|
-
##
|
|
37
|
+
## Star History
|
|
37
38
|
|
|
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 12 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.
|
|
87
|
+
|
|
88
|
+
### Quality Gate — 7-Pillar PR Validation
|
|
89
|
+
|
|
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:
|
|
91
|
+
|
|
92
|
+
| Pillar | What it enforces | Tools |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| **1 Security** | SAST, secrets, CVEs, supply chain | bandit, semgrep, gitleaks, pip-audit, dependency-review, Snyk, CodeQL, Socket |
|
|
95
|
+
| **2 Stability** | Flake detection, coverage trend, test count, deterministic runs | pytest-rerunfailures, codecov ±0.5pp, test-count guard |
|
|
96
|
+
| **3 Memory Leak** | RSS bounded under 1000-query load, no idle bloat | psutil-based baseline tests + nightly 50K-iteration soak |
|
|
97
|
+
| **4 Versatility** | 9 OS×Python combos, 14 format parsers, 4 config presets, locale tolerance, property-based fuzzing | matrix CI on Linux+Windows+macOS × 3.11+3.12+3.13, Hypothesis |
|
|
98
|
+
| **5 Scalability** | Performance regression > 10% blocks merge, public bench dashboard | pytest-benchmark, GH Pages chart |
|
|
99
|
+
| **6 Versioning** | Atomic version sync, API surface diff, conventional commits, CHANGELOG enforcement, backwards compat | griffe-style AST diff, custom guards |
|
|
100
|
+
| **7 Quality** | Type strictness, docstring coverage, complexity, dead code | mypy strict, interrogate ≥80%, radon, vulture |
|
|
101
|
+
|
|
102
|
+
Plus a **nightly resilience workflow** that runs chaos failure-injection (HF down, ChromaDB corruption, watchdog crash, ONNX zero-byte replay), determinism check (full suite × 3), and mutation testing on selected modules.
|
|
103
|
+
|
|
104
|
+
Read the full philosophy in [CONTRIBUTING.md](CONTRIBUTING.md). Report bugs via [SECURITY.md](SECURITY.md) or the [issue templates](.github/ISSUE_TEMPLATE/).
|
|
105
|
+
|
|
106
|
+
### Critical Hotfix — No More Silent Zero-Vector Corruption (v3.8.1)
|
|
107
|
+
|
|
108
|
+
`FastEmbedEmbeddings.__call__` no longer swallows exceptions and returns `[[0.0]*dim, ...]` when the ONNX model fails to load. That bug pre-existed in master but was silent: ChromaDB happily stored zero embeddings, `count()` reported normal numbers, smart-reindex skipped them as "already indexed", and queries returned garbage similarity with no error visible. Now raises `EmbeddingModelLoadError` / `EmbeddingError` loudly. **All v3.8.0 users should upgrade.** Full details in [Changelog](#v381-2026-05-10--hotfix).
|
|
109
|
+
|
|
110
|
+
### Lazy-Loaded Embeddings — Cheaper Idle Processes (v3.8.0)
|
|
39
111
|
|
|
40
112
|
The FastEmbed ONNX model (~200MB resident) now loads on the **first query**, not at startup. Idle `knowledge-rag` processes are now genuinely cheap. Why this matters: MCP stdio is one-process-per-client by protocol — multiple Claude Code windows, Claude Desktop + IDE simultaneously, or review/approval flows that open extra connections all spawn their own processes. Before v3.8.0, every one of them paid the full embedding-model cost up front. Now only processes that actually serve queries load the model. Public API is unchanged.
|
|
41
113
|
|
|
42
|
-
### Opt-In Single-Instance Guard
|
|
114
|
+
### Opt-In Single-Instance Guard (v3.8.0)
|
|
43
115
|
|
|
44
116
|
For users who measured their setup and want a hard cap of one server per `data_dir`:
|
|
45
117
|
|
|
@@ -63,6 +135,9 @@ All methods produce the same MCP server. See [Installation](#installation) for f
|
|
|
63
135
|
|
|
64
136
|
### Recent Highlights
|
|
65
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
|
|
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)
|
|
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)
|
|
66
141
|
- **v3.8.0** — Lazy-load embeddings, opt-in single-instance guard, version sync across PyPI/NPM/Docker
|
|
67
142
|
- **v3.6.0** — Multi-language code parsing (C/C++/JS/TS/XML), NPM wrapper, Docker image, automated release pipeline
|
|
68
143
|
- **v3.5.2** — CUDA DLL auto-discovery from pip packages, graceful GPU→CPU fallback, explicit CPU provider (no CUDA noise when `gpu: false`), BASE_DIR resolution fix for editable installs
|
|
@@ -149,7 +224,7 @@ flowchart TB
|
|
|
149
224
|
direction LR
|
|
150
225
|
ROUTER["Keyword Router<br/>(word boundaries)"]
|
|
151
226
|
SEMANTIC["Semantic Search<br/>(ChromaDB)"]
|
|
152
|
-
BM25["BM25 Keyword<br/>(
|
|
227
|
+
BM25["BM25 Keyword<br/>(inverted-index + expansion)"]
|
|
153
228
|
RRF["Reciprocal Rank<br/>Fusion (RRF)"]
|
|
154
229
|
RERANK["Cross-Encoder<br/>Reranker"]
|
|
155
230
|
|
|
@@ -213,15 +288,23 @@ flowchart TB
|
|
|
213
288
|
subgraph HYBRID["Hybrid Search"]
|
|
214
289
|
direction LR
|
|
215
290
|
SEMANTIC["Semantic Search<br/>(ChromaDB embeddings)<br/>Conceptual similarity"]
|
|
216
|
-
BM25["BM25
|
|
291
|
+
BM25["BM25 Inverted-Index<br/>(posting lists + numpy top-k)<br/>Exact term matching"]
|
|
217
292
|
end
|
|
218
293
|
|
|
219
294
|
subgraph FUSION["Result Fusion + Reranking"]
|
|
220
295
|
RRF["Reciprocal Rank Fusion<br/>score = alpha * 1/(k+rank_sem)<br/>+ (1-alpha) * 1/(k+rank_bm25)"]
|
|
221
296
|
RERANK["Cross-Encoder Reranker<br/>Re-scores top 3x candidates<br/>query+doc pair scoring"]
|
|
222
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)"]
|
|
223
306
|
|
|
224
|
-
|
|
307
|
+
MINSCORE --> SNIPPET
|
|
225
308
|
end
|
|
226
309
|
|
|
227
310
|
CATEGORY --> HYBRID
|
|
@@ -229,7 +312,8 @@ flowchart TB
|
|
|
229
312
|
SEMANTIC --> RRF
|
|
230
313
|
BM25 --> RRF
|
|
231
314
|
|
|
232
|
-
|
|
315
|
+
ADJ --> MINSCORE
|
|
316
|
+
SNIPPET --> RESULTS["Results<br/>search_method: hybrid|semantic|keyword<br/>score + filtered_by_score + content_length"]
|
|
233
317
|
```
|
|
234
318
|
|
|
235
319
|
### Document Ingestion Flow
|
|
@@ -306,6 +390,7 @@ flowchart LR
|
|
|
306
390
|
|
|
307
391
|
- Python 3.11+
|
|
308
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)*
|
|
309
394
|
- ~200MB disk for model cache (auto-downloaded on first run)
|
|
310
395
|
- *Optional:* NVIDIA GPU + CUDA for accelerated embeddings (`pip install knowledge-rag[gpu]` + `models.embedding.gpu: true` in config)
|
|
311
396
|
|
|
@@ -421,6 +506,94 @@ Add to `~/.claude.json`:
|
|
|
421
506
|
> Replace `YOUR_USER` with your username, or use the full path from `echo $HOME`.
|
|
422
507
|
</details>
|
|
423
508
|
|
|
509
|
+
#### Option F: SSE Server Mode (multi-agent)
|
|
510
|
+
|
|
511
|
+
For multi-agent setups where multiple clients query the same knowledge base simultaneously:
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
pip install knowledge-rag[server] # Adds uvicorn for SSE/HTTP
|
|
515
|
+
knowledge-rag --transport sse # Starts on http://127.0.0.1:8179
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Then configure each MCP client to connect via SSE:
|
|
519
|
+
|
|
520
|
+
```json
|
|
521
|
+
{
|
|
522
|
+
"mcpServers": {
|
|
523
|
+
"knowledge-rag": {
|
|
524
|
+
"type": "sse",
|
|
525
|
+
"url": "http://127.0.0.1:8179/sse"
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
One server process serves all agents — shared embedding model, shared cache, shared ChromaDB. See [Configuration > Server](#server) for rate limiting, metrics, and auth options.
|
|
532
|
+
|
|
533
|
+
### Use with other MCP clients
|
|
534
|
+
|
|
535
|
+
`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.
|
|
536
|
+
|
|
537
|
+
#### Clients using the standard `mcpServers` format
|
|
538
|
+
|
|
539
|
+
For **Claude Desktop, Cursor, Antigravity, and Windsurf**, use the same block — only the file location changes:
|
|
540
|
+
|
|
541
|
+
```json
|
|
542
|
+
{
|
|
543
|
+
"mcpServers": {
|
|
544
|
+
"knowledge-rag": {
|
|
545
|
+
"command": "/home/YOUR_USER/knowledge-rag/venv/bin/python",
|
|
546
|
+
"args": ["-m", "mcp_server.server"]
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
> **Windows**: set `command` to the full path of `venv\Scripts\python.exe`.
|
|
553
|
+
|
|
554
|
+
| Client | Config file | Notes |
|
|
555
|
+
|---|---|---|
|
|
556
|
+
| **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. |
|
|
557
|
+
| **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). |
|
|
558
|
+
| **Cursor** | `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project) | — |
|
|
559
|
+
| **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**. |
|
|
560
|
+
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json` (global only) | Easiest: Cascade panel → MCP → **View raw config**. |
|
|
561
|
+
|
|
562
|
+
#### VS Code — uses a `servers` key
|
|
563
|
+
|
|
564
|
+
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:
|
|
565
|
+
|
|
566
|
+
```json
|
|
567
|
+
{
|
|
568
|
+
"servers": {
|
|
569
|
+
"knowledge-rag": {
|
|
570
|
+
"type": "stdio",
|
|
571
|
+
"command": "/home/YOUR_USER/knowledge-rag/venv/bin/python",
|
|
572
|
+
"args": ["-m", "mcp_server.server"]
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
#### opencode — uses an `mcp` key
|
|
579
|
+
|
|
580
|
+
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):
|
|
581
|
+
|
|
582
|
+
```jsonc
|
|
583
|
+
{
|
|
584
|
+
"$schema": "https://opencode.ai/config.json",
|
|
585
|
+
"mcp": {
|
|
586
|
+
"knowledge-rag": {
|
|
587
|
+
"type": "local",
|
|
588
|
+
"command": ["/home/YOUR_USER/knowledge-rag/venv/bin/python", "-m", "mcp_server.server"],
|
|
589
|
+
"enabled": true
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
> **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.
|
|
596
|
+
|
|
424
597
|
### Verify
|
|
425
598
|
|
|
426
599
|
```bash
|
|
@@ -529,6 +702,8 @@ Hybrid search combining semantic search + BM25 keyword search with cross-encoder
|
|
|
529
702
|
| `max_results` | int | 5 | Maximum results to return (1-20) |
|
|
530
703
|
| `category` | string | null | Filter by category |
|
|
531
704
|
| `hybrid_alpha` | float | 0.3 | Balance: 0.0 = keyword only, 1.0 = semantic only |
|
|
705
|
+
| `min_score` | float | 0.0 | Minimum relevance score (0.0-1.0) to include a result. Use 0.2-0.4 to cut noise |
|
|
706
|
+
| `snippet_mode` | bool | true | Truncate content to ~500 chars at natural break points. Adds `content_length` field |
|
|
532
707
|
|
|
533
708
|
**Returns:**
|
|
534
709
|
|
|
@@ -538,6 +713,7 @@ Hybrid search combining semantic search + BM25 keyword search with cross-encoder
|
|
|
538
713
|
"query": "mimikatz credential dump",
|
|
539
714
|
"hybrid_alpha": 0.5,
|
|
540
715
|
"result_count": 3,
|
|
716
|
+
"filtered_by_score": 2,
|
|
541
717
|
"cache_hit_rate": "0.0%",
|
|
542
718
|
"results": [
|
|
543
719
|
{
|
|
@@ -635,7 +811,6 @@ Get statistics about the knowledge base index.
|
|
|
635
811
|
"stats": {
|
|
636
812
|
"total_documents": 75,
|
|
637
813
|
"total_chunks": 9256,
|
|
638
|
-
"unique_content_hashes": 9100,
|
|
639
814
|
"categories": {"security": 52, "development": 8},
|
|
640
815
|
"supported_formats": [".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv", ".ipynb"],
|
|
641
816
|
"embedding_model": "BAAI/bge-small-en-v1.5",
|
|
@@ -817,6 +992,21 @@ query_expansions:
|
|
|
817
992
|
privesc:
|
|
818
993
|
- privilege escalation
|
|
819
994
|
- privesc
|
|
995
|
+
|
|
996
|
+
# Server — enterprise features (new in v4.0.0)
|
|
997
|
+
server:
|
|
998
|
+
transport: "stdio" # "stdio" | "sse" | "streamable-http"
|
|
999
|
+
host: "127.0.0.1" # Bind address (SSE/HTTP only)
|
|
1000
|
+
port: 8179 # Bind port (SSE/HTTP only)
|
|
1001
|
+
auth:
|
|
1002
|
+
bearer_token: "" # Set a secret to enable auth (SSE/HTTP only)
|
|
1003
|
+
rate_limit:
|
|
1004
|
+
enabled: false
|
|
1005
|
+
requests_per_minute: 60
|
|
1006
|
+
burst: 10
|
|
1007
|
+
metrics:
|
|
1008
|
+
enabled: false
|
|
1009
|
+
port: 9179 # Separate port for Prometheus scraping
|
|
820
1010
|
```
|
|
821
1011
|
|
|
822
1012
|
> See `config.example.yaml` for the fully documented template with explanations for every field.
|
|
@@ -836,6 +1026,22 @@ Pre-built configurations for common use cases:
|
|
|
836
1026
|
|
|
837
1027
|
### Configuration Reference
|
|
838
1028
|
|
|
1029
|
+
#### Server
|
|
1030
|
+
|
|
1031
|
+
| Field | Default | Description |
|
|
1032
|
+
|-------|---------|-------------|
|
|
1033
|
+
| `server.transport` | `"stdio"` | Transport protocol: `"stdio"`, `"sse"`, or `"streamable-http"` |
|
|
1034
|
+
| `server.host` | `"127.0.0.1"` | Bind address for SSE/HTTP mode |
|
|
1035
|
+
| `server.port` | `8179` | Bind port for SSE/HTTP mode |
|
|
1036
|
+
| `server.auth.bearer_token` | `""` (disabled) | Bearer token for SSE/HTTP auth. Empty = no auth |
|
|
1037
|
+
| `server.rate_limit.enabled` | `false` | Enable per-client rate limiting |
|
|
1038
|
+
| `server.rate_limit.requests_per_minute` | `60` | Max requests per minute |
|
|
1039
|
+
| `server.rate_limit.burst` | `10` | Burst allowance above steady rate |
|
|
1040
|
+
| `server.metrics.enabled` | `false` | Enable Prometheus `/metrics` endpoint |
|
|
1041
|
+
| `server.metrics.port` | `9179` | Port for metrics scraping |
|
|
1042
|
+
|
|
1043
|
+
In stdio mode (default), server settings are ignored. SSE/HTTP mode auto-enables the single-instance lock.
|
|
1044
|
+
|
|
839
1045
|
#### Paths
|
|
840
1046
|
|
|
841
1047
|
| Field | Default | Description |
|
|
@@ -932,6 +1138,22 @@ query_expansions:
|
|
|
932
1138
|
|
|
933
1139
|
Set `query_expansions: {}` for no expansion.
|
|
934
1140
|
|
|
1141
|
+
`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`.
|
|
1142
|
+
|
|
1143
|
+
```yaml
|
|
1144
|
+
query_expansion_groups:
|
|
1145
|
+
- ["triple barrier", "tb", "trip_barr"]
|
|
1146
|
+
- ["profit factor", "pf"]
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
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:
|
|
1150
|
+
|
|
1151
|
+
1. `query_expansions` entries are loaded as-is.
|
|
1152
|
+
2. `query_expansion_groups` adds reciprocal links for every term in each group.
|
|
1153
|
+
3. Overlaps are merged by union with duplicate terms removed.
|
|
1154
|
+
|
|
1155
|
+
This keeps backward compatibility while allowing concise synonym groups.
|
|
1156
|
+
|
|
935
1157
|
### Hybrid Search Tuning
|
|
936
1158
|
|
|
937
1159
|
| hybrid_alpha | Behavior | Best For |
|
|
@@ -1073,10 +1295,81 @@ export KNOWLEDGE_RAG_SINGLE_INSTANCE=1
|
|
|
1073
1295
|
|
|
1074
1296
|
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).
|
|
1075
1297
|
|
|
1298
|
+
### SSE server won't start
|
|
1299
|
+
|
|
1300
|
+
```bash
|
|
1301
|
+
# Check if port 8179 is already in use
|
|
1302
|
+
# Windows:
|
|
1303
|
+
netstat -aon | findstr :8179
|
|
1304
|
+
# Linux/macOS:
|
|
1305
|
+
lsof -i :8179
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
If `uvicorn` is not found, install the server extras: `pip install knowledge-rag[server]`
|
|
1309
|
+
|
|
1310
|
+
### Can't connect to SSE server
|
|
1311
|
+
|
|
1312
|
+
Verify the server is running and the URL is correct:
|
|
1313
|
+
|
|
1314
|
+
```bash
|
|
1315
|
+
curl http://127.0.0.1:8179/sse
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
Common issues:
|
|
1319
|
+
- Wrong URL: must end with `/sse` (not just the port)
|
|
1320
|
+
- Firewall blocking the port
|
|
1321
|
+
- Server started with a different host/port than configured in the MCP client
|
|
1322
|
+
|
|
1076
1323
|
---
|
|
1077
1324
|
|
|
1078
1325
|
## Changelog
|
|
1079
1326
|
|
|
1327
|
+
### v4.0.0 (2026-06-09) — Enterprise Concurrent Access
|
|
1328
|
+
|
|
1329
|
+
- **NEW**: SSE and streamable-http transport modes — 1 server serves N clients (`server.transport: "sse"` in config.yaml or `--transport sse` CLI).
|
|
1330
|
+
- **NEW**: Thread-safe shared state for concurrent queries — QueryCache locking, BM25 build lock, orchestrator double-checked locking.
|
|
1331
|
+
- **NEW**: ChromaDB WAL mode enabled automatically in SSE/HTTP mode for concurrent read performance.
|
|
1332
|
+
- **NEW**: Optional rate limiting — sliding-window counter, configurable RPM and burst, disabled by default.
|
|
1333
|
+
- **NEW**: Optional Prometheus metrics endpoint — tool call counts, latency histograms, separate port, disabled by default.
|
|
1334
|
+
- **NEW**: All 12 MCP tools instrumented with `@rate_limited` and `@instrument` decorators (zero-cost when disabled).
|
|
1335
|
+
- **NEW**: `--transport` CLI override for Docker/systemd deployments.
|
|
1336
|
+
- **NEW**: `pip install knowledge-rag[server]` optional dependency for SSE/HTTP (uvicorn).
|
|
1337
|
+
- **CHANGED**: SSE/HTTP mode auto-enables single-instance lock (port collision prevention).
|
|
1338
|
+
- **CHANGED**: `mcp` dependency bumped to `>=1.6.0` (SSE/streamable-http support).
|
|
1339
|
+
- **MIGRATION**: Default transport remains `stdio` — existing users need zero changes. See config.example.yaml for SSE setup.
|
|
1340
|
+
|
|
1341
|
+
### v3.9.1 (2026-06-08)
|
|
1342
|
+
|
|
1343
|
+
- **FIX**: Expand `~` in `config.yaml` path values (`documents_dir`, `data_dir`, `models_cache_dir`) via `expanduser()` on all platforms (#86).
|
|
1344
|
+
- **FIX**: Warn when `documents_dir` resolves to a non-existent path instead of silently indexing zero files.
|
|
1345
|
+
- **FIX**: File watcher now uses accumulate-mode debounce — bulk file copies no longer starve the reindex trigger.
|
|
1346
|
+
- **FIX**: Concurrent `index_all()` calls are serialized via `_index_lock` to prevent ChromaDB SQLite corruption.
|
|
1347
|
+
- **FIX**: `collection.add()` is batched (500 chunks/call) to cap memory usage during large reindex operations.
|
|
1348
|
+
- **NEW**: `KNOWLEDGE_RAG_WATCHER_DISABLED=1` env var to disable the file watcher for troubleshooting.
|
|
1349
|
+
- **NEW**: Progress logging every 10% for reindex operations with >100 documents.
|
|
1350
|
+
|
|
1351
|
+
### v3.9.0 (2026-05-10) — Quality Gate
|
|
1352
|
+
|
|
1353
|
+
**Major governance + CI hardening release. No runtime behavior change in `mcp_server/`. Public API surface unchanged from v3.8.1.**
|
|
1354
|
+
|
|
1355
|
+
- **NEW** Quality Gate workflow (`.github/workflows/quality-gate.yml`) enforcing the 7 pillars on every PR: Security, Stability, Memory Leak, Versatility, Scalability, Versioning, Quality. 35+ status checks total.
|
|
1356
|
+
- **NEW** Nightly resilience workflow (`.github/workflows/nightly.yml`): chaos suite (failure injection), 1h soak test (50K-iteration loop), determinism check (full suite × 3), mutation testing (mutmut). Auto-opens GitHub issue on any nightly failure.
|
|
1357
|
+
- **NEW** Performance benchmark suite under `bench/` (12 microbenchmarks, pytest-benchmark) with 10% regression gate on every PR.
|
|
1358
|
+
- **NEW** Public performance dashboard via GitHub Pages (`.github/workflows/bench-pages.yml`) — chart of latency/throughput per commit. Dormant until repo Pages is enabled.
|
|
1359
|
+
- **NEW** Property-based fuzzing of all parsers via Hypothesis (`tests/test_ingestion_property.py`) — 200 random examples per CI run.
|
|
1360
|
+
- **NEW** Memory baseline regression tests (`tests/test_memory_baseline.py`, cross-platform via psutil) — RSS bounded under 1000 queries; nightly soak amplifies to 50K iterations.
|
|
1361
|
+
- **NEW** Property/locale/format/preset matrices (`tests/test_presets.py`, `tests/test_locale.py`, `tests/test_format_smoke.py`).
|
|
1362
|
+
- **NEW** Backwards-compatibility regression tests (`tests/test_backwards_compat.py`) — legacy YAML configs from v3.6.0 / v3.7.0 still parse; all 12 MCP tool parameter names frozen.
|
|
1363
|
+
- **NEW** AST-based public API surface diff (`scripts/check_api_surface.py`) — any breaking change blocks merge, baseline at `.github/api-surface-baseline.json`.
|
|
1364
|
+
- **NEW** CHANGELOG enforcement (`scripts/check_changelog.py`) — user-facing PRs must add a bullet under `## Unreleased`; bypass via `skip-changelog` label.
|
|
1365
|
+
- **NEW** Test count anti-regression (`scripts/check_test_count.py`) — guards against silent test deletion.
|
|
1366
|
+
- **NEW** Conventional commits required on every PR title (commitlint via `amannn/action-semantic-pull-request`).
|
|
1367
|
+
- **NEW** mypy `--strict` rolling out per-module (currently `instance_lock.py` + `preflight.py` + `scripts/`); interrogate docstring coverage ≥ 80%; radon, vulture, PR-size guard report-only.
|
|
1368
|
+
- **NEW** CI matrix expanded to 9 cells: Linux + Windows + **macOS** × 3.11 + 3.12 + **3.13** (all required at v3.9.0; macOS / 3.13 promoted from experimental after two clean cycles).
|
|
1369
|
+
- **NEW** Governance docs: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `.github/PULL_REQUEST_TEMPLATE.md`, 3 issue templates, expanded `CODEOWNERS`.
|
|
1370
|
+
- **NEW** Pre-commit hooks: ruff, gitleaks, version-sync, conventional commits.
|
|
1371
|
+
- **CHORE** `.github/codecov.yml` enforcing coverage trend gate (-0.5pp blocks; new code ≥ 70%).
|
|
1372
|
+
|
|
1080
1373
|
### v3.8.1 (2026-05-10) — hotfix
|
|
1081
1374
|
|
|
1082
1375
|
- **FIX (critical)**: `FastEmbedEmbeddings.__call__` no longer returns vectors of zeros when the ONNX model fails to load or `embed()` raises. The previous behavior silently corrupted the index — ChromaDB stored zero embeddings, `count()` reported normal numbers, smart-reindex skipped the bad chunks, and queries returned garbage scores with no error visible. Now raises `EmbeddingModelLoadError` / `EmbeddingError`. (#36)
|
|
@@ -1098,6 +1391,38 @@ A second instance exits immediately with code 75. Default is OFF (multi-client f
|
|
|
1098
1391
|
|
|
1099
1392
|
### Unreleased
|
|
1100
1393
|
|
|
1394
|
+
### v4.2.0 (2026-06-17) — Search Performance & Output Quality
|
|
1395
|
+
|
|
1396
|
+
- **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.
|
|
1397
|
+
- **PERF**: `numpy.argpartition` for O(n) top-k selection instead of O(n log n) sort.
|
|
1398
|
+
- **PERF**: Batched adjacent chunk fetch — single ChromaDB `collection.get()` call replaces N round-trips per result.
|
|
1399
|
+
- **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`.
|
|
1400
|
+
- **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%.
|
|
1401
|
+
- **NEW**: `min_score` parameter on `search_knowledge` (default: `0.0`) — filters results below a normalized relevance threshold. Response includes `filtered_by_score` count.
|
|
1402
|
+
- **NEW**: `filtered_by_score` field in search response JSON for transparency.
|
|
1403
|
+
- **DEPS**: `numpy` added as direct dependency (was transitive via fastembed); `rank-bm25` import removed from server.py.
|
|
1404
|
+
- **TEST**: 6 new tests for `min_score` filtering and `snippet_mode` truncation.
|
|
1405
|
+
- **TEST**: Updated backwards-compat baseline to include new `search_knowledge` parameters.
|
|
1406
|
+
|
|
1407
|
+
### v4.1.2 (2026-06-17)
|
|
1408
|
+
|
|
1409
|
+
- **FIX**: `_save_metadata` dict snapshot prevents concurrent modification crash during file watcher events.
|
|
1410
|
+
- **STYLE**: ruff format applied to server.py.
|
|
1411
|
+
|
|
1412
|
+
### v4.1.1 (2026-06-17)
|
|
1413
|
+
|
|
1414
|
+
- **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`)
|
|
1415
|
+
|
|
1416
|
+
### v4.1.0 (2026-06-17)
|
|
1417
|
+
|
|
1418
|
+
- **Added:** `query_expansion_groups` config for symmetric synonym expansion (#92)
|
|
1419
|
+
- **Improved:** `expand_query()` now returns deterministic expansion order (set → ordered list with dedup)
|
|
1420
|
+
|
|
1421
|
+
### v4.0.1 (2026-06-16)
|
|
1422
|
+
|
|
1423
|
+
- **FIX**: Orphan cleanup now runs before indexing loop, preventing chunk loss when files are moved (#90).
|
|
1424
|
+
- **FIX**: Chunk deduplication is now per-document instead of global, preventing cross-document chunk deletion (#91).
|
|
1425
|
+
- **FIX**: Added `on_moved` handler to `DocumentWatcher` for proper file move detection.
|
|
1101
1426
|
- **FIX**: Startup preflight probes ChromaDB in a child process and moves crashing persistent indexes to `data/backups/auto-repair-*` before MCP initialization.
|
|
1102
1427
|
- **FIX**: Reranker load failures now fall back to RRF ordering instead of failing `search_knowledge` on offline machines.
|
|
1103
1428
|
- **FIX**: Virtualenv project-root detection now handles Python symlinks that resolve to the system interpreter.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knowledge-rag",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 12 MCP Tools + 20 Format Parsers. Zero external servers.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"knowledge-rag": "./bin/cli.js"
|