# CLAUDE.md — MCP Context Hub
## Project Overview
MCP Context Hub is a local MCP server (Node.js + TypeScript) providing context optimization, RAG memory with semantic search, semantic cache, text compression, and sub-MCP proxy. It runs on a machine with RTX 3060 Ti + Ollama and serves as a single MCP endpoint for Claude.
## Commands
```bash
npm run dev # Start HTTP server on :3100
npm run dev:stdio # Start in stdio mode (local MCP testing)
npm test # Run all tests (vitest)
npm run build # Compile TypeScript to dist/
npm run typecheck # Type-check without emitting
npm run health # Health check script
```
To start with sub-MCP proxy:
```bash
PROXY_SERVERS='{"filesystem":{"command":"node","args":["node_modules/@modelcontextprotocol/server-filesystem/dist/index.js","/tmp"]}}' npm run dev
```
## Environment
- **Node.js 20** installed via `~/miniforge3/bin/conda` — PATH needs `~/miniforge3/bin`
- **uv/uvx** installed at `~/.local/bin`
- **Ollama** running locally with models: `llama3.1:8b-instruct-q4_K_M`, `qwen2.5:7b-instruct-q4_K_M`, `nomic-embed-text:v1.5`
- Server port: **3100**
- Database: SQLite at `./data/context-hub.db` (WAL mode)
## Architecture
```
src/
index.ts — Entry point, init, graceful shutdown
config.ts — Env config loader (.env)
db/ — SQLite connection, migrations, cosine similarity
server/ — McpServer, Express transport, session mgmt
middleware/ — Auth (Bearer), IP allowlist, audit logging
tools/ — 5 MCP tools (schemas + implementations)
services/ — Ollama client, vector store, FTS5, chunker, dedup, cache, proxy
utils/ — Logger (pino), metrics, retry, token estimator
types/ — TypeScript interfaces
tests/
unit/ — cosine, chunker, dedup, cache
integration/ — sqlite vector store
e2e/ — Express server
```
## Key Technical Details
- **Zod v4**: `z.record()` requires two args — `z.record(z.string(), z.unknown())`
- **MCP SDK v1.26**: `registerTool` inputSchema is a plain object `{ field: z.string() }`, NOT `z.object()`
- **StreamableHTTPServerTransport**: Clients must send `Accept: application/json, text/event-stream` header
- **FTS5 queries**: All non-alphanumeric characters are stripped before MATCH (see `text-search.ts`)
- **Embeddings**: `nomic-embed-text:v1.5`, 768 dimensions, stored as BLOB in SQLite
- **Ollama fallback**: Primary `llama3.1` -> fallback `qwen2.5` on error/timeout
- **ESM**: Project uses `"type": "module"` — all imports need `.js` extensions
## MCP Tools
| Tool | Purpose |
|------|---------|
| `memory_upsert` | Store documents (chunks, embeds, indexes) |
| `memory_search` | Semantic similarity search over stored docs |
| `context_pack` | Combine vector+text search, dedup, LLM synthesis |
| `context_compress` | Compress text (bullets/json/steps/summary) |
| `proxy_call` | Call tools on sub-MCP servers with post-processing |
## Testing
Tests use **vitest**. Run with `npm test`. Currently 31 tests across 6 files. Tests use in-memory SQLite (`:memory:`) so they don't need Ollama or a running server.
When adding new tools or services, add corresponding tests in the appropriate directory.
## Systemd Service (Production)
Runs as a systemd user service (no root required). Install script: `scripts/install-service.sh`.
```bash
# Unit file location
~/.config/systemd/user/mcp-context-hub.service
# Management commands
systemctl --user status mcp-context-hub # Check status
systemctl --user restart mcp-context-hub # Restart
systemctl --user stop mcp-context-hub # Stop
journalctl --user -u mcp-context-hub -f # Tail logs
```
- **Restart policy**: `on-failure` with 5s delay
- **Linger enabled**: starts at boot without login session
- **Logs**: go to journald automatically (structured JSON from pino)
## MCP Servers Configured
- **Serena**: Semantic code analysis with TypeScript LSP (`claude mcp add serena`)
- **Playwright**: Headless browser automation — requires absolute path to `npx` and PATH env so it can find `node`:
```bash
claude mcp add playwright -e PATH="/home/diego-nogueira/miniforge3/bin:/usr/local/bin:/usr/bin:/bin" -- /home/diego-nogueira/miniforge3/bin/npx @playwright/mcp@latest --headless
```