Project Brain MCP
A lightweight MCP (Model Context Protocol) server that provides context orchestration, RAG-powered knowledge search, and project intelligence for AI agents (OpenCode, Claude, etc.).
Features
- Context Orchestrator — one-shot
prepare_context(task) returns unified Context Pack
- Workspace Intelligence — scan project directory, find files and symbols by name
- Code Intelligence — Tree-sitter AST index for Python/JS/TS/C/C++, with GDScript regex parser
- Semantic search over markdown/txt document repos using vector embeddings
- Priority-ranked context — Rules > Architecture > Decisions > Knowledge > Workspace for optimal LLM results
- Configurable logging — console + file output with level control
- 33 unit tests — core modules covered
- CI ready — GitHub Actions workflow + Dockerfile
- Heading-based chunking via Markdown AST parser — preserves document structure
- Pluggable embedding backends: sklearn (offline, zero-download) / bge-m3 / chroma-default
- SHA256 dedup — re-ingesting unchanged files skips embedding
- 37+ MCP tools for full knowledge, context, workspace, code, memory & workflow lifecycle management
- Configurable logging — console + file output
- 33 unit tests — core modules covered
- CI ready — GitHub Actions + Docker
- Zero external API calls — fully offline after setup
Quick Start
# 1. Install dependencies
pip install -r requirements.txt
# 2. (Optional) Switch to offline embedding — no model download
# Edit config.yaml:
# embedding.backend: sklearn
# 3. Run the server (stdio transport)
./run.sh
# or: python3 -m src.main
The server speaks MCP over stdio — configure your AI IDE/agent to launch it as a subprocess.
Configuration
Edit config.yaml:
server:
name: local-knowledge-mcp # MCP server name
transport: stdio # transport protocol (stdio only)
knowledge:
base_dir: knowledge # repo root directory
vector:
persist_dir: data/vector # ChromaDB persistence path
embedding:
backend: sklearn # sklearn | bge-m3 | chroma-default
fallback: sklearn # fallback if backend fails
device: cpu
logging:
level: INFO # DEBUG | INFO | WARNING | ERROR
file: true # enable file logging
dir: data/logs # log directory
Embedding Backends
| Backend |
Dimensions |
Model Download |
Notes |
sklearn |
256 |
None |
Default. Uses HashingVectorizer (char_wb ngram). Fully offline. |
bge-m3 |
1024 |
~2.2 GB (once) |
Best quality. Requires sentence-transformers. |
chroma-default |
768 |
None (ONNX) |
ChromaDB's built-in all-MiniLM-L6-v2. |
MCP Tools Reference
Health
| Tool |
Description |
ping |
Health check — returns "pong" |
Knowledge Management
| Tool |
Parameters |
Description |
list_knowledge |
— |
List all repos with file/chunk counts |
remove_document |
repo, filename |
Delete a file + its vector index |
remove_repo |
repo |
Delete entire repo + vector index |
rebuild_repo |
repo |
Clear vector index + re-index all files from disk |
Ingestion
| Tool |
Parameters |
Description |
ingest_document |
file_path, repo (default "default"), metadata (JSON, optional) |
Ingest a single .md or .txt file |
ingest_directory |
path, repo (defaults to directory name), metadata (JSON, optional) |
Batch import all .md/.txt files in a directory tree |
Search
| Tool |
Parameters |
Description |
search_knowledge |
query, repo (optional), top_k (default 5) |
Semantic search, text output |
search_knowledge_json |
query, repo (optional), top_k (default 5) |
Semantic search, structured JSON |
get_document |
repo, file |
Return full markdown file content |
Context Integration
| Tool |
Parameters |
Description |
search_context |
query, project_root, top_k (default 5) |
Merges .ai/{context,rules,decisions}.md from project with knowledge search |
prepare_context |
task (default ""), project_root (default "."), max_tokens (default 8000), top_k (default 5) |
🆕 One-shot context pack — Planner decides which sources to collect, returns priority-sorted Context Pack |
Workspace Intelligence
| Tool |
Parameters |
Description |
scan_workspace |
project_root (default ".") |
Full scan of project directory, build file + symbol index at .ai/workspace_index.json |
refresh_workspace |
project_root (default ".") |
Re-scan and rebuild workspace index |
find_file |
pattern, project_root (default "."), max_results (default 20) |
Find files by glob pattern (e.g. *.gd, **/player*) |
find_symbol |
query, project_root (default "."), max_results (default 20) |
Find symbols (functions, classes, signals) by name |
list_dir |
path (default ""), project_root (default ".") |
List directory contents from workspace index |
Code Intelligence
| Tool |
Parameters |
Description |
scan_code |
project_root (default ".") |
Full scan of source code, build AST-based code index at .ai/code_index.json |
refresh_code_index |
project_root (default ".") |
Re-scan and rebuild code index |
search_code |
query, project_root (default "."), max_results (default 20) |
Find symbols (class/function) by name in source code |
find_references |
symbol_name, project_root (default "."), max_results (default 20) |
Find where a symbol is called/used |
get_symbol |
name, project_root (default ".") |
Get symbol definition location |
list_symbols |
symbol_type (optional), project_root (default "."), max_results (default 50) |
List all symbols, optionally filtered by type (class/function) |
Project Memory
| Tool |
Parameters |
Description |
remember |
key, value, project_root (default "."), namespace (default "default") |
Store a key-value memory |
recall |
key, project_root (default "."), namespace (default "default") |
Retrieve a memory by key |
forget |
key, project_root (default "."), namespace (default "default") |
Delete a memory |
list_memories |
project_root (default "."), namespace (default "default") |
List all keys in a namespace |
search_memory |
query, project_root (default "."), max_results (default 10) |
Search memories by content |
refresh_git_index |
project_root (default "."), max_commits (default 200) |
Index git history |
search_git_history |
query, project_root (default "."), max_results (default 10) |
Search commits by message/author |
recent_commits |
project_root (default "."), count (default 5) |
Show recent commits |
log_decision |
title, context, decision, project_root (default "."), consequences, status |
Log an ADR decision |
search_decisions |
query, project_root (default "."), max_results (default 10) |
Search ADR decisions |
list_decision_log |
project_root (default "."), status (optional) |
List all decisions |
Agent Workflow
| Tool |
Parameters |
Description |
init_project |
name, project_root (default "."), description |
Initialize .ai/ structure (context.md, rules.md, decisions.md, architecture.md) |
project_status |
project_root (default ".") |
Show feature/task summary |
create_feature |
name, project_root (default "."), description |
Create a feature tracking entry |
list_features |
project_root (default "."), status (optional) |
List features by status |
start_task |
name, project_root (default "."), description, feature_id |
Create and start a task |
finish_task |
task_id, project_root (default "."), note |
Mark a task as completed |
list_tasks |
project_root (default "."), status (optional) |
List tasks by status |
review_pr |
project_root (default "."), pr_number, task (default "review PR") |
Prepare comprehensive PR review context |
Metadata (optional, on chunks)
{
"version": "4.x",
"category": "tutorial",
"language": "gdscript"
}
Pass as the metadata parameter to ingest_document / ingest_directory.
Project Layout
├── src/
│ ├── main.py # Entrypoint
│ ├── server.py # FastMCP factory + vector store init
│ ├── config.py # YAML config loader
│ ├── orchestrator/ # Context Orchestrator (V2)
│ │ ├── pack.py # ContextPack dataclass + priorities
│ │ ├── planner.py # task → source planning
│ │ ├── collector.py # multi-source collection
│ │ ├── ranker.py # priority sort + dedup + truncation
│ │ └── formatter.py # ContextPack → text / dict
│ ├── workspace/ # Workspace Intelligence (M006)
│ │ ├── scanner.py # file system walk + symbol extraction
│ │ ├── indexer.py # JSON index build / save / load
│ │ └── searcher.py # find_file, find_symbol, list_directory
│ ├── code/ # Code Intelligence (M007)
│ │ ├── parser.py # Tree-sitter AST + GDScript regex parser
│ │ ├── indexer.py # JSON index build / save / load
│ │ └── searcher.py # search_code, find_references, get_symbol
│ ├── memory/ # Project Memory (M008)
│ │ ├── store.py # key-value memory (remember/recall)
│ │ ├── git_store.py # git history index + search
│ │ └── decisions.py # ADR decision log
│ ├── workflow/ # Agent Workflow (M009)
│ │ ├── project.py # init_project, project_status
│ │ ├── feature.py # create_feature, list_features
│ │ ├── task.py # start_task, finish_task
│ │ └── review.py # review_pr (orchestrator + git)
│ ├── tools/
│ │ ├── knowledge.py # ping, list, remove, rebuild_repo
│ │ ├── ingest.py # ingest_document, ingest_directory
│ │ ├── search.py # search, search_json, get_document
│ │ ├── context.py # search_context, prepare_context
│ │ ├── workspace.py # scan_workspace, find_file, find_symbol, list_dir
│ │ ├── code.py # scan_code, search_code, find_references
│ │ ├── memory.py # remember, recall, git, decisions
│ │ └── workflow.py # init_project, create_feature, start_task, review_pr
│ └── rag/
│ ├── chunker.py # Markdown AST chunker (heading-based)
│ ├── embedding.py # Pluggable (sklearn / bge-m3 / chroma-default)
│ ├── vector_store.py # ChromaDB CRUD wrapper
│ └── document_loader.py # File read + sha256
├── knowledge/ # Document repos (gitignored — manage separately)
├── data/vector/ # ChromaDB persistence (auto-generated, gitignored)
├── config.yaml
├── requirements.txt
└── run.sh
V2 Roadmap
| MS |
Module |
Status |
| M005 |
Context Orchestrator |
🟢 Implemented |
| M006 |
Workspace Intelligence |
🟢 Implemented |
| M007 |
Code Intelligence |
🟢 Implemented |
| M008 |
Project Memory |
🟢 Implemented |
| M009 |
Agent Workflow |
🟢 Implemented |
| M010 |
Engineering (logs, tests, CI, Docker) |
🟢 Implemented |
Architecture
┌──────────────┐ MCP/stdio ┌──────────────────────┐
│ AI Agent │ ◄──────────────► │ FastMCP Server │
│ (OpenCode, │ │ │
│ Claude, etc)│ │ ┌────────────────┐ │
└──────────────┘ │ │ Vector Store │ │
│ │ (ChromaDB) │ │
│ ├────────────────┤ │
│ │ Embedding FN │ │
│ │ (sklearn/bge) │ │
│ ├────────────────┤ │
│ │ AST Chunker │ │
│ └────────────────┘ │
└──────────────────────┘
Chunking Strategy
The AST chunker splits documents by # headings:
# Node
## Lifecycle
body...
## Signals
body...
Produces chunks with heading_path (e.g. Node/Lifecycle), level, title, parent_heading. Each chunk is enriched with its heading path for better retrieval context.
Batch Import
# Via MCP tool call:
ingest_directory(path="/path/to/docs", repo="my-docs")
# Re-index an existing repo after changing chunker/embedding:
rebuild_repo(repo="my-docs")
Requirements
- Python 3.10+
- Dependencies:
mcp, pyyaml, chromadb, scikit-learn, markdown-it-py
- Optional:
sentence-transformers (for bge-m3 backend)
License
MIT