Content
# Tool List
Self-hosted knowledge base TypeScript/Node monorepo. Documents are chunked, vectorized, and stored in local Chroma; AI client performs semantic search through **MCP** (stdio or Streamable HTTP), and documents are uploaded and managed through **REST API / CLI / Web Management Interface**.
## Overview
| Capability | Status |
| --- | --- |
| Document ingestion (txt / markdown / text-layer PDF) | ✅ |
| CherryIn embedding (`qwen/qwen3-embedding-8b`) | ✅ |
| Local Chroma vector storage | ✅ |
| REST API (upload, list, search, health check) | ✅ |
| MCP tool `search_knowledge` (stdio + HTTP) | ✅ |
| Web management interface, JWT login, optional API Key (CLI/service) | ✅ Phase 4–8 |
## Architecture
```
┌─────────────┐ ingest ┌──────────────┐ embed ┌─────────┐
│ CLI / REST │ ──────────────► │ @kb/core │ ─────────────► │ Chroma │
│ (backend) │ │ Ingestion │ │ :8000 │
└─────────────┘ └──────────────┘ └────▲────┘
│
┌─────────────┐ search ┌──────────────┐ │
│ MCP Client │ ──────────────► │ SearchService│ ──────────────────┘
│ (stdio/HTTP)│ │ (@kb/core) │
└─────────────┘ └──────────────┘
```
| Port | Service | Description |
| --- | --- | --- |
| 8000 | Chroma | Vector database (HTTP sidecar) |
| 3000 | Backend | Fastify REST API + Swagger UI; hosts Web SPA in production/static mode |
| 5173 | Web (dev) | Vite development server (HMR); proxies `/api` to `:3000` |
| 3100 | MCP HTTP | Streamable HTTP, `POST /mcp` |
| — | MCP stdio | Local client, no port |
MCP layer is **only responsible for search**; management operations like ingestion and deletion are done through Backend or CLI.
## Requirements
- **Node.js** 24.x
- **pnpm** 11.x
- **Python 3** (for Chroma on Windows: `pnpm setup:chroma` installs `chromadb`)
- **CherryIn API Key** ([open.cherryin.cc](https://open.cherryin.cc))
## Quick Start
### 1. Install Dependencies
```bash
git clone https://github.com/laneinrain/kb-mcp-server.git
cd kb-mcp-server
pnpm install
```
### 2. Configure Environment Variables
```bash
cp .env.example .env
# Edit .env, at least fill in CHERRYIN_API_KEY
```
### 3. Install Chroma (recommended for Windows)
```bash
pnpm setup:chroma
```
### 4. Build and Start Development Environment
```bash
pnpm build
pnpm dev
```
`pnpm dev` starts Chroma, Backend (`:3000`), MCP HTTP (`:3100`), and **Web dynamic frontend** (Vite `:5173`). Open **http://localhost:5173** in your browser for daily development.
### 5. Ingest Documents
```bash
pnpm ingest path/to/document.pdf
pnpm ingest path/to/notes.md --collection default
```
Or upload through REST:
```bash
curl -F "file=@./scripts/fixtures/sample.md" http://127.0.0.1:3000/api/v1/documents
```
### 6. Verify Search
REST:
```bash
curl -X POST http://127.0.0.1:3000/api/v1/search \
-H "Content-Type: application/json" \
-d '{"query": "your question", "topK": 5}'
```
Health check:
```bash
curl http://127.0.0.1:3000/health
curl http://127.0.0.1:3000/health/chroma
curl http://127.0.0.1:3000/health/embeddings
```
API documentation: http://127.0.0.1:3000/docs
## Web Management Interface: Dynamic vs Static Frontend
Web application (`@kb/web`) has two modes:
| | **Dynamic Frontend (dev)** | **Static Frontend (prod/integrated)** |
| --- | --- | --- |
| **What** | Vite development server with HMR | `vite build` generates static files, hosted by **Backend** |
| **Access** | http://localhost:5173 | http://127.0.0.1:3000 |
| **API** | Vite proxies `/api` to Backend `:3000` | Same port as REST API (Backend hosts API + SPA) |
| **When enabled** | Default with `pnpm dev` | `NODE_ENV=production` or `SERVE_WEB=true` |
```
Development (dynamic):
Browser → :5173 (Vite) ──proxy /api──→ :3000 (Backend)
Production/static:
Browser → :3000 (Backend)
├── /api/v1/* REST
└── /* apps/web/dist static SPA
```
### Dynamic Frontend (dev, recommended)
```bash
# Full-stack: Chroma + Backend + MCP + Web (Vite :5173)
pnpm dev
# Only Web dynamic frontend (Backend running on :3000)
pnpm dev:web
# Equivalent to:
pnpm --filter @kb/web dev
```
Open **http://localhost:5173** in your browser to log in and use the management interface.
### Static Frontend (built, hosted by Backend)
```bash
# Build Web static assets → apps/web/dist/
pnpm --filter @kb/web build
# Full build (turbo builds @kb/web then @kb/backend)
pnpm build
```
**Host API + static page on Backend:**
```bash
# Method A: Verify single-port deployment in development environment (PowerShell)
pnpm --filter @kb/web build
$env:SERVE_WEB="true"; pnpm --filter @kb/backend dev
# Method B: Production mode (NODE_ENV=production also hosts static page)
pnpm build
$env:NODE_ENV="production"; pnpm --filter @kb/backend dev
```
On Linux/macOS, replace `$env:SERVE_WEB="true"` with `SERVE_WEB=true`.
Access **http://127.0.0.1:3000** (page and API on port 3000).
> By default, only `pnpm --filter @kb/backend dev` runs and `SERVE_WEB` is not set, `:3000` **only provides REST API**, not the Web interface.
### Auxiliary Commands (optional)
```bash
# Preview built dist (Vite built-in, default :5173, usually without /api proxy)
pnpm --filter @kb/web preview
```
### Scenario Checklist
| Scenario | Command | Open in browser |
| --- | --- | --- |
| Modify Web UI, local upload/search test | `pnpm dev` | http://localhost:5173 |
| Verify single-port deployment | `pnpm --filter @kb/web build` + `SERVE_WEB=true` start backend | http://127.0.0.1:3000 |
| Formal build | `pnpm build` | Production environment Backend listening on 3000 |
## MCP Configuration
MCP exposes a single tool **`search_knowledge`**:
| Parameter | Type | Description |
| --- | --- | --- |
| `query` | string | Search query (required, 1–2000 characters) |
| `top_k` | number | Return count, 1–10, default 5 |
| `collection` | string | Collection name, default `default` |
### Method 1: stdio (Cursor local, recommended)
**Recommended: Use project-level configuration** (already included in [.cursor/mcp.json](.cursor/mcp.json), no absolute path):
```json
{
"mcpServers": {
"kb-mcp-server": {
"command": "pnpm",
"args": ["--filter", "@kb/mcp-server", "dev:stdio"],
"env": { "DOTENV_CONFIG_QUIET": "true" }
}
}
}
```
Open the repository root directory in Cursor; the workspace root directory is `cwd`, which automatically loads the root directory `.env`.
**Production/built** (need to `pnpm --filter @kb/mcp-server build` first):
```json
{
"mcpServers": {
"kb-mcp-server": {
"command": "node",
"args": ["apps/mcp-server/dist/stdio.js"],
"env": { "DOTENV_CONFIG_QUIET": "true" }
}
}
}
```
> **Note**
>
> - Place configuration in project `.cursor/mcp.json`, not `D:/...` or `node.exe` absolute path.
> - Global `~/.cursor/mcp.json` only suitable for HTTP method without path (see Method 2); stdio uses project-level configuration.
> - If Cursor cannot find `pnpm`/`node` on Windows: add Node installation directory to system PATH or start Cursor from an administrator-run terminal.
### Method 2: Streamable HTTP (remote / multi-client)
Run `pnpm dev` or start MCP HTTP separately:
```bash
pnpm --filter @kb/mcp-server dev
```
Cursor MCP configuration example:
```json
{
"mcpServers": {
"kb-mcp-server": {
"url": "http://127.0.0.1:3100/mcp"
}
}
}
```
> Directly accessing `GET /mcp` in the browser returns 404, which is expected behavior; MCP only accepts `POST /mcp`.
## Environment Variables
Complete example in [.env.example](.env.example). Common items:
| Variable | Default | Description |
| --- | --- | --- |
| `CHERRYIN_API_KEY` | — | CherryIn embedding API key (required) |
| `CHROMA_HOST` / `CHROMA_PORT` | `localhost` / `8000` | Chroma address |
| `BACKEND_HOST` / `BACKEND_PORT` | `127.0.0.1` / `3000` | REST API |
| `MCP_HTTP_HOST` / `MCP_HTTP_PORT` | `127.0.0.1` / `3100` | MCP HTTP |
| `DEFAULT_COLLECTION` | `default` | Default vector collection |
| `EMBEDDING_MODEL` | `qwen/qwen3-embedding-8b` | Embedding model |
| `CHUNK_SIZE` / `CHUNK_OVERLAP` | `1024` / `154` | Chunking parameters |
| `DATA_DIR` | `./data` | Local data directory (SQLite, upload cache) |
| `AUTH_ENABLED` | `false` | Global API Key (CLI/service access) |
| `USER_AUTH_ENABLED` | `false` | Web login + JWT; independent of `AUTH_ENABLED` |
### Authentication Matrix (Phase 8)
| Client | Credential | Document scope |
| --- | --- | --- |
| **Web Management Interface** | JWT (`POST /api/v1/auth/login`) | Own documents + system-shared historical documents |
| **CLI / Automation** | `AUTH_ENABLED` + `API_KEY` (Bearer) | Global (service account) |
| **MCP** | None (no change in this phase) | Search not limited by user isolation |
When `USER_AUTH_ENABLED=true`, Web must log in with JWT; CLI needs to set both `AUTH_ENABLED=true` and `API_KEY` to pass REST ingestion. User registration page (WEB-02) not implemented yet, login creates user on the fly.
**Do not commit `.env` to Git.**
## REST API Summary
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/health` | Service alive |
| `GET` | `/health/chroma` | Chroma connectivity |
| `GET` | `/health/embeddings` | Embedding API connectivity |
| `POST` | `/api/v1/documents` | Upload document (multipart) |
| `GET` | `/api/v1/documents` | List ingested documents |
| `GET` | `/api/v1/documents/:id` | Document details |
| `DELETE` | `/api/v1/documents/:id` | Delete document and vector |
| `POST` | `/api/v1/search` | Semantic search |
## Project Structure
```
kb-mcp-server/
├── apps/
│ ├── backend/ # Fastify REST API (optional static Web hosting)
│ ├── web/ # React management interface (Vite)
│ ├── cli/ # Command-line ingestion
│ └── mcp-server/ # MCP stdio + Streamable HTTP
├── packages/
│ ├── auth/ # User authentication (JWT / Mock CAS)
│ ├── config/ # Environment variables and constants
│ └── core/ # Ingestion, search, Chroma, embedding client
├── scripts/
│ ├── ingest.ts # CLI ingestion
│ ├── start-chroma.ts # Start Chroma sidecar
│ └── wait-for-chroma.ts
├── .env.example
└── package.json # pnpm workspace root
```
## Development and Testing
```bash
# Full build
pnpm build
# Full test
pnpm test
# Start individual services
pnpm --filter @kb/backend dev
pnpm dev:web # Web dynamic frontend :5173
pnpm --filter @kb/mcp-server dev # HTTP :3100
pnpm --filter @kb/mcp-server dev:stdio # stdio
# Wait for Chroma readiness
pnpm wait:chroma
```
## Roadmap
- **Phase 1–8** (completed): platform foundation, REST search, MCP, Web management, user JWT multi-tenancy
- **Phase 9+** (planned): filename content hash deduplication, etc.
## License
Open-source license not specified yet. If you want to contribute, add a `LICENSE` file.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available