#1082·mempalace

MCP tool_search returns "Error finding id" when wing-scoped to a convos-mined wing (CLI works, unscoped MCP works)

Author: raphaelsamyCreated Apr 21, 2026Updated Sep 16, 2026
Labelsbugarea/mcparea/search

Summary

MCP mempalace_search(query=..., wing=<convos-mined-wing>) fails with "Search error: Error executing plan: Internal error: Error finding id" for any wing that was created via mempalace mine ... --mode convos. The same query via CLI succeeds (mempalace search "..." --wing <wing>), and unscoped MCP search also succeeds and returns hits from the same wing mixed with others. Wing-scoped MCP search on projects-mined (code) wings is fine. The failure is specifically the combination of "MCP transport + wing filter + convos-mined wing".

Environment

  • mempalace: 3.3.2 (from PyPI — pip show mempalaceVersion: 3.3.2, sdist+wheel from https://github.com/MemPalace/mempalace/releases/tag/v3.3.2)
  • Install command: uv pip install --python $(pyenv which python3) mempalace (plugin hooks + MCP server need the system python3 on PATH to import mempalace; uv tool install isolates it and hooks fail)
  • Python: 3.12.11 via pyenv
  • OS: macOS, Darwin 25.3 (macOS 15 series, arm64)
  • Claude Code plugin: MemPalace/mempalace marketplace branch develop — plugin .claude-plugin/plugin.json v3.3.2, MCP server launched as python3 -m mempalace.mcp_server
  • Vector store: ChromaDB (default, local PersistentClient, no custom tenant/collection config)
  • Embedding model: all-MiniLM-L6-v2 (default)
  • Identity file: ~/.mempalace/identity.txt present
  • Palace location: default (~/.mempalace/palace/)

What happens

Given a palace that contains:

  • At least one projects-mined wing (e.g. sample_repo, created via mempalace mine /path/to/repo)
  • At least one convos-mined wing (e.g. chats_general, created via mempalace mine /path/to/chat-folder --mode convos --extract general --wing chats_general where the folder contains Claude Code session JSONL files)

Then from an MCP client connected to python3 -m mempalace.mcp_server:

Call Result
mempalace_search(query="decisions")unscoped OK — returns hits from the convos wing mixed with others
mempalace_search(query="decisions", wing="sample_repo") — scoped to projects wing OK — returns projects-wing hits
mempalace_search(query="decisions", wing="chats_general") — scoped to convos wing FAILS with {"error": "Search error: Error executing plan: Internal error: Error finding id"}
mempalace_search(query="decisions", wing="chats_general", room="decision") — scoped to convos wing + room FAILS with the same error
mempalace search "decisions" --wing chats_generalCLI, same wing OK — returns convos-wing hits with good similarity scores

Observed verbatim error payload returned by mempalace_search MCP tool:

json
{
  "error": "Search error: Error executing plan: Internal error: Error finding id"
}

No traceback is surfaced to the MCP client. The MCP server log (stderr of the launched python3 -m mempalace.mcp_server) shows no Python exception during the failing call — the error appears to originate from the underlying ChromaDB query engine and be wrapped by tool_search / search_memories.

Scope of failure

Reproducible on every convos-mined wing we have:

  • chats_general — wing for a folder of Claude Code session JSONLs, mined with --mode convos --extract general
  • club_prontosu_contracts — separate convos-mined wing, also --mode convos --extract general

Not reproducible on any projects-mined wing.

Affects:

  • wing filter alone
  • wing + room combined filter
  • Error persists across mempalace_reconnect MCP calls and across full MCP server process restarts

Minimal reproduction

bash
# 1. Install
uv pip install --python $(pyenv which python3) mempalace
python3 -c "import mempalace; print(mempalace.__version__)"  # should print 3.3.2

# 2. Identity
mkdir -p ~/.mempalace && echo "test-user" > ~/.mempalace/identity.txt

# 3. Projects-mined wing (control)
mkdir -p /tmp/sample_repo && echo "# sample" > /tmp/sample_repo/README.md
echo "def foo(): return 'decision: use async'" > /tmp/sample_repo/app.py
mempalace init /tmp/sample_repo --yes
mempalace mine /tmp/sample_repo
# → creates wing "sample_repo"

# 4. Convos-mined wing (the failing case)
mkdir -p /tmp/chat-folder
# place at least one Claude Code session JSONL here:
cp ~/.claude/projects/*/*.jsonl /tmp/chat-folder/  # pick any one
mempalace mine /tmp/chat-folder --mode convos --extract general --wing chats_general
# → creates wing "chats_general"

# 5. Start MCP server in another terminal
python3 -m mempalace.mcp_server

# 6. From any MCP client (Claude Code, mcp-cli, etc.):
#    Call A — works:
#      mempalace_search(query="decisions", wing="sample_repo")
#    Call B — works:
#      mempalace_search(query="decisions")                      # unscoped
#    Call C — FAILS:
#      mempalace_search(query="decisions", wing="chats_general")
#      → {"error": "Search error: Error executing plan: Internal error: Error finding id"}

# 7. CLI control — works fine against the same palace/collection:
mempalace search "decisions" --wing chats_general
# → prints hits with similarity scores, exit status 0

Command exit statuses observed in our run:

$ mempalace search "decisions" --wing chats_general ; echo "exit=$?"
... (hits printed) ...
exit=0

$ mempalace search "decisions" --wing sample_repo ; echo "exit=$?"
... (hits printed) ...
exit=0

MCP tool call (from Claude Code, via mcp__plugin_mempalace_mempalace__mempalace_search):

mempalace_search(query="decisions", wing="chats_general")
→ {"error": "Search error: Error executing plan: Internal error: Error finding id"}

mempalace_search(query="decisions")
→ {"results": [...], "count": 5}   ← includes hits from chats_general

Things tried that do NOT fix it

  • Restarting the MCP server (kill + relaunch)
  • Calling mempalace_reconnect MCP tool
  • Varying the query text ("decisions", "auth token", "bug", single-word, multi-word)
  • Swapping --wing for --room (room-only filter exhibits the same failure when the wing is a convos wing)
  • Combining wing + room filters
  • Re-mining the convos folder from scratch after deleting the wing
  • Re-creating the palace and re-mining

Hypothesis (unconfirmed)

This is speculation for the maintainer — happy to test patches.

tool_search at mempalace/mcp_server.py:428–477 calls search_memories(sanitized_query, palace_path=..., wing=wing, room=room, n_results=limit, max_distance=dist) — the same entry point the CLI mempalace search uses. The sanitization (_sanitize_optional_name) happens identically in both paths. Since CLI works and MCP doesn't with identical filter values against the same collection, the divergence must be either:

  1. Something ChromaDB-side about the way the MCP server's long-lived PersistentClient / cached collection (see #608 for the same cache pattern) resolves IDs vs. a fresh CLI-opened client, specifically when the resulting filtered candidate set crosses from the HNSW index back into metadata lookup — and only for drawer IDs minted by the convos path.

  2. Or a drawer-ID / metadata mismatch that the fresh-per-call CLI tolerates and the cached-client MCP server does not.

The drawer-ID formats differ between the two miners:

  • Projects miner (mempalace/miner.py) uses a static room interpolated into the ID.

  • Convos miner (mempalace/convo_miner.py:309–347) computes chunk_room = chunk.get("memory_type", room) if extract_mode == "general" else room (line 336) and then interpolates that per-chunk into the drawer ID:

    python
    drawer_id = f"drawer_{wing}_{chunk_room}_{hashlib.sha256((source_file + str(chunk['chunk_index'])).encode()).hexdigest()[:24]}"

    So a single convos mine produces drawers whose ID segments include room values like decision, emotional, code, etc. — not a single static room. Metadata stores room=chunk_room too. If MCP's internal Error finding id path (ChromaDB's plan executor failing to resolve an id during result assembly) is sensitive to the id vs. metadata shape in a way the fresh CLI client isn't, that would explain the reproducible asymmetry.

Whatever the root cause, the contract that "wing filter works identically via CLI and MCP" is broken for convos-mined wings.

Impact

Wing-scoped MCP retrieval is broken for all convos-mined wings. This blocks the most useful search pattern the tool enables: "give me the decisions we made about X in project Y," where Y is a per-project chat wing mined from Claude Code sessions. You can either:

  • Search unscoped (mixing all projects → noisy results), or
  • Shell out to CLI (no MCP integration benefits)

For users who structure their palace around one-convos-wing-per-project, this effectively disables per-project memory retrieval via MCP.

Current workaround

  • Use unscoped mempalace_search and accept cross-wing noise, or
  • Shell out to mempalace search ... --wing <wing> via a Bash tool call from the MCP client

Both are strictly worse than wing-scoped MCP search working correctly.

Relevant source (v3.3.2)

Not related to

  • #1049 (missing mempalace-mcp entry point on PyPI 3.3.2) — our MCP server is running fine via python3 -m mempalace.mcp_server; unscoped search works; only the wing-filtered convos-wing path fails.
  • #608 (stale-cache HNSW) — our results aren't stale, they're an outright error; also the CLI and unscoped MCP both succeed concurrently.

Happy to collect additional diagnostics (stderr logs from the MCP process, ChromaDB debug logs, sample palace) if helpful.