MSL 4400734867 feat(privacy): warn when LLM tier sends content to external API
4 files changed, 248 insertions, 0 deletions. 7 new tests (4 unit + 3 integration), all RED-first.

Per @milla-jovovich's question to @igorls during PR #1221 review: users
running `mempalace init` with an external LLM provider (Anthropic API,
OpenAI hosted, etc.) need a clear, explicit warning that their folder
content will be sent to the provider, that MemPalace doesn't control
how the provider logs/retains/uses that data, and how to opt out.
@igorls confirmed this should be a small follow-up PR scoped to the
warning itself, before the v3.3.4 tag.

This PR adds:

- `_endpoint_is_local(url)` helper in `mempalace/llm_client.py` —
  URL-based heuristic returning True if the hostname is on the user's
  machine or private network. Covers: localhost, 127.0.0.1, ::1,
  hostnames ending in .local (mDNS/Bonjour), IPv4 RFC1918 ranges
  (10/8, 172.16-31/12, 192.168/16), and IPv6 unique-local addresses
  (fc00::/7).

- `is_external_service` property on the `LLMProvider` base class.
  Subclasses inherit; the URL determines (no provider-specific
  hardcoding). This means: Ollama on localhost = local. LM Studio on
  LAN = local. Anthropic with default `https://api.anthropic.com` =
  external. A user proxying Anthropic through localhost (advanced
  setup) = local, no false-positive warning.

- One-line warning print in `cmd_init` after successful provider
  acquisition, gated on `is_external_service`:

      ⚠ {provider_name} is an EXTERNAL API. Your folder content will be
      sent to the provider during init. MemPalace does not control how
      the provider logs, retains, or uses your data. Pass --no-llm to
      keep init fully local.

  The warning fires AFTER `LLM enabled: ...` so users see both that
  the LLM is engaged AND the privacy implications of where it lives,
  before Pass 0 / entity detection actually runs.

LOCAL providers (Ollama on localhost, LM Studio on localhost or LAN,
llama.cpp on localhost, vLLM on localhost) DO NOT trigger the warning —
nothing leaves the user's machine/network in those configurations.

TDD: 7 tests added across 2 files.

Unit tests in `tests/test_llm_client.py` (4 tests, all RED-first):

1. test_ollama_provider_default_endpoint_is_local — pins that the
   default `http://localhost:11434` is classified local.
2. test_openai_compat_provider_localhost_endpoint_is_local — covers
   the LM Studio / llama.cpp / vLLM common case (localhost,
   127.0.0.1, and 192.168.x LAN).
3. test_openai_compat_provider_cloud_endpoint_is_external — pins
   that pointing openai-compat at https://api.openai.com (or any
   non-local URL) classifies as external.
4. test_anthropic_provider_default_endpoint_is_external — pins that
   AnthropicProvider's default endpoint is external (the dominant
   user-facing case for `--llm-provider anthropic`).

Integration tests in `tests/test_corpus_origin_integration.py` (3 tests,
RED-first; 1 was the critical RED — the other 2 passed by accident
since nothing printed "EXTERNAL API" before this PR):

5. test_init_prints_privacy_warning_when_provider_is_external —
   captures stdout from cmd_init with a mocked external provider,
   asserts the warning text contains "EXTERNAL API" + "--no-llm" +
   language about MemPalace not controlling provider behavior.
6. test_init_no_privacy_warning_when_provider_is_local — same flow
   with a mocked local provider, asserts the warning text does NOT
   appear.
7. test_init_no_privacy_warning_with_no_llm_flag — pins the --no-llm
   path: no provider acquisition attempted, no warning fires.

Tests: 1382 total mempalace tests pass. 2 pre-existing environmental
failures unrelated to this change (chromadb optional dep). Ruff check +
format both clean.

Backwards compatible: `is_external_service` is a new property; existing
callers don't reference it. The warning is a new print statement that
fires only when an external endpoint is acquired. The `--no-llm` opt-out
existed before this PR and continues to work identically.

Out of scope for follow-up (deliberately not in this PR per Igor's
"small PR" guidance): Tailscale CGNAT (100.64.0.0/10) treatment,
pre-init confirmation prompt, persistent privacy-mode config flag,
explicit cloud-provider name detection. Tracked for future iteration.
2026-04-26 14:43:20 -07:00
2026-04-23 16:44:22 -07:00
2026-04-23 16:44:22 -07:00
2026-04-16 21:46:03 -03:00

Caution

Scam alert. The only official sources for MemPalace are this GitHub repository, the PyPI package, and the docs site at mempalaceofficial.com. Any other domain — including mempalace.tech — is an impostor and may distribute malware. Details and timeline: docs/HISTORY.md.

