Skip to content

voycel/Gemini-Recall

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gemini Memory MCP v2

Grounded, repository-bound historical memory for MCP coding agents, backed by Google Gemini File Search.

The server stores deliberate project summaries and selected project files, then retrieves narrowly relevant passages with source metadata. Its output is historical, advisory, and untrusted: current repository files, tests, runtime state, and production evidence always take precedence.

What it does

  • Binds project-specific reads and all writes to an explicit repository path.
  • Stores redacted summaries with observation time, recording time, freshness, sensitivity, content hash, and (when available) Git commit metadata.
  • Retrieves focused context with citations and abstains when File Search returns no grounded evidence.
  • Reads existing legacy stores when their identity is unambiguous. On the first new write, it creates an embedding-2 shadow store, writes there, and searches the new and legacy stores together while the legacy store remains available.
  • Deduplicates repeated session summaries and project files locally by content hash.
  • Audits store counts, empty stores, legacy embeddings, aliases, and safety settings without reading document contents.

It does not provide live project truth, replace source control or backups, automatically create memory for every task, upload raw transcripts, or install compaction hooks. It is not a secret vault. Cross-project, name-only reads must be explicitly enabled by the caller.

Architecture

MCP client or gmem CLI
        |
        v
repository identity + safety policy
        |
        +--> permission-restricted local registry
        |      (path bindings and content hashes)
        |
        v
async Gemini gateway with bounded retries
        |
        v
Gemini File Search store --> grounded answer + normalized citations

The local repository fingerprint is derived from the Git remote when available, or from the resolved local path otherwise. The path itself is not sent as the fingerprint. Stored content and metadata are sent to Google Gemini File Search.

All audited legacy stores use models/gemini-embedding-001, whose published shutdown date is 14 July 2026. V2 protects new writes with models/gemini-embedding-2; it cannot losslessly re-embed old cloud-only documents because File Search does not expose their original contents for download. See Migration.

Install

Requirements: Python 3.11+, uv, a Gemini API key, and a supported operating-system keyring.

cd /path/to/Gemini-Memory-MCP-v2
uv sync --all-groups
uv run gmem key set

gmem key set reads the key without echoing it and stores it under the gemini-memory-mcp service in the OS keyring. GEMINI_API_KEY remains available for ephemeral environments, but should not be written into client configuration or committed files.

Configure Codex and Claude

The migration script updates the clients to run this checkout, removes matching legacy memory/compaction hooks, and removes plaintext Gemini keys from their MCP entries. It is a dry run unless --apply is supplied.

uv run python scripts/configure_clients.py
uv run python scripts/configure_clients.py --apply

Apply mode creates a permission-restricted backup before changing client files. The Codex registration uses a 300-second tool timeout so bounded listing, fallback, ingestion, and retry sequences are not cancelled by the client first. Restart Codex and Claude after applying; already-running MCP processes do not reload their configuration. See Migration before replacing an existing installation.

For another MCP client, register this checkout's .venv/bin/python as the command and the absolute path to server.py as its only argument. Do not put the API key in that registration.

MCP tools

Tool Purpose
gemini_memory_create_store Create repository-bound memory deliberately.
gemini_memory_retrieve_context Retrieve focused, cited historical context.
gemini_memory_save_session Save one meaningful, redacted summary.
gemini_memory_upload_file Upload one secret-scanned UTF-8 text file inside the repository.
gemini_memory_list_stores List store and document-state counts.
gemini_memory_list_documents List document metadata, not document contents.
gemini_memory_audit Run a read-only operational and safety audit.
gemini_memory_health Check provider access and non-secret configuration.
gemini_memory_consolidate Report eligibility only; unsafe v1 deletion is disabled.
gemini_memory_delete_document Delete one path-bound document with exact-name confirmation.
gemini_memory_delete_store Delete one path-bound store with exact-name confirmation.

