A private knowledge retrieval MCP server for LLM clients. Syncs Notion · Tistory · GitHub · Obsidian into vector + metadata stores and returns citation-backed context.
[ Sources ]
Notion / Tistory / GitHub / Obsidian
|
v
[ Ingestion Service ]
/ \
v v
[ Chroma ] [ SQLite ]
semantic search metadata gate
\ /
v v
[ Verified Context ]
| Tool | Description |
|---|---|
list_sources() |
List configured sources |
sync_source(source_id) |
Sync a specific source |
sync_all() |
Sync all sources at once |
get_sync_status(source_id="") |
Get source and sync job status |
search_context(query, ...) |
Semantic search with SQLite validation |
search_documents(query, ...) |
Search results grouped by document |
fetch_context(document_id="", chunk_id="") |
Fetch a specific document or chunk directly |
💡 In production, use
search_context/search_documentsto gather grounded evidence, then let a downstream LLM generate the final answer.
Prerequisites: Python 3.13, uv
uv sync --locked
cp .env.example .env
uv run --locked python main.pyDocker:
docker build -t contextwiki .
cp .env.example .env
docker run --rm -i \
--env-file .env \
-v contextwiki_data:/home/appuser/.mcp_content_search \
contextwikiFor Obsidian in Docker, add
-v "/path/to/vault:/vault:ro"and setCONTEXTWIKI_OBSIDIAN_VAULT_PATH=/vault.
| Source | Source ID | Env var to enable |
|---|---|---|
| Notion | source_notion |
NOTION_API_KEY |
| Tistory | source_tistory |
TISTORY_BLOG_NAME |
| GitHub | source_github |
CONTEXTWIKI_GITHUB_REPOSITORIES |
| Obsidian | source_obsidian |
CONTEXTWIKI_OBSIDIAN_VAULT_PATH |
Set only the sources you plan to use. A source stays disabled when its enabling
config is missing or empty. Bad credentials can still fail later during refresh
or sync. Some invalid target values can fail earlier during startup or source
refresh; for example, a malformed CONTEXTWIKI_GITHUB_REPOSITORIES value can
prevent the server from starting cleanly.
Source-specific env vars only register and enable each source. With the default
embedding setup, successful sync/indexing still also requires OPENAI_API_KEY
unless you reconfigure embeddings.
OPENAI_API_KEY=... # required for default embeddings/indexing; also used by optional rewrite
NOTION_API_KEY=...
TISTORY_BLOG_NAME=devlog # subdomain only, not the full URL
CONTEXTWIKI_GITHUB_REPOSITORIES=eunhwa99/MCPContentSearch@main
GITHUB_TOKEN=... # needed for private repos or higher rate limits
CONTEXTWIKI_OBSIDIAN_VAULT_PATH=/absolute/path/to/vaultImportant GitHub notes:
- Use
owner/repoorowner/repo@ref. - Do not wrap
CONTEXTWIKI_GITHUB_REPOSITORIESin quotes in.env. GITHUB_TOKENis optional, but private repositories and higher rate limits usually need it.
Notion example
NOTION_API_KEY=...Set this only if you want to enable the Notion source.
Tistory example
TISTORY_BLOG_NAME=devlogUse the blog subdomain only, not the full URL. For example, use devlog, not
https://devlog.tistory.com.
Obsidian example
CONTEXTWIKI_OBSIDIAN_VAULT_PATH=/absolute/path/to/your/vault
CONTEXTWIKI_OBSIDIAN_MAX_FILES=2000
CONTEXTWIKI_OBSIDIAN_MAX_FILE_BYTES=512000Use the vault root path, not an individual .md file path.
CONTEXTWIKI_SEARCH_LLM_ENABLED=true
CONTEXTWIKI_SEARCH_LLM_PROVIDER=openai
CONTEXTWIKI_SEARCH_LLM_MODEL=gpt-4.1-miniThis is the easiest setup path on macOS because:
- Claude Desktop can spawn the server directly.
- ContextWiki loads the repository-local
.envat startup, so Claude Desktop does not need plaintext env entries inclaude_desktop_config.json. - Obsidian can use your real host vault path directly.
- You do not need Docker mounts for the vault.
Important:
- Repository
.envvalues do not override env vars already set by Claude Desktop or your shell. - If you previously set
OPENAI_API_KEY,NOTION_API_KEY,GITHUB_TOKEN, or other source env vars inclaude_desktop_config.jsonor a parent shell, clear the stale values there too.
Do this in order:
- Create
.envin your repo root. - Put your real values there.
- Add the MCP entry below to Claude Desktop.
- Fully restart Claude Desktop.
- In a fresh Claude Desktop chat, ask it to call
list_sources().
Example .env:
# Required for default sync/indexing because embeddings use OpenAI by default
OPENAI_API_KEY=...
# Optional: enable Notion source
NOTION_API_KEY=...
# Optional: enable Tistory source
TISTORY_BLOG_NAME=devlog
# Optional: enable GitHub source
CONTEXTWIKI_GITHUB_REPOSITORIES=eunhwa99/MCPContentSearch
CONTEXTWIKI_GITHUB_DEFAULT_REF=main
# Optional for private repos or higher GitHub API limits
GITHUB_TOKEN=...
# Optional: enable Obsidian source
CONTEXTWIKI_OBSIDIAN_VAULT_PATH=/absolute/path/to/your/vaultOn macOS, add this to
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"content-search-server": {
"command": "/absolute/path/to/uv",
"args": [
"--directory", "/absolute/path/to/MCPContentSearch",
"run", "--python", "3.13", "python", "main.py"
]
}
}
}Run
which uvto find the path. Fully restart Claude Desktop after any config change.
{
"mcpServers": {
"content-search-server": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"--env-file", "/absolute/path/to/MCPContentSearch/.env",
"-v", "contextwiki_data:/home/appuser/.mcp_content_search",
"contextwiki:latest"
]
}
}
}Add the same local uv config above to .cursor/mcp.json.
- Call
sync_all()orsync_source("source_notion") - Search with
search_context()orsearch_documents()
Example prompt:
find my projects about DynamoDB and organize it with STAR method. Answer in English
| Symptom | Fix |
|---|---|
| MCP server not discovered | Recheck config path and fully restart the client |
| Only works after manual start | Run command + args directly in terminal to see errors |
Invalid GitHub repository spec |
Remove quotes from .env; use owner/repo, not a full URL |
| Obsidian not working in Docker | Set both the volume mount and CONTEXTWIKI_OBSIDIAN_VAULT_PATH=/vault |
| Source still disabled after config change | Fully restart the MCP client — a chat refresh is not enough |
sync_all() too slow |
Sync individually: sync_source("source_github"), etc. |
./scripts/demo.sh # Quick flow check with sample vault (no credentials needed)
./scripts/verify_all.sh # Full verification after code changes
./scripts/demo.sh --query "your question" # Custom query./scripts/demo.shis the default reviewer path. It uses the bundled sample vault, needs no credentials, and keeps retrieval plus helper preview on the same input by default.
main.py FastMCP server entry point
api/ MCP tool handlers
core/ Shared models, exceptions, utilities
environments/ Env var and secret loading
fetching/ Source connectors (Notion, Tistory, GitHub, Obsidian)
indexing/ Chunking, deduplication, Chroma indexing
search/ Search, ranking, metadata gate, citation answer support
storage/ SQLite lifecycle management
tests/, scripts/ Verification harnesses and utilities
