MCP Knowledge Viz
by abtpst
README.md
# MCP Knowledge Viz
A knowledge-base chatbot with semantic search and interactive embedding visualisation, built as a hybrid of **REST microservices** (browser UI) and a proper **MCP stdio server** (Claude Desktop / Cursor integration).
Store facts in natural language, ask questions, and explore the embedding space in 2D (matplotlib) or interactive 3D (Plotly) — all backed by ChromaDB and SentenceTransformers.
---
## Architecture Overview

The system has two independent access paths that share the same business logic:
| Layer | Transport | Use case |
|---|---|---|
| **REST servers** (`run_all.sh`) | HTTP | Browser chatbot UI |
| **MCP stdio server** (`mcp_tools.py`) | stdin/stdout JSON-RPC | Claude Desktop, Cursor, any MCP client |
Both layers delegate to **`kb_core.py`** — the single module that owns the ChromaDB client and the SentenceTransformer embedder. Neither layer duplicates data-access logic.
### Key Design Principles
- **Single source of truth for data access** — only `kb_core.py` talks to ChromaDB. REST endpoints and MCP tools are thin wrappers.
- **No HTTP for MCP** — `mcp_tools.py` calls `kb_core` directly; the REST servers do not need to be running for an MCP client to use the tools.
- **SOLID / Pydantic structure** — the Visualization package uses typed Pydantic models at every boundary (`EmbeddingPayload`, `VisualizationRequest`, `ReducedEmbeddings`).
---
## Diagrams
### Module Structure

### QnA Request Flow (REST)

### Visualization Flow (2D + 3D)

### MCP Tools Flow (stdio)

