knowledge-rag 4.6.0__tar.gz → 4.7.0__tar.gz
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.
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/.gitignore +1 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/PKG-INFO +24 -2
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/README.md +23 -1
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/__init__.py +1 -1
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/server.py +23 -2
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/pyproject.toml +1 -1
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/LICENSE +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/config.example.yaml +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/config.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/guarded.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/ingestion.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/instance_lock.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/metrics.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/preflight.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/ratelimit.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/mcp_server/security.py +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/npm/README.md +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/presets/cybersecurity.yaml +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/presets/developer.yaml +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/presets/general.yaml +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/presets/research.yaml +0 -0
- {knowledge_rag-4.6.0 → knowledge_rag-4.7.0}/requirements.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: knowledge-rag
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.7.0
|
|
4
4
|
Summary: Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 13 MCP Tools + 20 Format Parsers. Zero external servers.
|
|
5
5
|
Project-URL: Homepage, https://github.com/lyonzin/knowledge-rag
|
|
6
6
|
Project-URL: Repository, https://github.com/lyonzin/knowledge-rag
|
|
@@ -97,7 +97,21 @@ pip install knowledge-rag → restart Claude Code → search_knowledge("your que
|
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
100
|
-
## What's New in v4.
|
|
100
|
+
## What's New in v4.6.0
|
|
101
|
+
|
|
102
|
+
### MCP spec 2026-07-28 via Anthropic Tier 1 SDK (v4.6.0)
|
|
103
|
+
|
|
104
|
+
Adopts the [**MCP spec 2026-07-28**](https://blog.modelcontextprotocol.io/posts/2026-07-28/) — stateless request/response core, per-request `_meta.io.modelcontextprotocol/protocolVersion` + `clientCapabilities`, `serverInfo` on every response, retirement of the `initialize`/`initialized` handshake and the `Mcp-Session-Id` header. Delivered by moving directly to the **Anthropic Tier 1 Python SDK** (`mcp>=2.0.0,<3.0.0`, published 2026-07-28).
|
|
105
|
+
|
|
106
|
+
**What changed under the hood**:
|
|
107
|
+
- `mcp>=1.6.0,<2.0.0` → **`mcp>=2.0.0,<3.0.0`**
|
|
108
|
+
- `from mcp.server.fastmcp import FastMCP` → `from mcp.server import MCPServer`
|
|
109
|
+
- `FastMCP(name, host=, port=)` → `MCPServer(name, version="4.6.0")` — `host` / `port` moved to `mcp.run(transport=..., host=..., port=...)` on non-stdio transports (per v2 API)
|
|
110
|
+
- Server now advertises `version` in `serverInfo`, matching the 2026-07-28 spec recommendation
|
|
111
|
+
|
|
112
|
+
**Zero user-facing changes** — `@mcp.tool()` / `@mcp.resource()` / `@mcp.prompt()` decorator ergonomics are unchanged. All 13 MCP tool signatures frozen. **stdio users see zero behaviour change**. Existing clients (Claude Code, Claude Desktop, Cursor, Windsurf, VS Code Copilot, Cline, Gemini CLI, Zed) negotiate the spec version per request and continue to work.
|
|
113
|
+
|
|
114
|
+
**Why the Tier 1 SDK and not the third-party `fastmcp` package**: an early experiment with jlowin's [`fastmcp`](https://gofastmcp.com) tripped the Pillar 5 perf gate — `test_bench_orchestrator_idle_rss` +21.9% and `test_bench_query_cache_5000_entries` +17.1% RSS from the ~20 transitive deps its `[client,server]` extras pull in. Cutting the extras broke `@mcp.tool()` at runtime. Anthropic's `mcp 2.x` is the direct upstream reference — no third-party intermediary, no dependency bloat. Full details in the [v4.6.0 changelog entry](#v460-2026-07-30--mcp-spec-2026-07-28-via-anthropic-tier-1-sdk-mcp-2x) and closed PR #134.
|
|
101
115
|
|
|
102
116
|
### Search Performance & Output Quality (v4.2.0)
|
|
103
117
|
|
|
@@ -1448,6 +1462,14 @@ Common issues:
|
|
|
1448
1462
|
|
|
1449
1463
|
### Unreleased
|
|
1450
1464
|
|
|
1465
|
+
### v4.7.0 (2026-07-31) — BM25 Fragment Query Support
|
|
1466
|
+
|
|
1467
|
+
- **FIX (retrieval)**: BM25 tokenizer now emits **sub-tokens** for hyphenated alphanumeric-code composites, so fragment queries no longer silently return `NO_RESULTS`. Before v4.7.0, `MDR-AD002` was indexed as a single token `mdr-ad002`; queries like `AD002`, `MDR`, `CS005` returned zero even when the composite lived in the corpus. This is not a bug specific to MDR — it hit every hyphenated code taxonomy in typical infosec / doc corpora (`MDR-*`, `CVE-*`, `ADR-*`, `MS17-*`, `MDR-Custom001-xxxx`). The tokenizer now emits both the composite token AND its sub-parts of length ≥ 2 (`mdr-ad002` → `["mdr-ad002", "mdr", "ad002"]`). IDF preserves ranking — composite matches still rank above fragment matches because the composite is rarer. **Heuristic (perf-safety)**: sub-token expansion is triggered ONLY when the composite contains at least one digit — so `pass-the-hash`, `state-of-the-art`, and other natural-language hyphenated phrases stay as single tokens (expanding them would flood the inverted index with stop-word-like sub-parts and hurt concurrent-query throughput). (#140)
|
|
1468
|
+
- **NEW (tests)**: `tests/test_bm25_tokenizer_fragment.py` — 25 tests across 4 classes covering unit tokenizer behavior, end-to-end fragment matching, multi-doc disambiguation, and the 5 query patterns explicitly reported (`MDR-AD019`, `MDR-Custom001-xxxx`, `MDR`, `AD019`, `CS005`). Includes retrocompat sentinel + IDF ranking invariant. Baseline: 314 → 339.
|
|
1469
|
+
- **UPGRADE NOTE**: run `reindex_documents(force=True)` once after upgrade to rebuild the BM25 inverted index with the new sub-token emission. ChromaDB vectors are untouched. Expect a **~30–50% increase in BM25 index memory** (measured +32.5% on synthetic corpus) — negligible for typical corpora, worth reviewing for deployments with >100K docs.
|
|
1470
|
+
- **KNOWN LIMITATION**: alphanumeric-glued tokens without separators (`HARDLAB11`, `6a635623e114b8...`) still require exact match — no sub-token expansion possible without character n-grams (5-10× index overhead). Tracked as follow-up.
|
|
1471
|
+
- **VERSION**: 4.6.0 → **4.7.0** (MINOR — tokenization behavior change + reindex requirement, though no API/config break).
|
|
1472
|
+
|
|
1451
1473
|
### v4.6.0 (2026-07-30) — MCP spec 2026-07-28 via Anthropic Tier 1 SDK (mcp 2.x)
|
|
1452
1474
|
|
|
1453
1475
|
- **NEW (protocol)**: adopt the [MCP spec `2026-07-28`](https://blog.modelcontextprotocol.io/posts/2026-07-28/) — stateless request/response core, per-request `_meta.io.modelcontextprotocol/protocolVersion` + `clientCapabilities`, `serverInfo` on responses, retirement of the `initialize`/`initialized` handshake and the `Mcp-Session-Id` header. The MCP client Claude Code (and every Tier 1 client) negotiates the spec version per request, so this release stays backwards-compatible for clients speaking earlier spec revisions.
|
|
@@ -49,7 +49,21 @@ pip install knowledge-rag → restart Claude Code → search_knowledge("your que
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
-
## What's New in v4.
|
|
52
|
+
## What's New in v4.6.0
|
|
53
|
+
|
|
54
|
+
### MCP spec 2026-07-28 via Anthropic Tier 1 SDK (v4.6.0)
|
|
55
|
+
|
|
56
|
+
Adopts the [**MCP spec 2026-07-28**](https://blog.modelcontextprotocol.io/posts/2026-07-28/) — stateless request/response core, per-request `_meta.io.modelcontextprotocol/protocolVersion` + `clientCapabilities`, `serverInfo` on every response, retirement of the `initialize`/`initialized` handshake and the `Mcp-Session-Id` header. Delivered by moving directly to the **Anthropic Tier 1 Python SDK** (`mcp>=2.0.0,<3.0.0`, published 2026-07-28).
|
|
57
|
+
|
|
58
|
+
**What changed under the hood**:
|
|
59
|
+
- `mcp>=1.6.0,<2.0.0` → **`mcp>=2.0.0,<3.0.0`**
|
|
60
|
+
- `from mcp.server.fastmcp import FastMCP` → `from mcp.server import MCPServer`
|
|
61
|
+
- `FastMCP(name, host=, port=)` → `MCPServer(name, version="4.6.0")` — `host` / `port` moved to `mcp.run(transport=..., host=..., port=...)` on non-stdio transports (per v2 API)
|
|
62
|
+
- Server now advertises `version` in `serverInfo`, matching the 2026-07-28 spec recommendation
|
|
63
|
+
|
|
64
|
+
**Zero user-facing changes** — `@mcp.tool()` / `@mcp.resource()` / `@mcp.prompt()` decorator ergonomics are unchanged. All 13 MCP tool signatures frozen. **stdio users see zero behaviour change**. Existing clients (Claude Code, Claude Desktop, Cursor, Windsurf, VS Code Copilot, Cline, Gemini CLI, Zed) negotiate the spec version per request and continue to work.
|
|
65
|
+
|
|
66
|
+
**Why the Tier 1 SDK and not the third-party `fastmcp` package**: an early experiment with jlowin's [`fastmcp`](https://gofastmcp.com) tripped the Pillar 5 perf gate — `test_bench_orchestrator_idle_rss` +21.9% and `test_bench_query_cache_5000_entries` +17.1% RSS from the ~20 transitive deps its `[client,server]` extras pull in. Cutting the extras broke `@mcp.tool()` at runtime. Anthropic's `mcp 2.x` is the direct upstream reference — no third-party intermediary, no dependency bloat. Full details in the [v4.6.0 changelog entry](#v460-2026-07-30--mcp-spec-2026-07-28-via-anthropic-tier-1-sdk-mcp-2x) and closed PR #134.
|
|
53
67
|
|
|
54
68
|
### Search Performance & Output Quality (v4.2.0)
|
|
55
69
|
|
|
@@ -1400,6 +1414,14 @@ Common issues:
|
|
|
1400
1414
|
|
|
1401
1415
|
### Unreleased
|
|
1402
1416
|
|
|
1417
|
+
### v4.7.0 (2026-07-31) — BM25 Fragment Query Support
|
|
1418
|
+
|
|
1419
|
+
- **FIX (retrieval)**: BM25 tokenizer now emits **sub-tokens** for hyphenated alphanumeric-code composites, so fragment queries no longer silently return `NO_RESULTS`. Before v4.7.0, `MDR-AD002` was indexed as a single token `mdr-ad002`; queries like `AD002`, `MDR`, `CS005` returned zero even when the composite lived in the corpus. This is not a bug specific to MDR — it hit every hyphenated code taxonomy in typical infosec / doc corpora (`MDR-*`, `CVE-*`, `ADR-*`, `MS17-*`, `MDR-Custom001-xxxx`). The tokenizer now emits both the composite token AND its sub-parts of length ≥ 2 (`mdr-ad002` → `["mdr-ad002", "mdr", "ad002"]`). IDF preserves ranking — composite matches still rank above fragment matches because the composite is rarer. **Heuristic (perf-safety)**: sub-token expansion is triggered ONLY when the composite contains at least one digit — so `pass-the-hash`, `state-of-the-art`, and other natural-language hyphenated phrases stay as single tokens (expanding them would flood the inverted index with stop-word-like sub-parts and hurt concurrent-query throughput). (#140)
|
|
1420
|
+
- **NEW (tests)**: `tests/test_bm25_tokenizer_fragment.py` — 25 tests across 4 classes covering unit tokenizer behavior, end-to-end fragment matching, multi-doc disambiguation, and the 5 query patterns explicitly reported (`MDR-AD019`, `MDR-Custom001-xxxx`, `MDR`, `AD019`, `CS005`). Includes retrocompat sentinel + IDF ranking invariant. Baseline: 314 → 339.
|
|
1421
|
+
- **UPGRADE NOTE**: run `reindex_documents(force=True)` once after upgrade to rebuild the BM25 inverted index with the new sub-token emission. ChromaDB vectors are untouched. Expect a **~30–50% increase in BM25 index memory** (measured +32.5% on synthetic corpus) — negligible for typical corpora, worth reviewing for deployments with >100K docs.
|
|
1422
|
+
- **KNOWN LIMITATION**: alphanumeric-glued tokens without separators (`HARDLAB11`, `6a635623e114b8...`) still require exact match — no sub-token expansion possible without character n-grams (5-10× index overhead). Tracked as follow-up.
|
|
1423
|
+
- **VERSION**: 4.6.0 → **4.7.0** (MINOR — tokenization behavior change + reindex requirement, though no API/config break).
|
|
1424
|
+
|
|
1403
1425
|
### v4.6.0 (2026-07-30) — MCP spec 2026-07-28 via Anthropic Tier 1 SDK (mcp 2.x)
|
|
1404
1426
|
|
|
1405
1427
|
- **NEW (protocol)**: adopt the [MCP spec `2026-07-28`](https://blog.modelcontextprotocol.io/posts/2026-07-28/) — stateless request/response core, per-request `_meta.io.modelcontextprotocol/protocolVersion` + `clientCapabilities`, `serverInfo` on responses, retirement of the `initialize`/`initialized` handshake and the `Mcp-Session-Id` header. The MCP client Claude Code (and every Tier 1 client) negotiates the spec version per request, so this release stays backwards-compatible for clients speaking earlier spec revisions.
|
|
@@ -696,9 +696,30 @@ class BM25Index:
|
|
|
696
696
|
self._index_built: bool = False
|
|
697
697
|
|
|
698
698
|
def _tokenize(self, text: str) -> List[str]:
|
|
699
|
-
"""
|
|
699
|
+
"""Tokenize: lowercase, split on non-alphanumeric, emit composite + sub-tokens.
|
|
700
|
+
|
|
701
|
+
For alphanumeric-code composites (containing at least one digit — e.g.
|
|
702
|
+
"mdr-ad002", "cve-2024-1234", "ms17-010"), emit both the composite token
|
|
703
|
+
AND its sub-parts of length >= 2. This enables fragment queries ("AD002",
|
|
704
|
+
"CVE", "010") to match while IDF preserves exact-match ranking (composite
|
|
705
|
+
is rarer).
|
|
706
|
+
|
|
707
|
+
Natural-language hyphenated words (e.g. "pass-the-hash", "state-of-the-art")
|
|
708
|
+
are kept as single tokens — expanding them would flood the inverted index
|
|
709
|
+
with high-frequency stop-word-like sub-parts and hurt query throughput
|
|
710
|
+
without helping recall for typical use cases.
|
|
711
|
+
"""
|
|
700
712
|
text_lower = text.lower()
|
|
701
|
-
|
|
713
|
+
composite_tokens = re.findall(r"[a-z0-9][-a-z0-9]*[a-z0-9]|[a-z0-9]", text_lower)
|
|
714
|
+
tokens: List[str] = []
|
|
715
|
+
for tok in composite_tokens:
|
|
716
|
+
tokens.append(tok)
|
|
717
|
+
# Only expand codes (composites containing at least one digit).
|
|
718
|
+
# Skips natural-language phrases like "pass-the-hash".
|
|
719
|
+
if "-" in tok and any(c.isdigit() for c in tok):
|
|
720
|
+
for part in tok.split("-"):
|
|
721
|
+
if len(part) >= 2:
|
|
722
|
+
tokens.append(part)
|
|
702
723
|
return tokens
|
|
703
724
|
|
|
704
725
|
def expand_query(self, query: str) -> str:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "knowledge-rag"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.7.0"
|
|
8
8
|
description = "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 13 MCP Tools + 20 Format Parsers. Zero external servers."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|