repopack MCP server
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., "@repopack MCP serversearch for rate limiting logic in the API gateway repo"
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.
repopack
Give an LLM the context of a repository — without sending the whole project over the network. Two ways to do it, one tool, zero runtime dependencies (standard library only):
pack— squeeze a repository (any language) into a single JSON file you can hand to a model, under a token ceiling you choose.serve— index your repositories locally and expose them over MCP, so a model pulls only the snippets a task needs, from all your projects, through one server.
Install
pip install -e . # or just run: python -m repopack ...Python 3.9+. No runtime dependencies — that is the point: it works on a bare interpreter.
Related MCP server: roam-code
Pack a repository
# Full pack of the current repository (any path works too)
repopack pack . -o context.json --gzip
# Incremental: only what changed since the last pack
repopack pack . --delta -o delta.json --gzip
# Restore on the other end
repopack unpack context.json -d ./restored--budget is a ceiling on the whole pack, in estimated tokens — tree, stats and the
per-file metadata count against it too, not just file content. The command prints how much of
the budget went to content and how much to structure.
How the context is organized
What is left after the structural floor is spent in three layers, in priority order (README/docs → configs/manifests → entrypoints → the rest, boosted by git churn):
full— complete content, secrets redacted, up to ~72% of what is leftskeleton— imports, signatures and docstrings: the interface survives, the bodies do not. Measured on this codebase it keeps ~22% of the original characters (13–29% per file), so treat it as "a fifth of the cost", not a tenthmetadata — path, size, sha256, language (
content: nullplus a reason)
Besides the files, a pack carries tree (every path), stats, git.recent_commits, todos
(harvested TODO/FIXME/HACK) and, in --delta mode, deleted_since_last_pack.
Byte-identical content is packed once. The other copies become pointers
(content: null, reason: duplicate_of, plus the path that carries it) — their paths stay in
the tree, and unpack resolves the pointer so every file is still restored. The highest
ranked copy is the one that keeps the content. Measured on a repository with a SKILL.md
copied into three places: duplicated content went from 0.89% to 0.00%, 8,982 characters freed
for unique context.
In a large repository the structural floor alone can exceed a small budget — 4,212 files cost
about 252k tokens in tree and metadata. When that happens the pack is generated without
file content and the tool says so on stderr, naming the floor, instead of quietly returning
26× what you asked for. Trimming the tree to fit would hide which files exist, which is
exactly what the pack promises to list.
Serve your repositories over MCP
One server, many repositories — local and remote — instead of one MCP per project.
repopack repo add . # a local repository
repopack repo add https://github.com/user/project # or a remote (shallow clone, cached)
repopack index # ingest; the second run is a no-op
repopack serve # MCP at http://127.0.0.1:7777/mcpRunning repopack serve inside a git repository registers and indexes it
automatically (--no-auto-register opts out). Only repositories that were never indexed
are ingested at startup, so restarting the server is not a full re-index.
A repository that is registered but never indexed answers nothing, so it is never silent
about it: repo_stats counts it under unindexed, and a search that comes back empty
names it and tells you to run repopack index.
Tools exposed
Tool | What it does |
| Finds snippets across every repository (or one, via |
| Reads a file, optionally a line range. |
| Known paths. |
| What is being served, when each was indexed, and the last refresh error. |
| Repositories, files, chunks, symbols, how many are failing to refresh, how many are registered but not indexed, and the code-graph health: edges by kind, average degree, isolated files, and whether the |
Protocol: revision 2026-07-28 (stateless), with a compatibility shim for clients from the
initialize era (2025-03-26 … 2025-11-25).
The code graph
repopack index builds a graph of the repository alongside the text index, and search
walks it (Personalized PageRank seeded by the lexical hits). Four kinds of edge, each
carrying a different signal:
edge | where it comes from | note |
| declared dependencies | precise, cheap, and scarce |
| who calls whom | densest signal, requires the |
| files in the same directory | weak signal that keeps docs and configs connected |
| files changed in the same commits | the only signal from history; empty on a shallow clone |
Whether the walk helps depends on the graph being dense: the ICLR'26 GraphRAG
benchmark finds graph retrieval losing to plain RAG and names sparse, fragmented graphs
as the cause. So repo_stats reports the diagnosis, not just a total — measured here:
repository | files | edges | avg degree | isolated |
repopack itself | 77 | 913 | 23.7 | 0% |
a 3-repository, 4,458-file workspace | 4,458 | 29,590 | 13.3 | 8.3% |
(A snapshot: these move as the repositories do. Run repo_stats for yours.)
Both are an order of magnitude denser than the sparse profile the paper blames, which is
the reason the walk is switched on by default here. Without the [ast] extra the call
edges disappear — the densest kind — so check graph.ast in repo_stats before reading
a thin graph as "this repository has no structure".
Automatic refresh
Remotes are refreshed in the background (--refresh-interval, default 900s, jittered;
--no-auto-refresh opts out). When a fetch fails the server keeps serving, and the
failure shows up in list_repos and repo_stats — not only in the log. Stale context served
as if it were fresh is the failure mode that visibility exists to prevent.
Security
Binds to
127.0.0.1by default. Leaving loopback (--host 0.0.0.0) requires a bearer token: if you do not pass one, the server generates it and prints it once. There is no "network without authentication" mode — the index holds the source code of every repository in the workspace.The
Originheader is validated on every request (403 when invalid), against DNS rebinding.Redaction happens at ingest, not on the way out: what is secret never enters the database, so there is no path for it to leave.
.envand its variants stay out by default (--include-envopts in, and still redacts).get_filenever serves anything outside the repository root — the same guardunpackuses.Credentials for private repositories come from your environment (ssh-agent, git helper); repopack stores no token and never prompts for a password (
GIT_TERMINAL_PROMPT=0).Secrets are redacted by pattern (API keys, GitHub/Slack tokens, JWT, private keys,
.envvariables, URLs with credentials) plus a Shannon-entropy sweep.unpackaudits each restored file against thesha256the pack carries, and warns on mismatch. The check is conclusive only for content that is intact by definition — complete, not truncated, not redacted — because a redacted file diverges from its hash by construction.
Redaction is a net, not a guarantee: it covers variable names containing SECRET/TOKEN/KEY/PASSWORD and known key formats, so a line like
MY_PLAIN=value123gets through. That is why the default for.envis to not pack the content at all, rather than trusting the filter.
What this is not
unpackis not a backup tool. It restores only content that is intact, refuses degraded content by default (naming each file and why), and never overwrites an existing file unless you pass--force. A pack is a context artifact, not a copy of your repository.skeletonmode is lossy by design. It keeps imports, signatures and docstrings and drops function bodies. Restoring a skeleton over a real file destroys the original and gives back something that will not even parse — which is why it takes--forceand says so.Skeleton extraction is regex, not a real AST. It is good enough to keep an interface readable and wrong often enough that you should not treat it as a parser. The
[ast]extra does bring real tree-sitter parsing, but it feeds the code graph, notpack --skeleton: installing it makes search better and leaves skeleton output byte-identical.
Honest limitations
Search is lexical (BM25) fused with a code-graph walk, and still has no embeddings. Measured on this repository with
repopack eval(18 questions,--no-graphreproduces the first row):ranking
recall@5
MRR
identifier
conceptual
BM25 only
83.3%
0.596
100% / 0.875
70% / 0.373
BM25 + graph (default)
94.4%
0.625
100% / 0.823
90% / 0.467
Read those absolute numbers with the ruler's granularity in mind: 18 questions means one question is worth 5.6 points, and the corpus being measured is this repository, which changes every commit. Measured: adding two files whose docstrings talk about budgets and ceilings moved recall between 88.9% and 94.4% with no ranking change at all. What the gate enforces is therefore a floor one question below the measurement, and the comparison between the two rows — both measured on the same corpus in the same run, which is the part that does not drift.
The graph costs about +212 ms per query on a 4,212-file repository (68 ms → 280 ms; on a small one it is 4.5 ms → 7.7 ms), and it costs a little position on identifier queries — which is why the lexical top hit is pinned. What it did not fix: a test file that mentions the concept still outranks the implementation for some conceptual questions. "Where is the budget enforced?" now returns
packer.pyin the top-3, but behindtest_rag_search.py. A dense ranker is still absent.Diversification (MMR) is implemented and deliberately switched off, because it did not win. Measured across λ from 1.0 down to 0.6, the one apparent gain does not survive a change of
k(at k=3 a different λ wins; at k=10 every λ ties at 100% recall while MRR falls monotonically as λ drops) — a peak that moves is one question oscillating, not an effect. The premise did not hold either: across a 3-repository, 14,606-chunk workspace the average Jaccard similarity between returned snippets is 0.04–0.08, and the only identical pairs are 3-token fixtures. Switching it on costs 4 ms → 97 ms per query.select.LAMBDAre-opens the decision, and a test refuses the change unless the ruler backs it.Cross-repo search gets noisy with many repositories and a generic query. What holds today is the token ceiling and per-repo attribution.
IDF is measured across the whole workspace. A term that is common in one project and rare in the others weighs differently than it would in an isolated search.
The local gate (
scripts/check.sh) runs on the Python versions installed on your machine, which is usually fewer than the matrix. The full 3.9–3.14 matrix is exercised by CI on every push; the three lists (classifiers, CI matrix, local gate) are cross-checked by the test suite, so they cannot drift apart in silence.
The index — and the --delta state — live in ~/.cache/repopack/ (honors XDG_CACHE_HOME;
REPOPACK_HOME overrides), never inside the repositories you scan. A --delta state left
in a repository root by an older version is still read, so your delta survives the upgrade; it
is not deleted, because removing a file from someone's repository is more invasive than having
created it.
Configuration
Create a .repopackrc (JSON) at the repository root — see .repopackrc.example.
Precedence: defaults < .repopackrc < CLI flags.
Roadmap
Ranking priors by file kind, so a test file stops taking the first slot from the implementation it tests — the one conceptual defect the graph did not fix
Diversification (MMR) and near-duplicate suppression across repositories
Optional dense ranker behind a
[rag]extra, for conceptual queriesTask-conditioned packing (
--task)
Contributing
See CONTRIBUTING.md. The one rule that is not negotiable: zero runtime dependencies.
License
MIT — see LICENSE.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
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 Connectors
An MCP server that gives your AI access to the source code and docs of all public github repos
Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceLocal MCP server that provides semantic search (RAG) over code repositories, enabling AI clients like Claude and Gemini to access project context without manual re-upload.-
- AlicenseNot gradedqualityAmaintenanceProvides local codebase intelligence as an MCP server, enabling AI agents to query dependencies, assess change impact, and produce tamper-evident change evidence packets.514Apache 2.0
- AlicenseNot gradedqualityBmaintenanceAgent-safe code retrieval MCP server that indexes repositories and provides semantic search, file navigation, call graph analysis, and bounded file reading tools for coding agents.3,448,4193AGPL 3.0
- AlicenseBqualityCmaintenanceExposes CodeGraph capabilities for multiple local repositories to MCP-compatible AI coding assistants, enabling multi-repo code exploration and cross-repo symbol tracing.5MIT
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/DiegoNogueiraDev/repopack'
If you have feedback or need assistance with the MCP directory API, please join our Discord server