reporelay
Self-hosted MCP server for indexing and searching code repositories via hybrid search and deep code understanding.
README
<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.
- Add repositories from any source — GitHub, GitLab, Bitbucket, on-premise, or local disk
- Index the refs you need — pick the branches and tags that matter; each gets its own versioned snapshot
- Use them everywhere — 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 or the admin dashboard. Register once, query from any project in any editor. RepoRelay parses files with 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 | 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
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 running locally with nomic-embed-text as a model.
2. Start everything
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
# 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 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
git clone https://github.com/chwoerz/reporelay.git
cd reporelay
pnpm install
2. Start Postgres
docker compose up -d postgres
This starts ParadeDB (Postgres with pgvector + pg_search).
3. Configure environment
cp .env.example .env
# Defaults work for local development — no edits needed
4. Start services
# 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
# 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 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.
# 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:
{
"mcpServers": {
"reporelay": {
"command": "npx",
"args": ["reporelay", "--server", "http://localhost:3000/mcp"]
}
}
}
See the full documentation 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:
- Detects languages from the developer's working directory
- Connects to the RepoRelay MCP server over HTTP
- Forwards all MCP requests, injecting detected languages into tool calls
# 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:
{
"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.
{
"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, including:
- Indexing pipeline deep-dive
- MCP tools, resources & prompts reference
- REST API reference (18 endpoints)
- Configuration reference
- Database design
- Project structure
- Tech stack
Testing
Comprehensive test suite (unit + integration) covering every module.
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.
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
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.