mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
feat: Add enhanced prompts and resources (#15)
## Summary - Add comprehensive documentation to all MCP prompt modules - Enhance search prompt with detailed contextual output formatting - Implement consistent logging and docstring patterns across prompt utilities - Fix type checking in prompt modules ## Prompts Added/Enhanced - `search.py`: New formatted output with relevance scores, excerpts, and next steps - `recent_activity.py`: Enhanced with better metadata handling and documentation - `continue_conversation.py`: Improved context management ## Resources Added/Enhanced - `ai_assistant_guide`: Resource with description to give to LLM to understand how to use the tools ## Technical improvements - Added detailed docstrings to all prompt modules explaining their purpose and usage - Enhanced the search prompt with rich contextual output that helps LLMs understand results - Created a consistent pattern for formatting output across prompts - Improved error handling in metadata extraction - Standardized import organization and naming conventions - Fixed various type checking issues across the codebase This PR is part of our ongoing effort to improve the MCP's interaction quality with LLMs, making the system more helpful and intuitive for AI assistants to navigate knowledge bases. 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: phernandez <phernandez@basicmachines.co>
This commit is contained in:
@@ -196,7 +196,7 @@ def sync(
|
||||
|
||||
except Exception as e: # pragma: no cover
|
||||
if not isinstance(e, typer.Exit):
|
||||
logger.exception("Sync failed")
|
||||
logger.exception("Sync failed", e)
|
||||
typer.echo(f"Error during sync: {e}", err=True)
|
||||
raise typer.Exit(1)
|
||||
raise
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""Database management commands."""
|
||||
"""CLI tool commands for Basic Memory."""
|
||||
|
||||
import asyncio
|
||||
from typing import Optional, List, Annotated
|
||||
|
||||
import typer
|
||||
from loguru import logger
|
||||
from rich import print as rprint
|
||||
|
||||
from basic_memory.cli.app import app
|
||||
@@ -13,9 +14,15 @@ from basic_memory.mcp.tools import read_note as mcp_read_note
|
||||
from basic_memory.mcp.tools import recent_activity as mcp_recent_activity
|
||||
from basic_memory.mcp.tools import search as mcp_search
|
||||
from basic_memory.mcp.tools import write_note as mcp_write_note
|
||||
|
||||
# Import prompts
|
||||
from basic_memory.mcp.prompts.continue_conversation import (
|
||||
continue_conversation as mcp_continue_conversation,
|
||||
)
|
||||
|
||||
from basic_memory.schemas.base import TimeFrame
|
||||
from basic_memory.schemas.memory import MemoryUrl
|
||||
from basic_memory.schemas.search import SearchQuery
|
||||
from basic_memory.schemas.search import SearchQuery, SearchItemType
|
||||
|
||||
tool_app = typer.Typer()
|
||||
app.add_typer(tool_app, name="tools", help="cli versions mcp tools")
|
||||
@@ -82,18 +89,13 @@ def build_context(
|
||||
|
||||
@tool_app.command()
|
||||
def recent_activity(
|
||||
type: Annotated[Optional[List[str]], typer.Option()] = ["entity", "observation", "relation"],
|
||||
type: Annotated[Optional[List[SearchItemType]], typer.Option()] = None,
|
||||
depth: Optional[int] = 1,
|
||||
timeframe: Optional[TimeFrame] = "7d",
|
||||
page: int = 1,
|
||||
page_size: int = 10,
|
||||
max_related: int = 10,
|
||||
):
|
||||
assert type is not None, "type is required"
|
||||
if any(t not in ["entity", "observation", "relation"] for t in type): # pragma: no cover
|
||||
print("type must be one of ['entity', 'observation', 'relation']")
|
||||
raise typer.Abort()
|
||||
|
||||
try:
|
||||
context = asyncio.run(
|
||||
mcp_recent_activity(
|
||||
@@ -132,7 +134,7 @@ def search(
|
||||
try:
|
||||
search_query = SearchQuery(
|
||||
permalink_match=query if permalink else None,
|
||||
text=query if query else None,
|
||||
text=query if not (permalink or title) else None,
|
||||
title=query if title else None,
|
||||
after_date=after_date,
|
||||
)
|
||||
@@ -140,6 +142,7 @@ def search(
|
||||
rprint(results.model_dump_json(indent=2))
|
||||
except Exception as e: # pragma: no cover
|
||||
if not isinstance(e, typer.Exit):
|
||||
logger.exception("Error during search", e)
|
||||
typer.echo(f"Error during search: {e}", err=True)
|
||||
raise typer.Exit(1)
|
||||
raise
|
||||
@@ -155,3 +158,23 @@ def get_entity(identifier: str):
|
||||
typer.echo(f"Error during get_entity: {e}", err=True)
|
||||
raise typer.Exit(1)
|
||||
raise
|
||||
|
||||
|
||||
@tool_app.command(name="continue-conversation")
|
||||
def continue_conversation(
|
||||
topic: Annotated[Optional[str], typer.Option(help="Topic or keyword to search for")] = None,
|
||||
timeframe: Annotated[
|
||||
Optional[str], typer.Option(help="How far back to look for activity")
|
||||
] = None,
|
||||
):
|
||||
"""Continue a previous conversation or work session."""
|
||||
try:
|
||||
# Prompt functions return formatted strings directly
|
||||
session = asyncio.run(mcp_continue_conversation(topic=topic, timeframe=timeframe))
|
||||
rprint(session)
|
||||
except Exception as e: # pragma: no cover
|
||||
if not isinstance(e, typer.Exit):
|
||||
logger.exception("Error continuing conversation", e)
|
||||
typer.echo(f"Error continuing conversation: {e}", err=True)
|
||||
raise typer.Exit(1)
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user