github-rag-mcp
Provides hybrid search across GitHub issues, pull requests, releases, documentation, and more, enabling AI agents to retrieve and reason about project state from durable artifacts.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@github-rag-mcpSearch for issues about embedding pipeline"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
github-rag-mcp
Language: English | Japanese
GitHub issue, pull request, release, and documentation search for MCP clients on Cloudflare Workers.
github-rag-mcp is designed as a shared working memory over GitHub. It does not try to remember every conversation. Instead, it helps agents recover the current project state from durable artifacts that humans can also inspect: issues, pull requests, docs, and releases.
It is the search-oriented counterpart to github-webhook-mcp. Together they provide both:
push-based awareness of what just happened
hybrid retrieval (dense + sparse) of the state that matters for the next step
Breaking change: MCP protocol revision 2026-07-28
From this release the Worker serves MCP protocol revision 2026-07-28 only. It keeps no compatibility lane for the previous revision.
Bridge versions older than this release stop working. They open a session with
initialize, which the Worker no longer answers. The failure is quiet: the bridge does not crash, it returns the protocol error as tool output text.Restart Claude Desktop to pick up the new bridge. The bridge is launched with
npx, and@latestis resolved at process start — an already-running Claude Desktop keeps the copy it started with, however new the published version is. Quit it fully and reopen.Pinning the bridge version leaves you stuck. If your MCP client config pins a version older than this release, restarting does not help; remove the pin (or move it forward) first.
The Worker and the bridge ship together, so a bridge from this release or later needs no configuration change.
Related MCP server: Documentation MCP Server
Memory Model
The project treats GitHub as a visible state store for AI work.
Do not aim for complete memory.
Do not add unnecessary material.
Do not omit information required for the next correct action.
Preserve state in human-readable, reviewable artifacts.
Recover context by search instead of replaying full chat history.
For a fuller explanation, see:
Architecture
GitHub webhooks + GitHub API
|
v
Cloudflare Worker
+ MCP HTTP surface
+ webhook receiver
+ cron poller (fallback)
+ embedding pipeline
+ hybrid retrieval (dense + sparse + RRF fusion + cross-encoder rerank)
|
+--> Vectorize (dense semantic index)
+--> D1 FTS5 (BM25 sparse index)
+--> Durable Object / SQLite (structured state store)
+--> Workers AI BGE-M3 (embeddings)
+--> Workers AI bge-reranker-base (cross-encoder rerank)The MCP surface exposes hybrid retrieval and context tools to AI clients.
The webhook receiver updates memory in near real time when GitHub changes.
The cron poller repairs missed updates and supports backfill.
Vectorize stores semantic embeddings for the dense side of retrieval.
D1 FTS5 stores the BM25 sparse index for exact-term and identifier queries.
The cross-encoder reranker re-scores fused candidates as the 3rd tier (toggleable per query).
Durable Object keeps structured state for fast lookups and activity views.
Why GitHub
GitHub already contains the artifacts that matter for software work:
issues for requirements and open decisions
pull requests for implementation history and review state
documentation for stabilized understanding
releases for shipped checkpoints
Using those artifacts as memory makes handoff and auditing easier than keeping state inside a private chat transcript.
Installation
See:
Versioning
Published versions come from the GitHub Release tag. The version fields committed in this repository are placeholders that CD rewrites from the tag at publish time, so they are expected to differ from the published version — see Versioning and published artifacts.
Requirements
See:
MCP Tools
This MCP server exposes a single consolidated tool. All retrieval modes — semantic search, time-ordered activity scan, inline doc content fetch, and stored-content fetch by vector_id — are reached through search via its parameter set. Earlier builds split these across get_issue_context, get_doc_content, and list_recent_activity; those tools have been removed and their use cases now fold into the parameters below.
search
Unified search across GitHub issues, pull requests, releases, repository documentation, GitHub Wiki pages, commit diffs, and comment / review surfaces (top-level comments on issues and PRs, PR review bodies, and PR inline review comments).
Four modes are selected by the parameter set:
Hybrid semantic search (default) — dense BGE-M3 over Vectorize + sparse BM25 over D1 FTS5, fused via Reciprocal Rank Fusion (RRF, k=60), then re-scored with the
@cf/baai/bge-reranker-basecross-encoder. Pass a natural-languagequery.Time-ordered activity scan — omit or leave
queryempty and setsortto"updated_desc"or"created_desc". Optionally narrow withsince/untilto list recent activity across every type. This subsumes the previouslist_recent_activitytool. The[since, until)window is applied inside the index, so any window holding rows returns rows however far back it sits; the response carriestruncated: truewhen the window holds more than one page, which is what separates "no such rows" from "the read stopped short". Walk backwards by re-issuing the scan withuntilset to the oldest row returned.Doc / wiki content fetch — set
include_content: true. For result rows whosetypeis"doc", the raw file content is fetched from the GitHub contents API; fortype: "wiki_doc"rows, the raw markup is fetched fromraw.githubusercontent.com/wiki/. Both are inlined as acontentfield. Capped at the first few rows of each type to bound API fan-out. This subsumes the previousget_doc_contenttool.Stored-content fetch — pass
vector_ids(thevector_idvalues carried by earlier results). Every indexed type returns the body text the index already holds for that exact row — issues, PRs, comments, reviews, releases and diffs included, not just docs — so locating something withsearchand then reading it no longer costs a round trip throughghor grep. Served from D1: no GitHub API call is made. See Stored-content fetch below for what the returned text is and is not.
Structured filters (repo, state, labels, milestone, assignee, type) apply in every mode except stored-content fetch, where the rows are named rather than selected.
Search mode reports filters that matched nothing at all in filters_unmatched (always present, [] when every filter matched something). repo is an exact match on the full owner/repo slug, so a bare repository name selects an empty population and returns a response shaped exactly like a genuine zero-hit search — this field is what separates the two. It matters most in multi-step agentic search, where a zero reads as a normal intermediate result and the mis-specified filter would otherwise never surface.
Bot-authored comments (sender.login ending in [bot]) and comments shorter than 10 characters (trimmed) are filtered out at ingest time so noise such as LGTM, +1, or CI chatter does not dilute the retrieval surface.
Parameters
Name | Type | Description |
| string (optional) | Natural-language query. Omit or empty = scan mode. |
| string | Filter by repository — full slug ( |
|
| Filter by state (default |
| string[] | Filter by label names (AND). |
| string | Filter by milestone title. |
| string | Filter by assignee login. |
| see below | Filter by type (default |
| number | Max results (default 10, max 50). Counts distinct entities, not index rows — see Entity aggregation below. |
|
| Fusion strategy (default |
| boolean | Cross-encoder rerank (default |
|
| Result ordering. Default |
| ISO 8601 string | Keep only results with |
| ISO 8601 string | Keep only results with |
| boolean | Inline raw content on top doc results (default |
| string[] | Stored-content fetch. The |
| boolean | Opt-in GraphRAG expansion (search mode only). When |
| number | Graph traversal depth for |
type values
Value | Surface |
| GitHub issues (title + body). |
| Pull request descriptions (title + body). |
| Release notes (name + body). |
| Markdown documentation files. |
| GitHub Wiki pages (separate surface from repo docs; both co-exist). |
| Per-file commit diffs (commit message + file path + patch). |
| Top-level comments on issues and PRs. |
| PR review bodies ( |
| PR inline review comments (per-line diff comments). |
| Union of every type above (default). |
Entity aggregation
One thing is indexed as several rows: a file is a doc row plus one diff row per commit that touched it, an issue or PR is its own row plus its comments and reviews. Those rows are collapsed into one result before the response is trimmed, so top_k returns that many distinct entities. Rows are grouped by what they point at, not by the work that produced them — different files touched by one commit stay separate results, and so do an issue and the PR that closes it.
The representative is the highest-ranked row of the group, so a query about when something changed still returns the relevant old commit diff rather than the current version. A result that absorbed other rows carries a same_entity field (count including itself, plus others[] with the type, URL, timestamp and score of each collapsed row) so nothing is lost. See docs/0-requirements.md for the full rule.
Stored-content fetch
Every result row — and every same_entity.others entry — carries a vector_id. Passing those ids back as vector_ids returns the body text the index holds for exactly those rows.
What comes back is the index's copy of the body, not the live source: it is the embedding input, truncated by the ingest pipeline at 8000 characters. Inlined text carries no mark of which it is, so the response says so — content_source: "index" and content_max_chars at the top level, content_chars and content_truncated on each row. A row flagged content_truncated: true is a prefix; read the rest from GitHub if the tail matters.
Unknown or stale ids come back in not_found and the remaining rows still return. That partial success is deliberate: vector_id is a handle for reaching a row in the result set it arrived in, not a durable identifier. The id scheme has been migrated once already, so do not store one for later use — take it from a fresh result.
This is a different axis from include_content, which is unchanged: that flag re-reads whole files from GitHub because a doc needs its full text, and it is capped to bound API fan-out. Fetch mode reads D1 and is bounded by the ids you listed.
Ids come from search-mode results only; scan-mode rows are read from the structured store and carry none. They are opaque ({type prefix}:{base64url sha256}) — copy them from a result, never build one by hand:
{
"vector_ids": [
"i:d0qhtOi9Lxc4yuMbgbDD1BvcpptqrMWpphGMGw4t79I",
"ic:kPjVFYzpd5y9Y2RWQ1KstYDZYsSDzmxhqQphaHKHHRU"
]
}{
"count": 2,
"mode": "fetch",
"requested": 2,
"content_source": "index",
"content_max_chars": 8000,
"not_found": [],
"results": [
{
"vector_id": "i:d0qhtOi9Lxc4yuMbgbDD1BvcpptqrMWpphGMGw4t79I",
"repo": "Liplus-Project/github-rag-mcp",
"type": "issue",
"state": "open",
"number": 239,
"updated_at": "2026-08-14T00:00:00Z",
"content": "feat(mcp): add vector_ids to search ...",
"content_chars": 4213,
"content_truncated": false
}
]
}Retrieval axes
Search mode reports two axes separately and never fuses them into one ranking.
Axis | Field | Ordering | Score |
Keyword |
| ranker order (RRF / rerank / time sort) |
|
Relationship |
|
| none — the graph carries no relevance value |
graph_results is present only when graph_expand: true; the default response does not carry the field at all. Its items hold identity plus graph_hop (distance from the seed) and graph_from (which seed reached them), and deliberately carry no score field: the mention graph has no weights, so absence of a score is not a score of zero. Graph-derived candidates used to arrive as score: 0 rows inside results, indistinguishable from candidates the rankers scored at zero.
Triage for the consumer: appearing on both axes is the strongest signal — two independent paths agreed. Keyword axis only = the words matched. Relationship axis only = the vocabulary did not match, but the entry is structurally adjacent to what did.
Examples
Semantic search for a specific topic:
{
"query": "rerank latency budget",
"repo": "Liplus-Project/github-rag-mcp",
"top_k": 5
}Time-ordered activity scan across the last 24 hours:
{
"sort": "updated_desc",
"since": "2026-04-22T00:00:00Z",
"top_k": 20
}Semantic search with inline doc content on the top doc hits:
{
"query": "memory philosophy",
"type": "doc",
"include_content": true,
"top_k": 3
}Search past PR review judgments about a specific topic:
{
"query": "rerank threshold tuning",
"type": "pr_review",
"top_k": 5
}Repository Structure
src/
index.ts
mcp.ts
oauth.ts
webhook.ts
pipeline.ts
github-ip.ts
poller.ts
store.ts
types.ts
docs/
0-requirements.md
0-requirements.ja.md
1-memory-philosophy.md
1-memory-philosophy.ja.md
installation.md
installation.ja.md
mcp-server/
wrangler.tomlRelated
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseCqualityDmaintenanceEnables AI models to access GitHub repository contents as context, with features to fetch entire repositories, specific file contents, and repository structures for use in AI interactions.31112MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to search and query documentation from git repositories using hybrid search and structured metadata queries.1
- AlicenseAqualityBmaintenanceTurns any GitHub repository into your organisation's persistent context layer, enabling AI agents to read, search, and propose updates via pull requests.125MIT
- AlicenseNot gradedqualityCmaintenanceEnables LLM agents to search, read, and create GitHub issues and pull requests via natural language, using the GitHub API.1MIT
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Liplus-Project/github-rag-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server