mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
fix: parse tag: prefix at MCP tool level to avoid hybrid search failure (#30)
When semantic search is enabled (default), `search_notes(query="tag:security")` failed because the HYBRID retrieval mode requires non-empty text, but the service-layer tag: parser clears the text after the mode is already set. Parse tag: prefix at the tool level before search mode selection, converting it to a tags filter. This works with all search modes (text, hybrid, vector). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""Search tools for Basic Memory MCP server."""
|
||||
|
||||
import re
|
||||
from textwrap import dedent
|
||||
from typing import List, Optional, Dict, Any, Literal
|
||||
|
||||
@@ -302,9 +303,9 @@ async def search_notes(
|
||||
- `search_notes("work-project", "category:observation")` - Filter by observation categories
|
||||
- `search_notes("team-docs", "author:username")` - Find content by author (if metadata available)
|
||||
|
||||
**Note:** `tag:` shorthand requires `search_type="text"` when semantic search is enabled
|
||||
(the default is hybrid). Alternatively, use the `tags` parameter for tag filtering with
|
||||
any search type: `search_notes("project", "query", tags=["my-tag"])`
|
||||
**Note:** `tag:` shorthand is automatically converted to a `tags` filter, so it works
|
||||
with any search type (text, hybrid, vector). You can also use the `tags` parameter
|
||||
directly: `search_notes("project", "query", tags=["my-tag"])`
|
||||
|
||||
### Search Type Examples
|
||||
- `search_notes("my-project", "Meeting", search_type="title")` - Search only in titles
|
||||
@@ -438,6 +439,16 @@ async def search_notes(
|
||||
note_types = note_types or []
|
||||
entity_types = entity_types or []
|
||||
|
||||
# Parse tag:<value> shorthand at tool level so it works with all search modes.
|
||||
# Without this, hybrid/vector modes fail because they require non-empty text,
|
||||
# but the service-layer tag: parser clears the text after the mode is set.
|
||||
if query and query.strip().lower().startswith("tag:"):
|
||||
tag_values = [t for t in re.split(r"[,\s]+", query.strip()[4:].strip()) if t]
|
||||
if tag_values:
|
||||
# Merge with any explicitly provided tags
|
||||
tags = list(set((tags or []) + tag_values))
|
||||
query = None
|
||||
|
||||
# Detect project from memory URL prefix before routing
|
||||
if project is None and query is not None:
|
||||
detected = detect_project_from_url_prefix(query, ConfigManager().config)
|
||||
|
||||
Reference in New Issue
Block a user