feat: add mempalace-mcp entry point for uv compatibility#805
Open
ichoosetoaccept wants to merge 2 commits intoMemPalace:developfrom
Open
feat: add mempalace-mcp entry point for uv compatibility#805ichoosetoaccept wants to merge 2 commits intoMemPalace:developfrom
ichoosetoaccept wants to merge 2 commits intoMemPalace:developfrom
Conversation
d839f2a to
e2a9e79
Compare
3 tasks
rosschurchill
added a commit
to rosschurchill/mempalace
that referenced
this pull request
Apr 18, 2026
…1 integrity bundle Phase 6 pays the debt surfaced by the advisor review of Phases 0–5: one regression we introduced, four "already fixed" claims we never verified, deferred quick wins, and the P1 MemPalace#934 data-loss bundle. No new features. 1024 tests passing, all lint clean. ── Part A: Regressions and empirical verification ── A1. HTTP-mode embedding guard regression (REAL BUG WE INTRODUCED): Phase 5 made write_palace_meta() a no-op in HTTP mode so palace_meta.json never got written — the Phase 2 model-drift warning was silently defeated in the multi-client scenario where drift is most likely. Fix: store embedding_model in ChromaDB's collection.metadata (works in both HTTP and embedded modes), keep palace_meta.json as a local cache for embedded-only callers. Added set_metadata() to the ChromaCollection adapter that strips hnsw:* keys (immutable by design). A1b. Settings mutation bug (found while fixing A1): _CHROMA_SETTINGS was a shared module-level Settings object. ChromaDB mutates it during HttpClient init by writing chroma_server_host/port into it — a subsequent PersistentClient using the SAME object would then silently switch to HTTP and fail with "Could not connect to a Chroma server" even when MEMPALACE_CHROMA_URL was unset. Replaced with _chroma_settings() factory that returns a fresh Settings per call. A2. Verification tests (tests/test_verification.py, 10 new tests): Each claim in the Phase 1–5 commits is now backed by a real test: MemPalace#590 — JSONL tool_result content preserved (unique marker survives) MemPalace#608 — Second backend sees first backend's writes (cache invalidates) MemPalace#655 — add_triple, evolve_fact, REM bridges all dedup correctly MemPalace#816 — MCP handles tools/call with extra Gemini-style fields MemPalace#903 — HTTP-mode embedding guard fires on mismatch, silent on match ── Part B: Deferred quick wins ── B1. MemPalace#847 — `mempalace status --palace /x` now works. Previous code only accepted --palace BEFORE the subcommand. Added per-subcommand --palace via parents=[palace_parent] and a merge step that falls back to the top-level arg. Both positions work now. B3. MemPalace#805 — mempalace-mcp entry point added to pyproject.toml. Enables `uvx mempalace-mcp` installation. B4. PreCompact timeout logging (MemPalace#906/MemPalace#941/MemPalace#949 root cause): _mine_sync() caught subprocess.TimeoutExpired silently — masking data loss as success. Now logs explicitly with transcript path and duration so hook.log shows exactly when mining failed to complete. B5. REM cycle per-query timeout guard: col.query() calls now run in a ThreadPoolExecutor with 10s timeout. A single stuck query no longer stalls the entire scan. Added queries_timed_out counter to the result. B6. _get_all_wings 30s TTL cache: Was paging through the entire palace on every explain() call (O(N)). Now cached keyed by id(col) with 30s TTL. ── Part C: MemPalace#934 P1 data-integrity bundle (all 7 items) ── C1. repair.py — upsert loop wrapped in try/except, restores from chroma.sqlite3.backup on any failure. No more partial-rebuild data loss. C2. migrate.py — atomic palace swap via os.rename(palace → .old) + os.rename(temp → palace). Crash at any point leaves one intact. C3. cli.py cmd_repair — offset += len(batch["ids"]) not batch_size, and break on empty batch. No more silently-skipped drawers. C4. mcp_server.py tool_diary_write — topic now passes through sanitize_name(), rejecting path traversal/null bytes/overlong strings. C5. closet_llm.py — JSONDecodeError now retries (with backoff) up to 3 attempts. LLM non-determinism no longer permanently skips files. C6. mcp_server.py tool_reconnect — now resets _metadata_cache and _metadata_cache_time (was leaking stale metadata for 5s TTL). C7. exporter.py — refuses symlinked output_dir or wing dirs. Prevents attackers pre-seeding symlinks to redirect export data. ── Part D/E: New issue cleanup + UX docs ── D1. MemPalace#923 — oversized files (>10MB) now logged with size + limit. Users can see exactly why an expected file wasn't mined. D3. MemPalace#929 — verified: non-ASCII diary round-trip works correctly after our Phase 0 ensure_ascii=False fix. Test covers Chinese + arrows + stars + check/cross chars. E1. docs/RETRIEVAL_TOOLS.md — one-page decision guide for search vs explain vs whisper. Addresses the UX regression from having 3 overlapping "find stuff" tools. ── Tests ── 16 new tests across test_verification.py (10) and test_phase6_integrity.py (6). Total: 1024 passing, 1 pre-existing env-related failure (unchanged). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds support for installing MemPalace with uv, the fast Python package manager that's become the standard (for many) for modern Python tooling.
When MemPalace is installed via
uv tool install mempalace, the MCP server and hooks fail because they hardcodepython3 -m mempalace.mcp_server— which hits the system Python that doesn't have chromadb or other dependencies. The uv-managed venv has everything, but nothing points to it.This PR adds a dedicated
mempalace-mcpconsole script entry point and updates all configs and hooks to use it. Bothpip installanduv tool installcreate the same entry point, so this is fully backwards compatible.Changes
mempalace-mcp = "mempalace.mcp_server:main"in pyproject.toml.claude-plugin/.mcp.json,.claude-plugin/plugin.json,.codex-plugin/plugin.jsonnow usemempalace-mcpinstead ofpython3 -m mempalace.mcp_serverclaude-plugin,codex-plugin,hooks/) now usemempalaceCLI entry point instead ofpython3 -m mempalacemempalace mcpnow printsmempalace-mcpas the setup commanduv tool install mempalaceas recommended install methodtest_mcp_entrypoint.pyverifying entry point, configs, and hooks don't regressWhat stays the same
python -m mempalace.mcp_serverstill works (for existing setups)python3 -ccalls in legacy hooks untouched (stdlib-only JSON parsing, no mempalace imports)mempalace-mcpis the MCP server entry pointHow to test
Checklist
python -m pytest tests/ -v)ruff check .)