4 Commits

Author SHA1 Message Date
steve 75e4a0cf73 Bump engine version to 3.2.4 2026-05-15 18:37:12 +01:00
steve 753c641e72 Switch container registry to Gitea built-in (gitea.dcglab.co.uk/steve/kb)
The standalone Registry v2 host (docker.dcglab.co.uk, briefly registry.dcglab.co.uk)
is being scrapped. Move all kb images to Gitea's built-in container registry.
2026-05-15 18:35:20 +01:00
steve 45e2c5ce91 Bump engine version to 3.2.3 2026-05-15 18:22:08 +01:00
steve e6e91f1d5c Clarify hybrid semantic + full-text search in MCP descriptions
Agents were misreading kb_search as keyword-only because the vector/semantic
component was only mentioned in the negative ("fts_only: no vector similarity").
Lead with hybrid semantic + BM25 + RRF in the server instructions, kb_search
docstring, and MCP.md so agents recognise it as a vector search tool.
2026-05-15 18:19:42 +01:00
7 changed files with 34 additions and 20 deletions
+1 -1
View File
@@ -61,7 +61,7 @@ curl http://localhost:8000/api/v1/status | jq .version
### Docker images ### Docker images
Images are pushed to `docker.dcglab.co.uk/dcg/kb/engine` with tags: Images are pushed to `gitea.dcglab.co.uk/steve/kb/engine` with tags:
- `engine-v2.0.6-nvidia` / `engine-v2.0.6-cpu` — versioned - `engine-v2.0.6-nvidia` / `engine-v2.0.6-cpu` — versioned
- `latest-nvidia` / `latest-cpu` — latest release - `latest-nvidia` / `latest-cpu` — latest release
+3 -3
View File
@@ -1,6 +1,6 @@
# MCP Server (Agent Integration) # MCP Server (Agent Integration)
The MCP server exposes kb operations as native MCP tools, so agents can search, add notes, upload files, and manage documents without shelling out to the CLI. The MCP server exposes kb operations as native MCP tools, so agents can search, add notes, upload files, and manage documents without shelling out to the CLI. `kb_search` is hybrid: dense vector embeddings (semantic similarity) fused with BM25 full-text ranking via Reciprocal Rank Fusion, so agents can ask natural-language questions and find conceptually related content even when the exact words don't match.
## Start the MCP server ## Start the MCP server
@@ -20,14 +20,14 @@ docker run -d --name kb-mcp \
-e KB_API_KEY=your-engine-key \ -e KB_API_KEY=your-engine-key \
-e KB_MCP_API_KEY=your-agent-key \ -e KB_MCP_API_KEY=your-agent-key \
--restart unless-stopped \ --restart unless-stopped \
docker.dcglab.co.uk/dcg/kb/mcp:latest gitea.dcglab.co.uk/steve/kb/mcp:latest
``` ```
## MCP tools ## MCP tools
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `kb_search` | Hybrid search with optional tag/type filters | | `kb_search` | Hybrid semantic (vector) + full-text search with tag/type filters |
| `kb_addnote` | Add a text note (queued for async ingestion) | | `kb_addnote` | Add a text note (queued for async ingestion) |
| `kb_update_note` | Update an existing note in place | | `kb_update_note` | Update an existing note in place |
| `kb_get` | Get document details by ID or source path | | `kb_get` | Get document details by ID or source path |
+2 -2
View File
@@ -33,7 +33,7 @@ docker run -d --name kb-engine \
-e KB_DEVICE=auto \ -e KB_DEVICE=auto \
-e KB_API_KEY=your-secret-key \ -e KB_API_KEY=your-secret-key \
--restart unless-stopped \ --restart unless-stopped \
docker.dcglab.co.uk/dcg/kb/engine:latest-nvidia gitea.dcglab.co.uk/steve/kb/engine:latest-nvidia
# CPU only (no GPU required — smaller image) # CPU only (no GPU required — smaller image)
docker run -d --name kb-engine \ docker run -d --name kb-engine \
@@ -42,7 +42,7 @@ docker run -d --name kb-engine \
-e KB_MODEL=all-MiniLM-L6-v2 \ -e KB_MODEL=all-MiniLM-L6-v2 \
-e KB_API_KEY=your-secret-key \ -e KB_API_KEY=your-secret-key \
--restart unless-stopped \ --restart unless-stopped \
docker.dcglab.co.uk/dcg/kb/engine:latest-cpu gitea.dcglab.co.uk/steve/kb/engine:latest-cpu
``` ```
Or use a compose file from the repo: Or use a compose file from the repo:
+1 -1
View File
@@ -1 +1 @@
3.2.2 3.2.4
+24 -10
View File
@@ -44,11 +44,16 @@ _transport_security = TransportSecuritySettings(
mcp = FastMCP( mcp = FastMCP(
"kb", "kb",
instructions=( instructions=(
"Knowledge base MCP server. Provides tools for searching, adding, and " "Knowledge base MCP server with hybrid semantic + full-text search. "
"managing documents and notes. Use tags to organise and filter documents " "kb_search uses dense vector embeddings (semantic similarity) fused with "
"(e.g. tag notes with 'agent:mybot' and filter searches by that tag). " "BM25 full-text ranking, so it finds conceptually related content even "
"This server requires Bearer token authentication — all requests are " "when the exact words don't match — agents can ask natural-language "
"authenticated via the Authorization header at the HTTP transport layer." "questions rather than guessing keywords. Also provides tools for adding "
"notes, uploading files, and managing documents and tags. Use tags to "
"organise and filter documents (e.g. tag notes with 'agent:mybot' and "
"filter searches by that tag). This server requires Bearer token "
"authentication — all requests are authenticated via the Authorization "
"header at the HTTP transport layer."
), ),
transport_security=_transport_security, transport_security=_transport_security,
) )
@@ -62,17 +67,25 @@ async def kb_search(
doc_type: str | None = None, doc_type: str | None = None,
fts_only: bool = False, fts_only: bool = False,
) -> str: ) -> str:
"""Search the knowledge base for relevant documents and notes. """Hybrid semantic (vector) + full-text search over the knowledge base.
Returns ranked chunks matching the query, with text content, relevance scores, Combines dense vector embeddings (semantic similarity — finds conceptually
and document metadata. related content even when the wording differs) with BM25 keyword ranking,
fused via reciprocal rank fusion. Because the search is semantic, you can
ask natural-language questions ("what did we decide about X?") rather than
guessing the exact keywords used in the source documents.
Returns ranked chunks matching the query, with text content, relevance
scores, and document metadata.
Args: Args:
query: The search query. Can be a natural language question or keywords. query: The search query a natural language question or keywords.
top: Maximum number of results to return (default 10). top: Maximum number of results to return (default 10).
tags: Filter results to documents with ALL of these tags. tags: Filter results to documents with ALL of these tags.
doc_type: Filter by document type (e.g. "note", "pdf", "markdown", "code"). doc_type: Filter by document type (e.g. "note", "pdf", "markdown", "code").
fts_only: If true, use only full-text search (no vector similarity). fts_only: Disable the vector/semantic component and use only BM25
keyword matching. Default false (hybrid mode). Set true only when
you need exact-string matching (e.g. an error code, identifier).
Tips for complex queries: Tips for complex queries:
- Consider expanding into 2-3 variant phrasings and calling this tool multiple - Consider expanding into 2-3 variant phrasings and calling this tool multiple
@@ -80,6 +93,7 @@ async def kb_search(
"pension revaluation rules" and "how are pensions revalued" to cast a wider net. "pension revaluation rules" and "how are pensions revalued" to cast a wider net.
- For precision, rerank the returned results using your own judgement based on - For precision, rerank the returned results using your own judgement based on
relevance to the original question. relevance to the original question.
- Call kb_status to see which embedding model is in use.
""" """
result = engine.search( result = engine.search(
query=query, query=query,
+1 -1
View File
@@ -65,7 +65,7 @@ The project SHALL provide Docker Compose files for single-command deployment. Co
#### Scenario: Pre-built image deployment #### Scenario: Pre-built image deployment
- **WHEN** an admin wants to use a pre-built engine image without building from source - **WHEN** an admin wants to use a pre-built engine image without building from source
- **THEN** the engine release notes SHALL include the exact `docker pull` command with the versioned tag (e.g. `docker.dcglab.co.uk/dcg/kb/engine:engine-v2.1.0-nvidia`) - **THEN** the engine release notes SHALL include the exact `docker pull` command with the versioned tag (e.g. `gitea.dcglab.co.uk/steve/kb/engine:engine-v2.1.0-nvidia`)
#### Scenario: MCP allowed hosts in Compose #### Scenario: MCP allowed hosts in Compose
- **WHEN** the kb-mcp service is defined in a Compose file - **WHEN** the kb-mcp service is defined in a Compose file
+2 -2
View File
@@ -15,8 +15,8 @@ ENGINE_DIR="$SCRIPT_DIR/engine"
VERSION_FILE="$ENGINE_DIR/VERSION" VERSION_FILE="$ENGINE_DIR/VERSION"
# Container registry # Container registry
REGISTRY="${REGISTRY:-docker.dcglab.co.uk}" REGISTRY="${REGISTRY:-gitea.dcglab.co.uk}"
IMAGE_ORG="${IMAGE_ORG:-dcg}" IMAGE_ORG="${IMAGE_ORG:-steve}"
IMAGE_BASE="${REGISTRY}/${IMAGE_ORG}/kb" IMAGE_BASE="${REGISTRY}/${IMAGE_ORG}/kb"
#────────────────────────────────────────────────────────────────────── #──────────────────────────────────────────────────────────────────────