Normal calls should pass the active project_path. Name-only retrieval or listing is rejected unless allow_cross_project=true is deliberately supplied. Retrieval modes are focused, overview, and current_state; all three remain historical and require live verification.

Create, save, upload, and delete tools are declared non-idempotent because the provider does not expose an end-to-end idempotency key. Local locks and content hashes suppress common duplicate writes, but clients must not blindly retry a timed-out write. Inspect the resulting store or document state first. Destructive calls additionally require an exact resource-name confirmation and a project_path whose resolved binding contains that resource.

Retrieval results report searched_store_names. If a deprecated legacy shadow is rejected, they also report candidate stores and search_fallback_reason=legacy_store_unavailable_primary_only, making it clear that only the embedding-2 primary was actually searched.

Returned context is assembled only from valid provider-attributed byte spans; uncited Gemini prose is discarded. Accordingly, citation_coverage describes the returned context and is 1.0 for a successful retrieval. provider_response_citation_coverage records the raw Gemini answer ratio as a non-gating diagnostic. That raw ratio can vary because of headings and connective prose and is not used as a proxy for semantic relevance.

CLI

The CLI intentionally exposes common safe operations. Destructive deletion is available through the confirmation-gated MCP tools, not the CLI.

uv run gmem key status
uv run gmem init --path /absolute/path/to/repository
uv run gmem context "authentication decisions" --path /absolute/path/to/repository --tokens 3000
uv run gmem save --path /absolute/path/to/repository --label auth-fix \
  --message "Recorded outcome, evidence, files changed, and remaining uncertainty."
uv run gmem upload README.md --path /absolute/path/to/repository
uv run gmem docs --path /absolute/path/to/repository
uv run gmem stores
uv run gmem audit
uv run gmem health

save also accepts a summary on standard input. Save only durable decisions, verified outcomes, and useful handoff context; do not pipe raw conversations or logs into it.

Runtime settings

Variable Default Meaning
GEMINI_API_KEY OS keyring fallback Process-only credential override.
GEMINI_RETRIEVAL_MODEL gemini-3.5-flash Grounded retrieval model.
GEMINI_SUMMARY_MODEL gemini-3.5-flash Reserved summary model setting.
GEMINI_FALLBACK_MODEL gemini-3.1-flash-lite Reserved fallback model setting.
GEMINI_EMBEDDING_MODEL models/gemini-embedding-2 Embedding model for newly created stores.
GEMINI_MEMORY_MAX_TOKENS 3000 Default answer limit; valid range 500-16000.
GEMINI_MEMORY_TOP_K 8 Default File Search result count.
GEMINI_MEMORY_TIMEOUT_SECONDS 45 Request/ingestion timeout.
GEMINI_MEMORY_MAX_RETRIES 2 Bounded retries for transient failures.
GEMINI_MEMORY_STATE_DIR platform state directory Local registry location.
GEMINI_MEMORY_REDACT 1 Set to 0, false, or no only with care.
GEMINI_MEMORY_RETRIEVAL_BACKEND generate_content generate_content or interactions.

Provider availability, pricing, quotas, and retention terms can change. Check Google's current Gemini documentation rather than relying on this repository for commercial limits.

Verification

uv run ruff check .
uv run mypy src
uv run pytest
uv run gmem key status
uv run gmem health

The first three checks are local and deterministic. health uses the configured credential and makes a live provider request; it is the final configuration check before restarting clients.

The final frozen-tree release gate passed 152 tests, Ruff, and strict mypy over 16 source modules.

For repeatable existing-store retrieval probes, copy benchmark/cases.example.json, bind its project paths through environment variables, and run:

uv run python benchmark/run_live.py --cases /path/to/cases.json

The harness validates its case schema, uses isolated temporary local state by default, and reports the case-file hash, runtime/model configuration, statuses, source titles, citation coverage, latency, and expected-term checks. It does not print retrieved context.

