Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e39e00a2c0 | |||
| d078af9ad3 | |||
| b3dce188e1 | |||
| 0dc3065979 |
@@ -4,3 +4,6 @@ __pycache__/
|
|||||||
engine/data/
|
engine/data/
|
||||||
|
|
||||||
TMP/
|
TMP/
|
||||||
|
.env
|
||||||
|
.venv/
|
||||||
|
test_mcp_client.py
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Start the MCP server
|
||||||
|
|
||||||
|
The compose files include a `kb-mcp` service alongside the engine. Set `KB_MCP_API_KEY` to require Bearer token auth from connecting agents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
KB_API_KEY=your-engine-key KB_MCP_API_KEY=your-agent-key \
|
||||||
|
docker compose -f engine/compose.nvidia.yaml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Or run the MCP server standalone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name kb-mcp \
|
||||||
|
-p 3000:3000 \
|
||||||
|
-e KB_ENGINE_URL=http://your-engine-host:8000 \
|
||||||
|
-e KB_API_KEY=your-engine-key \
|
||||||
|
-e KB_MCP_API_KEY=your-agent-key \
|
||||||
|
--restart unless-stopped \
|
||||||
|
docker.dcglab.co.uk/dcg/kb/mcp:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## MCP tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|---|---|
|
||||||
|
| `kb_search` | Hybrid search with optional collection/tag/type filters |
|
||||||
|
| `kb_addnote` | Add a text note (queued for async ingestion) |
|
||||||
|
| `kb_update_note` | Update an existing note in place |
|
||||||
|
| `kb_get` | Get document details by ID or source path |
|
||||||
|
| `kb_status` | Engine health and statistics |
|
||||||
|
| `kb_jobs` | Ingestion queue status |
|
||||||
|
| `kb_upload_start` | Start a chunked file upload |
|
||||||
|
| `kb_upload_chunk` | Upload a base64-encoded file chunk |
|
||||||
|
| `kb_upload_finish` | Finish upload and submit for ingestion |
|
||||||
|
|
||||||
|
## Collections
|
||||||
|
|
||||||
|
The MCP server supports **collections** — scoped document namespaces implemented via tag conventions. Use these to separate agent memory from user documents:
|
||||||
|
|
||||||
|
- `documents` (default) — user-facing documents
|
||||||
|
- `memory` — agent memory and preferences
|
||||||
|
- `workspace` — working context
|
||||||
|
|
||||||
|
Tools accept a `collection` parameter. The MCP server translates this to `collection:<name>` tags on the engine, and strips them from responses so agents see a clean `"collection": "memory"` field.
|
||||||
|
|
||||||
|
## MCP server configuration
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `KB_ENGINE_URL` | `http://localhost:8000` | Engine API URL |
|
||||||
|
| `KB_API_KEY` | (none) | Engine API key |
|
||||||
|
| `KB_MCP_API_KEY` | (none) | Bearer token required from agents (disabled if unset) |
|
||||||
|
| `KB_MCP_PORT` | `3000` | Port to listen on |
|
||||||
|
|
||||||
|
## Connecting AI coding tools
|
||||||
|
|
||||||
|
The kb MCP server uses **Streamable HTTP** transport at `http://your-host:3000/mcp`. Below are configuration examples for popular AI coding tools.
|
||||||
|
|
||||||
|
### Claude Code (CLI / Desktop / Web)
|
||||||
|
|
||||||
|
Add the server to your project or user settings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude mcp add kb-server --transport http http://localhost:3000/mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Or add it manually to `.claude/settings.json` (project) or `~/.claude/settings.json` (global):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"kb-server": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### VS Code (GitHub Copilot)
|
||||||
|
|
||||||
|
Add to your `.vscode/settings.json` (workspace) or user settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcp": {
|
||||||
|
"servers": {
|
||||||
|
"kb-server": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or add to `.vscode/mcp.json` in your workspace:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": {
|
||||||
|
"kb-server": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cursor
|
||||||
|
|
||||||
|
Add to `.cursor/mcp.json` in your project root:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"kb-server": {
|
||||||
|
"type": "streamable-http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windsurf
|
||||||
|
|
||||||
|
Add to `~/.codeium/windsurf/mcp_config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"kb-server": {
|
||||||
|
"serverUrl": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### JetBrains IDEs (IntelliJ, WebStorm, PyCharm, etc.)
|
||||||
|
|
||||||
|
Add to `.junie/mcp.json` in your project root, or configure via **Settings > Tools > AI Assistant > MCP Servers**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"servers": {
|
||||||
|
"kb-server": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "http://localhost:3000/mcp",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer your-agent-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -2,16 +2,19 @@
|
|||||||
|
|
||||||
Personal knowledge base with hybrid search (full-text + semantic vector search).
|
Personal knowledge base with hybrid search (full-text + semantic vector search).
|
||||||
|
|
||||||
v2 uses a client-server architecture: a **FastAPI engine** running in Docker (with optional GPU acceleration) and a lightweight **Go CLI client** that talks to it over HTTP.
|
Client-server architecture: a **FastAPI engine** running in Docker (with optional GPU acceleration), a lightweight **Go CLI client**, and an **MCP server** for native agent integration.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
Go CLI (kb) ──HTTP──▶ FastAPI Engine (Docker) ──▶ SQLite + GPU
|
Go CLI (kb) ──HTTP──▶ FastAPI Engine (Docker) ──▶ SQLite + GPU
|
||||||
|
▲
|
||||||
|
MCP Agents ──MCP/HTTP──▶ MCP Server (Docker) ──┘
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Engine**: Keeps the embedding model warm in memory. Handles search, ingestion, and document management via REST API. Runs in Docker with NVIDIA GPU, AMD GPU (ROCm), or CPU-only support.
|
- **Engine**: Keeps the embedding model warm in memory. Handles search, ingestion, document management, and note mutation via REST API. Runs in Docker with NVIDIA GPU, AMD GPU (ROCm), or CPU-only support.
|
||||||
- **Client**: Single static Go binary. No Python, no ML dependencies, instant startup. Talks to the engine over HTTP.
|
- **Client**: Single static Go binary. No Python, no ML dependencies, instant startup. Talks to the engine over HTTP.
|
||||||
|
- **MCP Server**: Exposes kb operations as native MCP tools over Streamable HTTP. Runs as a separate Docker container alongside the engine. Supports collections for scoping agent memory vs user documents.
|
||||||
- **Storage**: Single SQLite database with FTS5 (keyword search) and sqlite-vec (vector search). Portable via bind mount — just copy the data directory between hosts.
|
- **Storage**: Single SQLite database with FTS5 (keyword search) and sqlite-vec (vector search). Portable via bind mount — just copy the data directory between hosts.
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
@@ -84,7 +87,7 @@ Check [releases](https://gitea.dcglab.co.uk/steve/kb/releases) for the latest cl
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Set the version tag
|
# Set the version tag
|
||||||
TAG=client-v2.1.0
|
TAG=client-v3.0.0
|
||||||
|
|
||||||
# Linux (amd64)
|
# Linux (amd64)
|
||||||
curl -L -o kb https://gitea.dcglab.co.uk/steve/kb/releases/download/${TAG}/kb-linux-amd64
|
curl -L -o kb https://gitea.dcglab.co.uk/steve/kb/releases/download/${TAG}/kb-linux-amd64
|
||||||
@@ -135,6 +138,9 @@ kb jobs
|
|||||||
kb search "how to install git"
|
kb search "how to install git"
|
||||||
kb search "deploy process" --tags ops --type pdf
|
kb search "deploy process" --tags ops --type pdf
|
||||||
|
|
||||||
|
# Update a note in place
|
||||||
|
kb updatenote 42 "revised note content"
|
||||||
|
|
||||||
# Manage
|
# Manage
|
||||||
kb list
|
kb list
|
||||||
kb info 1
|
kb info 1
|
||||||
@@ -182,6 +188,12 @@ KB_DATA_PATH=~/kb-data docker compose -f compose.nvidia.yaml up -d
|
|||||||
|
|
||||||
Data is device-agnostic — you can ingest on NVIDIA and serve from AMD or CPU (or any combination) with the same data directory.
|
Data is device-agnostic — you can ingest on NVIDIA and serve from AMD or CPU (or any combination) with the same data directory.
|
||||||
|
|
||||||
## Claude Code skill
|
## MCP server (agent integration)
|
||||||
|
|
||||||
This tool is designed to be wrapped as a Claude Code skill. See `SKILL.md` for the skill definition.
|
The MCP server exposes kb operations as native MCP tools over Streamable HTTP, so agents can search, add notes, upload files, and manage documents without shelling out to the CLI. Includes setup guides for Claude Code, VS Code, Cursor, Windsurf, and JetBrains IDEs.
|
||||||
|
|
||||||
|
See **[MCP.md](MCP.md)** for full details — server setup, available tools, collections, configuration, and client examples.
|
||||||
|
|
||||||
|
## Agent skill
|
||||||
|
|
||||||
|
If you are restricted from using MCP server, or you just prefer to utilise Agent SKILLS, please also see `SKILL.md` for the skill definition.
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ func (c *Client) checkEngineVersion() {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return // auth error or other issue — let the actual request surface it
|
||||||
|
}
|
||||||
|
|
||||||
var status struct {
|
var status struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -87,7 +87,12 @@ async def _ensure_exclusive_collection(doc_id: int, collection: str) -> None:
|
|||||||
|
|
||||||
mcp = FastMCP(
|
mcp = FastMCP(
|
||||||
"kb",
|
"kb",
|
||||||
instructions="Knowledge base MCP server. Provides tools for searching, adding, and managing documents and notes.",
|
instructions=(
|
||||||
|
"Knowledge base MCP server. Provides tools for searching, adding, and "
|
||||||
|
"managing documents and notes. This server requires Bearer token "
|
||||||
|
"authentication — all requests are authenticated via the Authorization "
|
||||||
|
"header at the HTTP transport layer."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -218,6 +223,7 @@ async def kb_status() -> str:
|
|||||||
database size, and ingestion queue state.
|
database size, and ingestion queue state.
|
||||||
"""
|
"""
|
||||||
result = engine.get_status()
|
result = engine.get_status()
|
||||||
|
result["authenticated"] = bool(config.KB_MCP_API_KEY)
|
||||||
return json.dumps(result, indent=2)
|
return json.dumps(result, indent=2)
|
||||||
|
|
||||||
|
|
||||||
@@ -323,10 +329,8 @@ class BearerAuthMiddleware(BaseHTTPMiddleware):
|
|||||||
return await call_next(request)
|
return await call_next(request)
|
||||||
|
|
||||||
auth_header = request.headers.get("authorization", "")
|
auth_header = request.headers.get("authorization", "")
|
||||||
if auth_header.startswith("Bearer "):
|
if auth_header.startswith("Bearer ") and auth_header[7:] == config.KB_MCP_API_KEY:
|
||||||
token = auth_header[7:]
|
return await call_next(request)
|
||||||
if token == config.KB_MCP_API_KEY:
|
|
||||||
return await call_next(request)
|
|
||||||
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=401,
|
status_code=401,
|
||||||
|
|||||||
Reference in New Issue
Block a user