MemPalace

MemPalace

Local-first AI memory. Verbatim storage, pluggable backend, 96.6% R@5 raw on LongMemEval — zero API calls.


What it is

MemPalace stores your conversation history as verbatim text and retrieves it with semantic search. It does not summarize, extract, or paraphrase. The index is structured — people and projects become wings, topics become rooms, and original content lives in drawers — so searches can be scoped rather than run against a flat corpus.

The retrieval layer is pluggable. The current default is ChromaDB; the interface is defined in mempalace/backends/base.py and alternative backends can be dropped in without touching the rest of the system.

Nothing leaves your machine unless you opt in.

Architecture, concepts, and mining flows: mempalaceofficial.com/concepts/the-palace.


Install

pip install mempalace
mempalace init ~/projects/myapp

Quickstart

# Mine content into the palace
mempalace mine ~/projects/myapp                    # project files
mempalace mine ~/.claude/projects/ --mode convos   # Claude Code sessions (scope with --wing per project)

# Search
mempalace search "why did we switch to GraphQL"

# Load context for a new session
mempalace wake-up

For Claude Code, Gemini CLI, MCP-compatible tools, and local models, see mempalaceofficial.com/guide/getting-started.


Benchmarks

All numbers below are reproducible from this repository with the commands in benchmarks/BENCHMARKS.md. Full per-question result files are committed under benchmarks/results_*.

LongMemEval — retrieval recall (R@5, 500 questions):

Mode R@5 LLM required
Raw (semantic search, no heuristics, no LLM) 96.6% None
Hybrid v4, held-out 450q (tuned on 50 dev, not seen during training) 98.4% None
Hybrid v4 + LLM rerank (full 500) ≥99% Any capable model

The raw 96.6% requires no API key, no cloud, and no LLM at any stage. The hybrid pipeline adds keyword boosting, temporal-proximity boosting, and preference-pattern extraction; the held-out 98.4% is the honest generalisable figure.

The rerank pipeline promotes the best candidate out of the top-20 retrieved sessions using an LLM reader. It works with any reasonably capable model — we have reproduced it with Claude Haiku, Claude Sonnet, and minimax-m2.7 via Ollama Cloud (no Anthropic dependency). The gap between raw and reranked is model-agnostic; we do not headline a "100%" number because the last 0.6% was reached by inspecting specific wrong answers, which benchmarks/BENCHMARKS.md flags as teaching to the test.

Other benchmarks (full results in benchmarks/BENCHMARKS.md):

Benchmark Metric Score Notes
LoCoMo (session, top-10, no rerank) R@10 60.3% 1,986 questions
LoCoMo (hybrid v5, top-10, no rerank) R@10 88.9% Same set
ConvoMem (all categories, 250 items) Avg recall 92.9% 50 per category
MemBench (ACL 2025, 8,500 items) R@5 80.3% All categories

We deliberately do not include a side-by-side comparison against Mem0, Mastra, Hindsight, Supermemory, or Zep. Those projects publish different metrics on different splits, and placing retrieval recall next to end-to-end QA accuracy is not an honest comparison. See each project's own research page for their published numbers.

Reproducing every result:

git clone https://github.com/MemPalace/mempalace.git
cd mempalace
pip install -e ".[dev]"
# see benchmarks/README.md for dataset download commands
python benchmarks/longmemeval_bench.py /path/to/longmemeval_s_cleaned.json

Knowledge graph

MemPalace includes a temporal entity-relationship graph with validity windows — add, query, invalidate, timeline — backed by local SQLite. Usage and tool reference: mempalaceofficial.com/concepts/knowledge-graph.

MCP server

29 MCP tools cover palace reads/writes, knowledge-graph operations, cross-wing navigation, drawer management, and agent diaries. Installation and the full tool list: mempalaceofficial.com/reference/mcp-tools.

Agents

Each specialist agent gets its own wing and diary in the palace. Discoverable at runtime via mempalace_list_agents — no bloat in your system prompt: mempalaceofficial.com/concepts/agents.

Auto-save hooks

Two Claude Code hooks save periodically and before context compression: mempalaceofficial.com/guide/hooks.


Requirements

  • Python 3.9+
  • A vector-store backend (ChromaDB by default)
  • ~300 MB disk for the default embedding model

No API key is required for the core benchmark path.

Docs

Contributing

PRs welcome. See CONTRIBUTING.md.

License

MIT — see LICENSE.

S
Description
Server-mode fork of MemPalace — shared Docker container on Unraid so Claude Code, Codex, and MCP clients can share one persistent AI memory palace over LAN
Readme MIT 17 MiB
Languages
Python 99.2%
Shell 0.7%