Tea Rags MCP
by artk0de
README.md
<p align="center">
<a href="https://artk0de.github.io/TeaRAGs-MCP/">
<img src="public/logo.png" alt="TeaRAGs logo">
</a>
</p>
<h1 align="center">TeaRAGs π¦π΅</h1>
<p align="center">
<strong>Codebase Intelligence layer for AI coding agents</strong><br>
<sub>Trajectory Enrichment-Aware RAG Β· served over MCP Β· 100% local</sub>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/tea-rags"><img src="https://img.shields.io/npm/v/tea-rags?logo=npm&color=d4af37" alt="npm version"></a>
<a href="https://github.com/artk0de/TeaRAGs-MCP/actions/workflows/ci.yml"><img src="https://github.com/artk0de/TeaRAGs-MCP/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://codecov.io/gh/artk0de/TeaRAGs-MCP"><img src="https://codecov.io/gh/artk0de/TeaRAGs-MCP/graph/badge.svg?token=BU255N03YF" alt="codecov"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-d4af37" alt="MIT license"></a>
</p>
---
**Your coding agent copies the first code it finds β not the right one.**
TeaRAGs is a **Codebase Intelligence layer** your agent queries over MCP. It
indexes the repository on your machine and returns every piece of code with
three views of it:
- π **What it does** β semantic and hybrid search over AST-aware chunks
- πΈοΈ **How it is connected** β callers, callees, fan-in, transitive impact
- 𧬠**How it has lived** β churn, bug-fix rate, ownership, age
β¦and ships agent skills that know which view a task needs. The agent stops
guessing which code is safe to copy, what is critical, and what a change will
break β it reads the dossier instead.
π **[Documentation](https://artk0de.github.io/TeaRAGs-MCP/)** Β· π
**[15-minute quickstart](https://artk0de.github.io/TeaRAGs-MCP/quickstart/installation)**
Β· π§
**[Core concepts](https://artk0de.github.io/TeaRAGs-MCP/introduction/core-concepts)**
## π See It
Three questions an agent asks before touching code, answered by TeaRAGs on its
own repository. Every number below is a real response, trimmed.
### 1. "Find retry logic I can reuse"
`semantic_search { query: "retry a failed request with exponential backoff", rerank: "hotspots" }`
Similarity alone puts `OllamaEmbeddings#retryWithBackoff` first. The dossiers of
the top two candidates tell different stories:
| | π₯ `OllamaEmbeddings#retryWithBackoff` | π₯ `DeletionRetryHelper#execute` |
| ------------------------- | -------------------------------------- | -------------------------------- |
| Similarity rank | #1 | #2 (`retry-helper.ts`) |
| Commits to the file | 28 | 1 |
| Share that were bug fixes | 54% Β· π΄ _concerning_ | 0% Β· π’ _healthy_ |
| Last changed | 2 days ago Β· _recent_ | 86 days ago Β· _old_ |
| Callers | 2 | 1 |
The closest match keeps getting fixed. The agent copies the quiet helper's shape
β or learns why the first one keeps breaking before it repeats the mistake.
<details>
<summary>Raw response for the first hit (trimmed)</summary>
```json
{
"symbolId": "OllamaEmbeddings#retryWithBackoff",
"relativePath": "src/core/adapters/embeddings/ollama.ts",
"startLine": 290,
"endLine": 378,
"preset": "hotspots",
"git": {
"file": {
"commitCount": 28,
"ageDays": { "value": 2, "label": "recent" },
"bugFixRate": { "value": 54, "label": "concerning" },
"relativeChurn": { "value": 2.55, "label": "normal" }
},
"chunk": {
"commitCount": { "value": 11, "label": "extreme" },
"relativeChurn": { "value": 9.09, "label": "high" }
}
},
"codegraph": { "symbols": { "chunk": { "fanIn": 2, "fanOut": 6 } } }
}
```
Labels are computed from **this repository's own percentiles**, so _extreme_
means extreme for this codebase, not for some global average.
</details>
### 2. "What is risky to touch around vector writes?"
`semantic_search { query: "write points to the vector database in batches", rerank: "dangerous" }`
Similarity alone ranks `PointsAccumulator#flushBatch`,
`QdrantPointStore#addPointsOptimized` and `QdrantPointStore#addPoints` first.
The `dangerous` preset reorders by risk and says why:
| # | Ranked by risk | Why it moved up |
| --- | -------------------------------------------- | --------------------------------------------------------------------------- |
| 1 | `ChunkPipeline#createBatchHandler` | 16 outgoing calls, 77 lines, 5 commits Β· _high_ |
| 2 | `QdrantManager#addPointsWithSparseOptimized` | file with 45 commits, relative churn 8.09 Β· π΄ _high_, 4 authors |
| 3 | `PointsAccumulator#flushBatch` | one author owns 100% of the live lines Β· π _deep-silo_, 158 days untouched |
### 3. "Who calls it before I change it?"
`get_callers { symbolId: "QdrantManager#addPointsWithSparse" }`
Ten exact call sites across eight files β method fan-in 10 Β· _central_, file
transitive impact 47 Β· _regional_:
```text
ChunkPipeline#createBatchHandler ingest/pipeline/chunk-pipeline.ts
createQdrantPipeline ingest/pipeline/pipeline-manager.ts
storeIndexingMarker (2 sites) ingest/pipeline/indexing-marker.ts
DocumentOps#add api/internal/ops/document-ops.ts
SchemaManager#storeSchemaMetadata adapters/qdrant/schema-manager.ts
EmbeddingModelGuard#readOrCreateMarker adapters/qdrant/embedding-model-guard.ts
IndexStoreAdapter#storeSchemaVersion maintenance/migration/adapters/index-store-adapter.ts
SparseStoreAdapter#rebuildSparseVectors maintenance/migration/adapters/sparse-store-adapter.ts
SparseStoreAdapter#storeSparseVersion maintenance/migration/adapters/sparse-store-adapter.ts
```
Need the whole chain from an entry point to this call? `trace_path` enumerates
every AβB path and, with a rerank preset, sorts them by how dangerous each step
is.
## β What It Answers
Ask in plain language. **The plugin picks the skill, tools and rerank presets
for every question automatically** β it ships a decision table that maps intent
to the right call, so nobody has to know a preset name. Other MCP clients get
the same routing guide as an MCP resource (`tea-rags://schema/search-guide`).
The right column shows what runs under the hood.
### πΊοΈ Understand
| Ask your agent | What runs |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
| _"Where do we charge a bill with a saved card, and what will it touch?"_ | `hybrid_search` with `blastRadius` β the service, its neighbours, its reach |
| _"Onboard me into billing β where are the entry points?"_ | `/tea-rags:explore` Β· `onboarding`, `entryPoint`, outlines via `find_symbol` |
| _"Which modules is this whole app built around?"_ | `architecturalHub` Β· `hotMethod` Β· `hubs` filter |
| _"What was done under ticket #4521?"_ | `taskId` filter |
### β»οΈ Reuse and generate
| Ask your agent | What runs |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| _"Add partial payments to bill payment β in our style, no duplicates."_ | `/tea-rags:data-driven-generation` β proven template, reuse gate, placement, callers |
| _"We have four payment-gateway retries. Which one should I copy?"_ | `proven` β long-lived, stable, low-bug, multi-author Β· `battleTested` filter |
| _"Is there already a helper that rounds money amounts?"_ | `/tea-rags:pattern-search` Β· `find_similar` |
### π― Change safely
| Ask your agent | What runs |
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| _"What should I not touch in this task, and where is it safer to build a parallel implementation?"_ | `criticalPath` Β· `blastRadius` Β· `godModule`; `/tea-rags:data-driven-generation` proposes a separate home when the target is overloaded |
| _"Who calls bill payment, and how does a request get from the API to the card charge?"_ | `get_callers` Β· `trace_path` with `dangerous` β the riskiest step first |
| _"Which code here should never change without a second reviewer?"_ | `criticalPath` Β· `criticalMethod` Β· `panicZone`, `unstableCore`, `hubs` filters |
| _"Which tests cover the behaviour I'm about to change?"_ | `/tea-rags:tests-as-context` |
### π Find problems
| Ask your agent | What runs |
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| _"Where are the most dangerous modules in the payments domain?"_ | `/tea-rags:risk-assessment` β `bugHunt`, `hotspots`, `techDebt`, `dangerous`, `criticalPath` in one pass, plus god modules |
| _"After a retry, a bill gets marked as paid twice. What is most likely to blame?"_ | `/tea-rags:bug-hunt` β the ticket text as the query, `bugHunt`, then `get_callers` / `trace_path` |
| _"Map the tech debt in invoicing."_ | `techDebt` Β· `refactoring` Β· `decomposition` Β· `godModule` Β· `godMethod` |
| _"Which files in this domain changed most this month?"_ | `rank_chunks` with `hotspots` and a `modifiedAfter` filter |
| _"What here is dead or abandoned?"_ | `deadCandidates` Β· `abandonedHotspots` filters |
### π₯ Review, ownership and audit
| Ask your agent | What runs |
| ------------------------------------------------------------- | --------------------------------------------------------------------------- |
| _"What in this merge request should I look at first?"_ | `/tea-rags:mr-review` β risk signals over the diff, callers of every change |
| _"Whose code is this, and where is the bus factor one?"_ | `ownership` Β· `fragileSilo` filter |
| _"Which old security-critical code is overdue for an audit?"_ | `securityAudit` Β· `securityPaths` filter |
## β¨ Features
- π **Git- and codegraph-aware ranking** β 23 rerank presets blend churn,
bug-fix rate, ownership and age with fan-in, PageRank and transitive impact
(`proven`, `hotspots`, `techDebt`, `blastRadius`, `criticalPath`, β¦), plus 12
filter presets
- πΈοΈ **Call graph** β callers, callees, cycles and AβB paths (`get_callers`,
`get_callees`, `find_cycles`, `trace_path`) for TypeScript, JavaScript, Python
and Ruby at a high tier
- π§ **Agent skills** β the plugin routes every question to the right tools and
presets on its own; 14 ready-made workflows (`explore`, `bug-hunt`,
`risk-assessment`, `data-driven-generation`, `mr-review`, β¦) plus
[`dinopowers`](https://artk0de.github.io/TeaRAGs-MCP/usage/skills/#dinopowers--wrappers-over-superpowers),
10 wrappers that feed index signals into
[`superpowers`](https://github.com/obra/superpowers)
- π **100% local** β embedded Qdrant and DuckDB, no Docker; embeddings through
Ollama, with OpenAI, Cohere and Voyage optional
- π **Always fresh** β incremental reindex, auto-update on a target branch,
per-worktree index clones, and a drift report that names the exact command to
run
- π’ **Built for enterprise monorepos** β AST chunking for 9 languages, parallel
pipelines, validated on a 3.5M-line production monolith
## π¦ Installation
### π» System requirements
| | Requirement |
| -------------- | ------------------------------------------------------------------------------------------------------- |
| **OS** | macOS (arm64, x64) Β· Linux (x64, arm64) Β· Windows (x64) |
| **Node.js** | 22+ supported, 24+ recommended |
| **git** | Required β churn, ownership and bug-fix signals come from the repository's history |
| **Embeddings** | [Ollama](https://ollama.com) with the code-embedding model (322 MB), or an OpenAI, Cohere or Voyage key |
| **Disk** | 66 MB for the Qdrant binary, plus the per-project indexes below |
Disk taken by real indexes (turbo quantization, dense + sparse vectors):
| Codebase | Indexed | Vector index (Qdrant) | Call graph (DuckDB) |
| --------------------------------------- | ----------------------------------------------------------- | --------------------- | ------------------- |
| Production monolith (Ruby + TypeScript) | **3M+ LoC + 118K lines of docs** Β· ~33k files Β· 140k chunks | 1.3 GB | 1.1 GB |
| TeaRAGs itself (TypeScript) | 433K LoC + 36K lines of docs Β· ~2.4k files Β· 25k chunks | 1.2 GB | 42 MB |
The call graph grows with the code; the vector index barely does β a codebase
seven times smaller still takes 1.2 GB.
Pull the code-embedding model:
```bash
ollama pull unclemusclez/jina-embeddings-v2-base-code:latest
```
**Claude Code** β plugins plus a setup wizard that detects your hardware and
tunes the pipeline:
```text
/plugin marketplace add artk0de/TeaRAGs-MCP
/plugin install tea-rags-setup@tea-rags
/tea-rags-setup:install
/plugin install tea-rags@tea-rags
```
**Any MCP client** (Cursor, Roo Code, Continue, β¦):
```bash
npm install -g tea-rags
```
```json
{
"mcpServers": {
"tea-rags": {
"command": "tea-rags",
"args": ["server"],
"env": { "CODEGRAPH_ENABLED": "true" }
}
}
}
```
Qdrant downloads and starts on first use. Cloud embeddings (OpenAI, Cohere,
Voyage), an external Qdrant, and the built-in ONNX provider (beta) are covered
in the
[installation guide](https://artk0de.github.io/TeaRAGs-MCP/quickstart/installation).
### πΈοΈ Enable the call graph
The call graph is **off by default** while it is in beta. Turn it on with
`CODEGRAPH_ENABLED=true` in the MCP server's environment β the JSON above
already does β or, in Claude Code:
```bash
claude mcp add tea-rags -s user -e CODEGRAPH_ENABLED=true -- tea-rags server
```
Then reindex. The flag is recorded per project, so later runs from the CLI or
auto-update keep the graph on. Details:
[Codegraph Enrichments](https://artk0de.github.io/TeaRAGs-MCP/usage/advanced/codegraph-enrichments).
## π Quick Start
```bash
tea-rags index-codebase /path/to/repo --name myrepo # first index: register + index
tea-rags prime /path/to/repo # index state, drift, signal thresholds
```
In Claude Code, `/tea-rags:index` does the same. Then ask your agent:
- _"How does auth work in this project?"_
- _"Find stable examples of retry logic I can copy."_
- _"What breaks if I change the payment module?"_
## π€ Why TeaRAGs?
| | `grep` / `ripgrep` | Embedding search | **TeaRAGs** |
| ---------------------------- | ------------------ | ---------------- | ----------------------------------------------------- |
| **Finds** | Exact text | Similar code | Similar code, ranked by evidence |
| **Knows history** | β | β | Churn, bug fixes, owners, age |
| **Knows callers** | β | β | Fan-in, transitive impact, call paths |
| **Ranks for the task** | β | Similarity only | 23 presets β see [What It Answers](#-what-it-answers) |
| **Cost on a large monorepo** | Many agent turns | One query | One query |
## βοΈ How It Works
```mermaid
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fdf8e7", "primaryTextColor": "#2d2d2d", "primaryBorderColor": "#d4af37", "lineColor": "#c4941f", "secondaryColor": "#f5f5dc", "tertiaryColor": "#fafafa", "mainBkg": "#fdf8e7", "secondBkg": "#f5f5dc", "nodeBorder": "#d4af37", "clusterBkg": "#fffdf6", "clusterBorder": "#d4af37", "titleColor": "#2d2d2d", "edgeLabelBackground": "#ffffff", "fontSize": "15px"}}}%%
flowchart LR
User([π€ You])
Agent[π€ Coding agent<br/>+ TeaRAGs skills]
subgraph pkg["π΅ tea-rags"]
MCP[π MCP server<br/>23 tools]
CLI[β¨οΈ CLI<br/>index Β· prime Β· projects Β· auto-update]
Core[βοΈ Core<br/>chunk Β· enrich Β· search Β· rerank]
MCP --> Core
CLI --> Core
end
subgraph storage["π» Local storage"]
Qdrant[(ποΈ Qdrant<br/>embedded Β· vectors + signals)]
DuckDB[(π¦ DuckDB<br/>embedded Β· call graph)]
end
Embeddings[β¨ Embeddings<br/>Ollama Β· OpenAI Β· Cohere Β· Voyage]
Repo[π Your repo<br/>code + git history]
User <--> Agent
Agent <--> MCP
User --> CLI
Core <--> Qdrant
Core <--> DuckDB
Core --> Embeddings
Core --> Repo
```
Your agent calls TeaRAGs over MCP; you run the CLI to index and maintain. Both
drive one core: it chunks code on AST boundaries, embeds each chunk, attaches
git and call-graph signals, and ranks results by the preset the task asks for.
Qdrant and DuckDB run embedded under `~/.tea-rags` β no Docker, no servers to
manage.
## π Measured
Call-graph quality is checked against independent oracles, not eyeballed.
| What | Result | Corpus |
| ----------------------------------------------------------- | -------------------------------------- | ---------------------------------- |
| π Python call graph vs. jedi + pyright (pyright tie-break) | recall 0.92β1.00 Β· wrong edges β€ 0.29% | flask, httpx, netbox, polar |
| π Ruby call graph, YARD-annotated | in-project recall 1.00 Β· 0 fabricated | octokit.rb |
| π Ruby call graph, un-annotated Rails | bare-call recall 0.93 | mastodon |
| π Ruby call graph, production Rails | in-project recall 87.7% | 3.5M-line production monolith |
| π¦ TypeScript call graph vs. the TypeScript type checker | phantom edges 0.32% Β· agreement 72.8%ΒΉ | 17k-file production React frontend |
| π¦ TypeScript call graph on TeaRAGs' own source | fabricated edges 93 β 0 | tea-rags `src/` |
| π§ `dinopowers` wrappers vs. plain `superpowers` skills | +71 pp mean pass rate | 136 eval cases, 10 wrappers |
| π©Ή Healing a drifted index instead of recomputing it | 113 ms | 134k-point production index |
ΒΉ About two thirds of the TypeScript gap is callbacks passed through props and
dependency injection β the type checker names a function type there, not an
implementation, so no static resolver can pin those edges.
The Python oracle harness ships in the repo
(`scripts/py-codegraph-jedi-oracle.ts`), so those numbers can be reproduced on
your own corpus.
<!-- BEGIN lang-compat -->
## Languages Compatibilities
<!-- markdownlint-disable MD033 -->
<details>
<summary>π Supported languages & support levels</summary>
**Support:** π maximum Β· π full Β· π high Β· π medium Β· π moderate Β· π
partial/low Β· π minimal Β· π none
What tea-rags supports per language and at what level. `AST chunking` is how
source is split into searchable chunks; `Test chunking` is how faithfully test
structure is preserved; `Codegraph` is the call-graph resolution ceiling (the
realized per-project number lives in the `tea-rags prime` digest, not here).
Rows are ordered by overall capability, richest support first.
| Language | AST chunking | Test chunking | Codegraph |
| ---------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **_TypeScript_** | π **full** Β· tree-sitter (comment attachment, method-body splitting, describe/it scopes) | π **high** Β· testScopeChunker (describe/it scopes) | π **high** β 14-strategy chain (10 tree-sitter + 4 ts.Program/typeChecker) + cone dispatch + typeChecker-backed union-receiver fan-out |
| **_JavaScript_** | π **full** Β· tree-sitter (assignment chunking, module/class split) | π **high** Β· testScopeChunker (describe/it scopes) | π **high** β 6-strategy; CommonJS/ESM require resolution (dynamic gaps) |
| **_Ruby_** | π **full** Β· tree-sitter (RSpec block grouping, comment attachment, spec scope splitting, method-body splitting) | π **high** Β· RSpec scope chunker (parent setup injected) | untyped π **high** Β· YARD π **maximum** Β· RBS/Sorbet π **TBD** β 15-strategy chain + 4 dispatch components + 20-grammar DSL catalogue + YARD type-source + db/schema.rb column accessors |
| **_Python_** | π **full** Β· tree-sitter | π **medium** Β· generic AST | π **high** β 9-strategy chain + C3 MRO + CHA cone dispatch + re-export-aware import mapping + annotation, docstring and return-type facts |
| **_Go_** | π **full** Β· tree-sitter (func/type split) | π **medium** Β· generic AST | π **moderate** β 7-pass chain + scope-aware typed locals + struct-field chains + embedding promotion + go.mod module-path imports; no interface dispatch |
| **_Java_** | π **full** Β· tree-sitter | π **medium** Β· generic AST | π **moderate** β 6-strategy + java.lang stdlib whitelist + overload disambiguation |
| **_Rust_** | π **full** Β· tree-sitter (named-item extraction) | π **medium** Β· generic AST (#[test] attrs not preserved) | π **moderate** β 6-strategy; trait-based dispatch |
| **_Bash_** | π **full** Β· tree-sitter | π **low** Β· generic AST (bats/shunit not recognized) | π **minimal** β function-call extraction only, no dispatch |
| **_Markdown_** | π **full** Β· MarkdownChunker (ToC + smart chunking) | π **N/A** Β· doc-only | π **none** β no call graph |
| **_sql_** | π **none** Β· CharacterChunker | π **N/A** | π **none** |
| **_jsonc_** | π **none** Β· CharacterChunker | π **N/A** | π **none** |
| **_json_** | π **none** Β· CharacterChunker | π **N/A** | π **none** |
</details>
<!-- markdownlint-enable MD033 -->
<!-- END lang-compat -->
## β¨οΈ CLI
| Command | What it does |
| ------------------------- | ------------------------------------------------------------------- |
| `tea-rags index-codebase` | Index or incrementally update a codebase, with live progress |
| `tea-rags prime` | Markdown digest of index state, drift and signal thresholds |
| `tea-rags projects` | Manage the project registry: `register`, `list`, `info`, `prune`, β¦ |
| `tea-rags auto-update` | Keep a project's index fresh on its target branch |
| `tea-rags worktree` | Per-worktree index clones for parallel branches |
| `tea-rags doctor` | Infrastructure and registry health |
| `tea-rags tune` | Auto-tune performance parameters for your hardware |
| `tea-rags update` | Check for and install a newer version |
| `tea-rags server` | Start the MCP server |
## π Documentation
| I want to⦠| Start here |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Get it running** | [Quickstart](https://artk0de.github.io/TeaRAGs-MCP/quickstart/installation) β install, index, first query |
| **Understand the concept** | [Core Concepts](https://artk0de.github.io/TeaRAGs-MCP/introduction/core-concepts) β vectorization, trajectory enrichment, reranking |
| **See what my agent can do** | [Skills](https://artk0de.github.io/TeaRAGs-MCP/usage/skills/) β the agent workflows and when each one fires |
| **Keep the index fresh** | [Auto-Update](https://artk0de.github.io/TeaRAGs-MCP/operations/auto-update) Β· [Drift Detection](https://artk0de.github.io/TeaRAGs-MCP/operations/drift-detection) |
| **Look under the hood** | [Architecture](https://artk0de.github.io/TeaRAGs-MCP/architecture/overview) β pipelines, data model, reranker internals |
| **Learn the theory** | [Knowledge Base](https://artk0de.github.io/TeaRAGs-MCP/knowledge-base/rag-fundamentals) β RAG, code search, software evolution |
## π From the Blog
Engineering notes behind the releases, each with the corpus it was measured on β
[all posts](https://artk0de.github.io/TeaRAGs-MCP/blog) Β·
[RSS](https://artk0de.github.io/TeaRAGs-MCP/blog/rss.xml).
<!-- BLOG:START -->
- [Why this blog exists β 2026-08-19](https://artk0de.github.io/TeaRAGs-MCP/blog/why-this-blog-exists)
<!-- BLOG:END -->
## π€ Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for workflow and conventions.
## π Acknowledgments
Started as a fork of
**[mhalder/qdrant-mcp-server](https://github.com/mhalder/qdrant-mcp-server)** β
clean architecture, solid tests, open-source spirit β and its ancestor
**[qdrant/mcp-server-qdrant](https://github.com/qdrant/mcp-server-qdrant)**.
Code vectorization inspired by
**[claude-context](https://github.com/zilliztech/claude-context)** (Zilliz).
_Feel free to fork this fork. It's forks all the way down._ π’
## βοΈ License
MIT β see [LICENSE](LICENSE). Brand policy in [BRAND.md](BRAND.md).
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessNo issues