- Remove orphaned __api_version__ ('v0' since 2025; real API routes are /v2,
and nothing else reads the constant)
- output_schema=None so FastMCP doesn't duplicate the markdown report into
structuredContent (halves the payload)
- Add title/tags annotations so #963 and #968 are merge-order independent
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
Extends the existing _SECRET_FIELDS redaction to also strip the
user:password userinfo component from any URL-bearing config fields
(database_url) before surfacing them in diagnostics output. Adds
_redact_url() helper and a _URL_FIELDS set so future credential-bearing
URL fields are easy to add. Postgres passwords no longer leak to MCP
clients or support transcripts; host/port/db-name remain visible.
Fixes the P1 security finding raised in review of PR #963.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
Adds a new read-only MCP tool `basic_memory_diagnostics` that surfaces:
- Basic Memory package version and API version (from __init__.py)
- Python version and platform/architecture details
- Config file path and full config.json contents (cloud_api_key redacted)
Resolves#187.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
- Add Annotated descriptions to note_types and entity_types parameters so
LLMs can distinguish frontmatter type filtering from knowledge graph item
type filtering (search.py, ui_sdk.py)
- Lowercase note_types values at filter time so "Chapter" matches stored
"chapter"
- Fix misleading entity_types references in schema.py guidance strings
(should be note_types)
- Add permalink pattern documentation note about full path matching
- Add test for note_types case-insensitive lowercasing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Both search() and fetch() read default_project from ConfigManager,
which returns None in cloud mode. Remove the manual ConfigManager
lookup and let the underlying search_notes/read_note resolve the
project via get_project_client(), which works in both modes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
🔧#640 — LinkResolver selects worst match instead of best
Replace `min(results, key=lambda x: x.score)` with `results[0]`.
Both SQLite and Postgres return results sorted best-first in SQL,
so using `results[0]` is backend-agnostic and correct.
🔧#641 — search_notes output_format="text" returns raw Pydantic model
Add `_format_search_markdown()` that formats SearchResponse as readable
markdown with title, permalink, score, and matched snippet per result.
Update prompts to use `output_format="json"` since they need structured
data for result counting and branching logic.
🔧#642 — metadata_filters with `note_type` key returns empty results
Add `_METADATA_KEY_ALIASES` mapping at the tool level that aliases
`note_type` → `type` before passing metadata_filters to the search query.
The frontmatter field is `type`, not `note_type`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>