### Regenerating diagrams
```bash
plantuml -tsvg docs/architecture/uml/*.puml -o ../images
plantuml -tpng docs/architecture/uml/*.puml -o ../images
```
---
## REST API Reference
### Knowledge Base Server — port 8000
Central data service. Also serves the chatbot browser UI.
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/chatbot` | Browser UI (two-column layout) |
| `POST` | `/add_fact` | Embed and store a fact in ChromaDB `facts` collection |
| `POST` | `/add_query` | Embed and store a query in ChromaDB `queries` collection |
| `POST` | `/search` | Semantic search — returns top-k facts + distances. Body: `{"query": "...", "n_results": 5}` |
| `GET` | `/get_all_embeddings` | Return all facts + queries with raw embeddings (used by Viz server) |
### QnA Server — port 8001
Thin HTTP wrapper. Calls the KB server; no direct DB access.
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/ask` | Stores query via `/add_query`, fetches matches via `/search`, returns ranked results |
### Visualization Server — port 8002
Generates embedding plots via PCA dimensionality reduction.
| Method | Endpoint | Query params | Returns |
|--------|----------|------|---------|
| `GET` | `/visualize_embeddings` | `dimensions` (2\|3), `show_radius`, `radius_neighbors`, `figure_width`, `figure_height`, `dpi` | `image/png` (matplotlib) |
| `GET` | `/visualize_embeddings_3d` | `show_radius`, `radius_neighbors`, `figure_width`, `figure_height`, `dpi` | `image/png` (matplotlib 3D) |
| `GET` | `/visualize_embeddings_interactive` | `show_radius`, `radius_neighbors` | `application/json` (Plotly figure) |
---
## MCP Tools Reference
`mcp_tools.py` is a **FastMCP stdio server**. Configure it in your MCP client and the three tools below appear automatically — no REST servers needed.
| Tool | Arguments | Description |
|------|-----------|-------------|
| `add_fact` | `text: str` | Embed and persist a fact in ChromaDB |
| `ask` | `query: str`, `n_results: int = 5` | Semantic search; also records the query for visualisation |
| `visualize_embeddings` | `show_radius: bool = true`, `radius_neighbors: int = 3` | Returns a Plotly 3D figure as a JSON string |
### Connecting to Claude Desktop / Cursor
Copy `mcp.json.example` to `mcp.json`, fill in your absolute paths, then copy the `mcpServers` block into your client's config file:
- **Claude Desktop**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Cursor**: `~/.cursor/mcp.json`
```jsonc
// mcp.json.example — fill in your local paths
{
"mcpServers": {
"knowledge-viz": {
"command": "/path/to/your/project/.venv/bin/python",
"args": ["-m", "mcp_servers.mcp_tools"],
"cwd": "/path/to/your/project"
}
}
}
```
> `mcp.json` is gitignored because it contains absolute local paths. Always edit `mcp.json.example` for committed changes.
---
## Getting Started
### Prerequisites
- Python 3.11+
- [PlantUML](https://plantuml.com/) (optional, only to regenerate diagrams)
### Setup
```bash
git clone <repository-url>
cd mcp-knowledge-viz
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
### Run the REST + browser UI stack
```bash
chmod +x run_all.sh
./run_all.sh
```
Starts three servers:
| Server | Port | Role |
|--------|------|------|
| Knowledge Base | 8000 | Data + chatbot UI |
| QnA | 8001 | Question answering |
| Visualization | 8002 | Embedding plots |
Open **http://127.0.0.1:8000/chatbot** in your browser.
### Visualisation tuning parameters
| Parameter | Default | Range | Effect |
|-----------|---------|-------|--------|
| `dimensions` | `2` | `2` or `3` | PCA target dimensions |
| `show_radius` | `true` | bool | Draw search-radius circle / sphere around latest query |
| `radius_neighbors` | `5` | 1–50 | Neighbour count used to compute the radius |
| `figure_width` | `16` | float | Matplotlib figure width (inches) |
| `figure_height` | `10` | float | Matplotlib figure height (inches) |
| `dpi` | `160` | int | Matplotlib output resolution |
| `n_results` | `5` | 1–50 | Facts returned per search |
---
## Project Structure
```
mcp-knowledge-viz/
├── app/
│ ├── static/
│ │ ├── chatbot.css # Two-column layout, vis viewport
│ │ └── chatbot.js # Fetch facts/QnA, Plotly 3D, spinner
│ └── templates/
│ └── chatbot.html # Bootstrap 5 two-column UI
├── docs/
│ └── architecture/
│ ├── images/ # Generated SVG + PNG diagrams
│ └── uml/ # PlantUML sources
├── mcp_servers/
│ ├── kb_core.py # ★ Shared ChromaDB + embedder logic
│ ├── knowledge_base_server.py # REST :8000 — delegates to kb_core
│ ├── qna_server.py # REST :8001 — HTTP wrapper
│ ├── visualization_server.py # REST :8002 — delegates to visualization/
│ ├── mcp_tools.py # ★ MCP stdio server (add_fact, ask, visualize)
│ └── visualization/
│ ├── models.py # Pydantic models
│ ├── kb_client.py # HTTP client → KB server
│ ├── reducer.py # PCA 2D/3D
│ ├── renderer.py # matplotlib (2D/3D static PNG)
│ ├── plotly_renderer.py # Plotly interactive 3D JSON
│ └── service.py # Orchestrator
├── chroma_db/ # Persistent vector store (gitignored)
├── mcp.json # Local MCP config (gitignored)
├── mcp.json.example # Template — commit this, not mcp.json
├── run_all.sh # Start all three REST servers
└── requirements.txt
```
---
## Tech Stack
| Concern | Library |
|---------|---------|
| REST framework | FastAPI + uvicorn |
| Vector store | ChromaDB (persistent) |
| Embeddings | SentenceTransformers `all-MiniLM-L6-v2` |
| Dimensionality reduction | scikit-learn PCA |
| 2D/3D static plots | matplotlib |
| Interactive 3D plots | Plotly (JS CDN + Python) |
| MCP server | `mcp[cli]` FastMCP |
| HTTP client | httpx |
| Frontend | Bootstrap 5, vanilla JS |This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues