reporelay
by chwoerz
README.md
<p align="center">
<h1 align="center">ALPHA VERSION</h1>
</p>
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/logo/logo-text-dark.png">
<source media="(prefers-color-scheme: light)" srcset="assets/logo/logo-text-light.png">
<img alt="RepoRelay — Self-hosted, MCP-native code context engine" src="assets/logo/logo-text-dark.png" width="400">
</picture>
</p>
<p align="center">
<a href="#quick-start"><img alt="Quick Start" src="https://img.shields.io/badge/-Quick_Start_%E2%86%92-blue?style=for-the-badge&color=2563eb"></a>
<a href="https://chwoerz.github.io/reporelay/"><img alt="Documentation" src="https://img.shields.io/badge/-Docs_%E2%86%92-blue?style=for-the-badge&color=8b5cf6"></a>
</p>
<p align="center">
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white">
<img alt="Node.js 22+" src="https://img.shields.io/badge/Node.js-22%2B-339933?logo=node.js&logoColor=white">
<img alt="MCP" src="https://img.shields.io/badge/MCP-Native-8b5cf6">
<img alt="Postgres" src="https://img.shields.io/badge/Postgres-ParadeDB-4169E1?logo=postgresql&logoColor=white">
<img alt="Tests" src="https://img.shields.io/badge/Tests-passing-22c55e">
<img alt="License" src="https://img.shields.io/badge/License-MIT-blue">
</p>
---
**RepoRelay** is a self-hosted code context engine for [MCP](https://modelcontextprotocol.io).
1. [**Add repositories**](https://chwoerz.github.io/reporelay/guide/getting-started) from any source — GitHub, GitLab, Bitbucket, on-premise, or local disk
2. [**Index the refs you need**](https://chwoerz.github.io/reporelay/guide/indexing-pipeline) — pick the branches and tags that matter; each gets its own versioned snapshot
3. [**Use them everywhere**](https://chwoerz.github.io/reporelay/guide/mcp-integration) — every indexed repo is instantly available as MCP tools in Claude Desktop, Cursor, Windsurf, OpenCode, or any other MCP-capable client
Manage everything through the [REST API](https://chwoerz.github.io/reporelay/reference/api) or the [admin dashboard](https://chwoerz.github.io/reporelay/guide/admin-dashboard). Register once, query from any project in any editor. RepoRelay parses files with [tree-sitter](https://tree-sitter.github.io/tree-sitter/), extracts symbols and imports, and stores everything in a hybrid search index (BM25 + pgvector).
RepoRelay runs entirely on your infrastructure — no third-party indexing service, no telemetry, no repo uploads. Code only leaves your network via the providers you explicitly configure: snippets requested by the LLM you connect via MCP (e.g. Claude, GPT), and chunks sent to your embedding provider during indexing (cloud providers like OpenAI see the code; a local Ollama setup keeps everything on-box).
---
## Demo
<p align="center">
<a href="https://www.youtube.com/watch?v=LBRttRAcL3w">
<img src="https://img.youtube.com/vi/LBRttRAcL3w/maxresdefault.jpg" alt="RepoRelay demo" width="640">
</a>
</p>
---
## Highlights
| | Feature | Description |
| :---------- | :-------------------------------------------------- | :---------------------------------------------------------------------------------------------- |
| **Repos** | Unlimited Repositories | Register repos from any Git host — GitHub, GitLab, Bitbucket, on-premise, or local paths |
| **Search** | Hybrid Search | BM25 full-text (ParadeDB) + vector similarity (pgvector), fused via Reciprocal Rank Fusion |
| **Parse** | Deep Code Understanding | tree-sitter parsing across 9 languages extracts symbols, imports, signatures, and doc comments |
| **Index** | Full-Index + SHA-256 Dedup | Every ref indexes all files via `git ls-tree`; SHA-256 content addressing skips unchanged files |
| **MCP** | MCP-Native | 7 tools, 2 resources, 3 prompts — works with any MCP host |
| **Version** | Versioned Snapshots | Every branch and tag is indexed independently; query with semver ranges like `^1.2` or `~3.0` |
| **Deploy** | Self-Hosted | Your code stays on your infrastructure. Postgres is the only runtime dependency |
| **UI** | REST API + Admin Dashboard | Fastify REST API (18 routes) + Angular 21 admin dashboard |
| **Embed** | Ollama | Ollama with Metal GPU acceleration for fast local embeddings |
| **Chunk** | Symbol-Aware Chunking | Respects function boundaries with overlap windows — never cuts a symbol in half |
| **Lang** | [Language Auto-Detection](#language-auto-detection) | Detects your project's languages from manifest files and filters relevant repos automatically |
<p align="center">
<img src="assets/icons/typescript-original.svg" width="38" alt="TypeScript"/>
<img src="assets/icons/javascript-original.svg" width="38" alt="JavaScript"/>
<img src="assets/icons/python-original.svg" width="38" alt="Python"/>
<img src="assets/icons/go-original-wordmark.svg" width="38" alt="Go"/>
<img src="assets/icons/java-original.svg" width="38" alt="Java"/>
<img src="assets/icons/kotlin-original.svg" width="38" alt="Kotlin"/>
<img src="assets/icons/rust-original.svg" width="38" alt="Rust"/>
<img src="assets/icons/c-original.svg" width="38" alt="C"/>
<img src="assets/icons/cplusplus-original.svg" width="38" alt="C++"/>
<img src="assets/icons/markdown-original.svg" width="38" alt="Markdown"/>
</p>
---
## Quick Start
<details>
<summary><h3>Option A: Docker Compose (recommended)</h3></summary>
Run the entire stack — Postgres, worker, REST API, MCP server, and admin UI — with a single command. No Node.js installation required.
#### Prerequisites
| Requirement | Version |
| ----------- | ------- |
| Docker | Latest |
#### 1. Clone and configure
```bash
git clone https://github.com/chwoerz/reporelay.git
cd reporelay
cp .env.example .env
```
Edit `.env` if you need to change the embedding model or Git tokens for private repos. The defaults work out of the
box if you have [Ollama](https://ollama.com/) running locally with `nomic-embed-text` as a model.
#### 2. Start everything
```bash
docker compose up -d
```
This builds and starts all 5 services:
| Service | Port | Description |
| ---------- | ------- | ------------------------------------------ |
| `postgres` | `5432` | ParadeDB (Postgres + pgvector + pg_search) |
| `worker` | — | Background indexing worker (pg-boss) |
| `web` | `3001` | REST API + Swagger UI (`/docs`) |
| `mcp` | `3000` | MCP server (HTTP transport) |
| `ui` | `80` | Angular admin dashboard (nginx) |
| Ollama | `11434` | Embedding model (external) |
The worker runs database migrations automatically on first startup.
#### 3. Index your repos
```bash
# Register a remote repo
curl -sS -X POST http://localhost:3001/api/repos \
-H 'content-type: application/json' \
-d '{"name":"my-lib","remoteUrl":"https://github.com/org/my-lib.git"}'
# Trigger indexing for a specific branch
curl -sS -X POST http://localhost:3001/api/repos/my-lib/sync \
-H 'content-type: application/json' \
-d '{"ref":"main"}'
# Index a tagged release — each version is stored independently
curl -sS -X POST http://localhost:3001/api/repos/my-lib/sync \
-H 'content-type: application/json' \
-d '{"ref":"v2.0.0"}'
# Search across all indexed repos and versions
curl -sS 'http://localhost:3001/api/search?query=handleAuth'
```
Or use the admin dashboard at `http://localhost` and the Swagger UI at `http://localhost:3001/docs`.
#### 4. MCP Client
Configure your MCP client (Claude Desktop, Cursor, etc.) to connect to the MCP proxy at `http://localhost:3000/mcp` — see the [MCP Client Setup](#mcp-client-setup) section below for details.
</details>
<details>
<summary><h3>Option B: Local Development</h3></summary>
Run services directly with Node.js for a faster dev loop with hot-reload.
#### Prerequisites
| Requirement | Version |
| ----------- | ------- |
| Node.js | 22+ |
| pnpm | 9+ |
| Docker | Latest |
#### 1. Clone and install
```bash
git clone https://github.com/chwoerz/reporelay.git
cd reporelay
pnpm install
```
#### 2. Start Postgres
```bash
docker compose up -d postgres
```
This starts [ParadeDB](https://www.paradedb.com/) (Postgres with pgvector + pg_search).
#### 3. Configure environment
```bash
cp .env.example .env
# Defaults work for local development — no edits needed
```
#### 4. Start services
```bash
# All-in-one dev script (Postgres + worker + web API)
pnpm dev
# Or individual services
pnpm dev:worker # Background indexing worker
pnpm dev:mcp # MCP server (HTTP on :3000)
pnpm dev:web # REST API on :3001
pnpm dev:proxy # MCP proxy (connects to MCP server)
pnpm dev:ui # Angular dashboard on :4200
```
| Service | Port | Description |
| ---------- | ------- | ------------------------------------------ |
| `postgres` | `5432` | ParadeDB (Postgres + pgvector + pg_search) |
| `worker` | — | Background indexing worker (pg-boss) |
| `web` | `3001` | REST API + Swagger UI (`/docs`) |
| `mcp` | `3000` | MCP server (HTTP transport) |
| `proxy` | — stdio | MCP proxy (connects to MCP server) |
| `ui` | `4200` | Angular dev server |
| Ollama | `11434` | Embedding model (external) |
The worker bootstraps the database on first startup (extensions, migrations, BM25 index).
#### 5. Index your repos
```bash
# Register a local repo
curl -sS -X POST http://localhost:3001/api/repos \
-H 'content-type: application/json' \
-d '{"name":"my-app","localPath":"/absolute/path/to/my-app"}'
# Register a remote repo
curl -sS -X POST http://localhost:3001/api/repos \
-H 'content-type: application/json' \
-d '{"name":"my-lib","remoteUrl":"https://github.com/org/my-lib.git"}'
# Trigger indexing for a specific branch
curl -sS -X POST http://localhost:3001/api/repos/my-app/sync \
-H 'content-type: application/json' \
-d '{"ref":"main"}'
# Index a tagged release — each version is stored independently
curl -sS -X POST http://localhost:3001/api/repos/my-lib/sync \
-H 'content-type: application/json' \
-d '{"ref":"v2.0.0"}'
# Search across all indexed repos and versions
curl -sS 'http://localhost:3001/api/search?query=handleAuth'
# Check status
curl -sS http://localhost:3001/api/repos
```
Or use the admin dashboard at `http://localhost:4200`.
#### 6. MCP Client
Configure your MCP client (Claude Desktop, Cursor, etc.) to connect to the MCP proxy at `http://localhost:3000/mcp` — see the [MCP Client Setup](#mcp-client-setup) section below for details.
</details>
### Supported Git Hosts
RepoRelay works with **any Git repository** accessible over HTTPS or on the local filesystem. There is no vendor lock-in — your repos can come from any combination of:
- **GitHub** (github.com and GitHub Enterprise)
- **GitLab** (gitlab.com and self-managed)
- **Bitbucket** (Cloud and Data Center)
- **Azure DevOps**
- **Gitea / Forgejo**
- **Any on-premise Git server** (Gerrit, cgit, etc.)
- **Local repositories** on disk
For private repos, set a `GIT_TOKEN_<HOST>` environment variable and RepoRelay handles authentication automatically. Host-specific username defaults are built-in for GitHub, GitLab, and Bitbucket — any other host uses `GIT_USER_<HOST>` or falls back to `oauth2`.
```bash
# Example: authenticate with GitHub and a self-hosted GitLab
GIT_TOKEN_GITHUB_COM=ghp_xxxxxxxxxxxx
GIT_TOKEN_GITLAB_INTERNAL_CORP_COM=glpat-xxxxxxxxxxxx
```
---
## MCP Client Setup
### Claude Desktop / Cursor
Clients connect via the MCP proxy, which auto-detects your project's languages and forwards requests to the RepoRelay HTTP server:
```json
{
"mcpServers": {
"reporelay": {
"command": "npx",
"args": ["reporelay", "--server", "http://localhost:3000/mcp"]
}
}
}
```
See the [full documentation](https://chwoerz.github.io/reporelay/guide/mcp-integration) for OpenCode, remote server, and other client configurations.
### MCP Proxy
The MCP proxy is a lightweight local binary that sits between your IDE and the RepoRelay HTTP server. It:
1. Detects languages from the developer's working directory
2. Connects to the RepoRelay MCP server over HTTP
3. Forwards all MCP requests, injecting detected languages into tool calls
```bash
# Via CLI argument
npx reporelay --server http://localhost:3000/mcp
# Or via environment variable
REPORELAY_URL=http://localhost:3000/mcp npx reporelay
```
For a remote server, just change the URL:
```json
{
"mcpServers": {
"reporelay": {
"command": "npx",
"args": ["reporelay", "--server", "https://reporelay.example.com/mcp"]
}
}
}
```
The proxy injects languages into 4 tools that support language filtering: `search_code`, `get_symbol`, `find`, and `list_repos`. Per-request `languages` values provided by the caller take priority over auto-detected ones.
### Language Auto-Detection
When `MCP_LANGUAGES` is not set, the MCP server automatically detects the host project's language by scanning the working directory for well-known manifest files:
| Manifest File | Detected Languages |
| ------------------------------- | ---------------------- |
| `package.json`, `tsconfig.json` | typescript, javascript |
| `Cargo.toml` | rust |
| `go.mod` | go |
| `pyproject.toml`, `setup.py` | python |
| `pom.xml`, `build.gradle(.kts)` | java, kotlin |
| `CMakeLists.txt`, `Makefile` | c, cpp |
Detected languages are used to filter which repos are served — only repos whose `language_stats` contain a matching language above the threshold are included.
**`MCP_LANGUAGE_THRESHOLD`** (default: `10`) controls the minimum percentage a language must represent in a repo ref's file breakdown. Set to `0` to disable repo filtering entirely.
```json
{
"mcpServers": {
"reporelay": {
"command": "npx",
"args": ["tsx", "src/mcp/main.ts"],
"env": {
"DATABASE_URL": "postgresql://reporelay:reporelay@localhost:5432/reporelay",
"MCP_LANGUAGE_THRESHOLD": "0"
}
}
}
}
```
---
## Documentation
Full documentation is available at the **[RepoRelay docs site](https://chwoerz.github.io/reporelay/)**, including:
- [Indexing pipeline deep-dive](https://chwoerz.github.io/reporelay/guide/indexing-pipeline)
- [MCP tools, resources & prompts reference](https://chwoerz.github.io/reporelay/reference/mcp-tools)
- [REST API reference (18 endpoints)](https://chwoerz.github.io/reporelay/reference/api)
- [Configuration reference](https://chwoerz.github.io/reporelay/guide/configuration)
- [Database design](https://chwoerz.github.io/reporelay/guide/database-design)
- [Project structure](https://chwoerz.github.io/reporelay/reference/project-structure)
- [Tech stack](https://chwoerz.github.io/reporelay/reference/tech-stack)
---
## Testing
Comprehensive test suite (unit + integration) covering every module.
```bash
pnpm test # All tests
pnpm test:unit # Unit tests only
pnpm test:integration # Integration tests (requires Docker)
pnpm test:watch # Watch mode
```
Integration tests use real ParadeDB containers via [Testcontainers](https://testcontainers.com/).
---
## Tech Stack
<p align="center">
<img src="assets/icons/typescript-original.svg" width="34" alt="TypeScript"/>
<img src="assets/icons/nodejs-original.svg" width="34" alt="Node.js"/>
<img src="assets/icons/fastify-original.svg" width="34" alt="Fastify"/>
<img src="assets/icons/postgresql-original.svg" width="34" alt="Postgres"/>
<img src="assets/icons/angular-original.svg" width="34" alt="Angular"/>
<img src="assets/icons/docker-original.svg" width="34" alt="Docker"/>
</p>
TypeScript (ESM, strict) / Node.js 22+ / Fastify 5 / Drizzle ORM / ParadeDB (BM25 + pgvector) / pg-boss / tree-sitter / MCP SDK / Angular 21 / Vitest + Testcontainers / Docker
---
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessUnresponsive