Skip to content

Commit eb27e00

Browse files
Samuel LEGROSKunalG67claude
committed
mcp: treat empty/whitespace wing or room as no filter in tool_search
Port of upstream 9947ad0 (PR MemPalace#1097) — LLM agents tend to fill optional parameters with "" rather than omitting them. Without this normalization, wing=" " (whitespace-only) is truthy in searcher.py and gets passed as a literal filter, scoping the search to a non-existent empty wing and returning zero results. Adapted: upstream centralizes through a _sanitize_optional_name helper that we don't have. Inlined the strip-and-empty-as-None at the entry point of tool_search instead, which is the only call site with this pattern in our fork (tool_list_rooms uses `if wing:` already-falsy on "", and tool_find_tunnels accepts no LLM-driven optional filters). Upstream: MemPalace@9947ad0 Co-authored-by: Kunal Garhewal <kunalgarhewal13@gmail.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0ec4b8c commit eb27e00

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

mempalace/mcp_server.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ def tool_get_taxonomy():
159159

160160

161161
def tool_search(query: str, limit: int = 5, wing: str = None, room: str = None):
162+
# LLM agents tend to fill every optional parameter with "" rather than
163+
# omitting it. Treat empty/whitespace-only wing/room as no filter so the
164+
# search isn't silently scoped to a non-existent empty wing/room.
165+
if isinstance(wing, str) and not wing.strip():
166+
wing = None
167+
if isinstance(room, str) and not room.strip():
168+
room = None
162169
return search_memories(
163170
query,
164171
palace_path=_config.palace_path,

tests/test_mcp_server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,32 @@ def fake_handler(**kwargs):
138138
assert calls == [{}]
139139

140140

141+
# ── tool_search: empty/whitespace wing/room treated as no filter (upstream #1097)
142+
143+
144+
def test_tool_search_empty_wing_room_means_no_filter(monkeypatch):
145+
"""LLMs often fill optional params with "" instead of omitting them.
146+
147+
Empty or whitespace-only wing/room must be normalized to None before
148+
reaching search_memories — otherwise the search gets silently scoped
149+
to a non-existent empty filter and returns 0 results.
150+
"""
151+
captured = {}
152+
153+
def fake_search_memories(query, palace_path=None, wing=None, room=None, n_results=5):
154+
captured["wing"] = wing
155+
captured["room"] = room
156+
return {"results": []}
157+
158+
monkeypatch.setattr(mcp_server, "search_memories", fake_search_memories)
159+
160+
mcp_server.tool_search("hello", wing="", room=" ")
161+
assert captured == {"wing": None, "room": None}
162+
163+
mcp_server.tool_search("hello", wing="wing_code", room="")
164+
assert captured == {"wing": "wing_code", "room": None}
165+
166+
141167
def test_tools_call_unknown_tool_returns_error():
142168
"""Unknown tool name yields a JSON-RPC error, not a crash."""
143169
request = {

0 commit comments

Comments
 (0)