Back to portfolio
Side Project · 2025

ContextWiki
MCP Retrieval Server

A private knowledge retrieval server built on the MCP protocol. Syncs Notion, Tistory, GitHub, and Obsidian into a dual-store index — ChromaDB for semantic search, SQLite as a metadata gate — and returns citation-backed context for LLM clients like Claude Desktop.

4 source connectors 7 MCP tools ChromaDB + SQLite dual-store Python · FastMCP Docker · CI
Claude Desktop using ContextWiki to retrieve citation-backed DynamoDB evidence before composing a STAR-style answer
Retrieval runs inside the LLM's own workflow. The screenshot shows cited source chunks surfaced before Claude composes the final response — no separate search tab needed.

Architecture

Ingestion → Dual Store → Verified Context

Each source connector fetches raw content, which is chunked and deduplicated before being written to two stores simultaneously. ChromaDB handles semantic similarity via OpenAI embeddings; SQLite acts as a metadata gate that validates chunk provenance before results reach the caller.

[ Sources ] Notion · Tistory · GitHub · Obsidian


[ Ingestion Service ] fetch → chunk → deduplicate
╱ ╲
▼ ▼
[ ChromaDB ] [ SQLite ]
semantic search metadata gate
╲ ╱
▼ ▼
[ Verified Context ] → MCP client

Tech Stack

Core

Python FastMCP Pydantic asyncio / aiohttp

Vector & Storage

ChromaDB LlamaIndex OpenAI Embeddings SQLite

Infra & Tooling

Docker uv GitHub Actions CI pytest · ruff · mypy · bandit

MCP Tools

7 tools registered on the FastMCP server

Tool Description
list_sources()List all configured source connectors and their status
sync_source(source_id)Trigger incremental sync for a specific source
sync_all()Sync all active sources in one call
get_sync_status()Return current source health and sync job state
search_context(query, ...)Semantic search with SQLite metadata validation — primary retrieval path
search_documents(query, ...)Same retrieval grouped by source document
fetch_context(document_id, ...)Direct chunk or document fetch by ID

Design Decisions

What I built

  • Source connectors for Notion API, Tistory RSS, GitHub REST, and Obsidian vault
  • Chunking pipeline with deduplication before indexing
  • Dual-store write path: Chroma for embedding, SQLite for metadata gating
  • Search & ranking layer with optional LLM query rewrite (GPT-4.1-mini)
  • FastMCP server entry point wiring all services together
  • Docker image + GitHub Actions CI (lint, type check, security scan, 70%+ coverage)

Evidence gathering vs. answer generation

In production, search_context and search_documents return grounded evidence chunks, and the downstream LLM — Claude Desktop, Cursor — composes the final answer.

Keeping the retrieval layer and the answer layer separate means the search results stay inspectable, the MCP server stays stateless, and swapping the LLM client requires zero changes to the server.