The committed benchmark/cases.fixed.json is the exact three-case legacy-account probe used during the v2 evaluation. It deliberately contains no home-directory paths or API keys. To replay it against the same controlled projects and Gemini account:

export GEMINI_MEMORY_BENCH_APPSEED_ROOT=/path/to/appseed
export GEMINI_MEMORY_BENCH_VUELUM_ROOT=/path/to/vuelum
uv run python benchmark/run_live.py \
  --cases benchmark/cases.fixed.json \
  --output benchmark/fixed-live-results-2026-07-13.json

This live holdout depends on the named account's existing historical stores; it is reproducible evidence for this migration, not a provider-independent unit test. Empty-store behavior is covered by deterministic tests instead of a temporary cloud artifact. The deterministic suite remains the portable release gate.

The final fingerprinted legacy report is benchmark/fixed-live-results-2026-07-13.json (3/3), bound to implementation c3fdb6fc...e61b and corrected case file 3719f8fe...268. The known Appseed answer was returned in 10.192 seconds with 1.0 returned-context coverage and 0.595 raw-provider coverage; the absent nonce abstained in 11.864 seconds; and the explicit cross-project request was blocked without a provider search in 4.077 seconds.

This is post-failure corrected acceptance, not an untouched holdout. Two valid 2/3 failures are retained: the be3db68d...54eb4 positive-grounding run suppressed a useful answer under the old raw-coverage gate, and the b57b6d32...bd33 term-recall run showed that the case expected terms not needed by the question: it unnecessarily required the generic query noun mobile, even though a correct label answer need not repeat that noun. The corrected case contract was then run once on b57b6d32...bd33 and again on the final frozen tree. The 1/3 pre-offset run is also retained as earlier citation-offset and project-scope failure evidence. These artifacts show the improvement sequence; only the c3fdb6fc...e61b report is final legacy acceptance.

For a controlled provider contract check, run the synthetic holdout:

uv run python benchmark/run_synthetic.py \
  --output benchmark/synthetic-live-results-2026-07-13.json

It creates a uniquely named temporary embedding-2 store, writes the committed temporal/conflict and expired-evidence fixture, runs three case-level checks, and exact-deletes that store in a finally cleanup. The result records the fixture hash, models, source titles, citation coverage, latency, and cleanup status without printing retrieved context.

The latest controlled result is benchmark/synthetic-live-results-2026-07-13.json (3/3), bound to implementation c7799a4e...32b. All three documents were accepted using explicit text/markdown MIME metadata; temporal conflict retrieval returned both decision codes from two sources, expired evidence was suppressed, and the absent nonce abstained. Exact cleanup deleted the same store that setup created, and an independent provider inventory found zero remaining synthetic benchmark stores. The earlier fingerprinted MIME-setup failure is preserved separately; its store was also deleted and it is not acceptance evidence.

New live reports include implementation_sha256, binding the result to every Python package file, pyproject.toml, uv.lock, and the relevant runner. Case and fixture hashes remain separate. See the exact framing algorithm in the benchmark methodology.

These benchmarks test specific safety and retrieval contracts. They do not establish global answer quality or prove that memory pays for its latency on an arbitrary project. V2 is therefore intended for a guarded, focused opt-in trial; its practical value must be measured by reduced re-discovery in real work. See the full benchmark methodology.

Data retention and removal

Gemini File Search stores are remote resources. Removing this checkout, client registration, hooks, or the local key does not delete them. Inventory stores with gmem stores, then use the exact-confirmation MCP deletion tools (or the Google API) only after reviewing the full resource names. Existing v1 stores are left unchanged during migration.

gmem key delete removes only the local keyring entry. Client backups produced by configure_clients.py --apply may contain historical plaintext credentials; protect and remove them according to Security.

Operating policy

Use the global-agent snippet in Policy. The core rule is simple: retrieve once and narrowly when it will help, save only meaningful changes, and verify everything important against live evidence.

License

MIT

About

No description, website, or topics provided.

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages