One MCP server that fetches, caches and digests context for Claude.
Point it at a GitHub repository and get back a digest small enough to read. Keep facts across conversations in two plain files you can open yourself. Everything runs locally over stdio.
claude mcp add gopher --scope user -- \
uv run --no-sync --project /path/to/gopher gopher
GitHub
A whole repository as markdown: directory tree plus the files that matter. Binaries, lock files and node_modules filtered out, the rest ranked.
Memory that survives the conversation, stored as a structured context.json and an append-only diary.md. Both readable without this tool.
Reads a transcript, pulls the facts out with a local Ollama model, and merges them into the cache. Nothing leaves the machine.
Early versions returned a fixed ten files, which is not a size limit at all: ten files is anywhere from four thousand characters to two hundred thousand. Anything past the client's ceiling was rejected whole, so the caller got nothing rather than something trimmed.
27,194 test/ecosystem/airflow/pyproject.toml
32,048 test/ecosystem/home-assistant/...
27,517 test/ecosystem/pandas/pyproject.toml
9,156 test/ecosystem/jupyterlab/...
8,757 test/ecosystem/black/pyproject.toml
228,310characters, mostly the wrong files
Cargo.toml
README.md
pyproject.toml
Dockerfile
crates/uv-build/src/main.rs
39,168characters, within budget
There is a total character budget now, spent on the tree first and then files in priority order until it runs out. Ranking accounts for where a file sits, not just what it is called, so a root manifest beats a vendored copy of the same filename buried in a test fixture.
| Repository | Before | After |
|---|---|---|
| astral-sh/uv | 207,867 | 39,321 |
| modelcontextprotocol/python-sdk | 217,488 | 39,224 |
| punkpeye/awesome-mcp-servers | 228,310 | 39,168 |
| sktime/sktime-mcp | 103,786 | 39,231 |
Facts accumulate across conversations. Reading them back used to mean returning the entire store every time, which works until it does not. Search over key paths and values, or read one section by its dot path.
read_context()
13,484characters returned
search_context("memory")
202characters returned
{
"query": "memory",
"matches": [
{
"key": "projects.precedent.note",
"value": "agentic memory hackathon, submitted",
"matched": "value"
}
],
"shown": 1,
"total": 1
}
Substring matching over keys and values, no embeddings and no index. On a store of a few hundred facts that is enough, and something cleverer can wait for evidence that it is not.
git clone https://github.com/pyarchana/gopher.git
cd gopher
uv venv
uv pip install -e ".[dev]"
cp .env.example .env
# add GITHUB_TOKEN=... to that file
claude mcp add gopher --scope user -- \
uv run --no-sync --project /absolute/path/to/gopher gopher
{
"mcpServers": {
"gopher": {
"command": "uv",
"args": ["run", "--no-sync", "--project",
"/absolute/path/to/gopher", "gopher"]
}
}
}
The digest tools additionally want Ollama running locally with
llama3.2 pulled. Fetch and cache work without it.
| Tool | What it does |
|---|---|
fetch_github_repo(repo_url) | Markdown digest of a public repo, tree plus top files |
search_context(query, limit) | Find facts whose key or value contains the query |
read_context(prefix) | The whole store, or just one section |
update_context(key, value) | Set a value at a dot path |
delete_context_key(key) | Delete a key by dot path |
log_diary(entry, tag) | Append a timestamped markdown entry |
read_diary(last_n) | Read back the last N entries |
digest_transcript(transcript_path) | Extract facts from a transcript, merge into the store |
summarize_only(transcript_path) | Same extraction, returns JSON without writing |
read_digest_log() | Full contents of the digest log |
Read from a .env file in the project root, which the server loads on startup.
| Variable | Default | Purpose |
|---|---|---|
GITHUB_TOKEN | none | Raises the GitHub rate limit from 60 to 5,000 an hour |
GOPHER_DATA_DIR | ./data | Where the store, diary and digest log live |
GOPHER_DIGEST_BUDGET | 40000 | Maximum characters one repo digest may return |
GOPHER_OLLAMA_MODEL | llama3.2 | Model used for fact extraction |