mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d528e5619 |
@@ -62,6 +62,21 @@ uv tool install basic-memory
|
||||
|
||||
You can view shared context via files in `~/basic-memory` (default directory location).
|
||||
|
||||
## Documentation
|
||||
|
||||
### MCP Tool Usage Guide
|
||||
|
||||
For comprehensive documentation on all available MCP tools with examples and usage patterns, see:
|
||||
|
||||
**[MCP Tool Usage Guide](docs/mcp-tool-usage.md)** - Complete reference for all 16 MCP tools including:
|
||||
- Content Management (write_note, read_note, edit_note, etc.)
|
||||
- Knowledge Graph Navigation (build_context, recent_activity, list_directory)
|
||||
- Search & Discovery (search_notes with advanced syntax)
|
||||
- Project Management (list_memory_projects, create_memory_project, etc.)
|
||||
- Visualization (canvas for Obsidian)
|
||||
|
||||
This guide is perfect for creating custom instructions for your LLM or learning how to integrate Basic Memory into your workflows.
|
||||
|
||||
### Alternative Installation via Smithery
|
||||
|
||||
You can use [Smithery](https://smithery.ai/server/@basicmachines-co/basic-memory) to automatically configure Basic
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,272 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate markdown documentation for Basic Memory MCP tools.
|
||||
|
||||
This script extracts tool documentation and usage examples from MCP tool files
|
||||
and generates a comprehensive markdown document that users can easily reference
|
||||
when creating instructions for their LLMs.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
def extract_function_signature(node: ast.FunctionDef) -> str:
|
||||
"""Extract a clean function signature from an AST node."""
|
||||
args = []
|
||||
for arg in node.args.args:
|
||||
arg_name = arg.arg
|
||||
# Skip self, cls, context parameters
|
||||
if arg_name in ["self", "cls", "context"]:
|
||||
continue
|
||||
# Add type annotation if available
|
||||
if arg.annotation:
|
||||
type_str = ast.unparse(arg.annotation)
|
||||
args.append(f"{arg_name}: {type_str}")
|
||||
else:
|
||||
args.append(arg_name)
|
||||
return f"({', '.join(args)})"
|
||||
|
||||
|
||||
def extract_tool_info(file_path: Path) -> Optional[Dict]:
|
||||
"""Extract tool information from a Python file."""
|
||||
try:
|
||||
with open(file_path, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
tree = ast.parse(content)
|
||||
|
||||
# Find functions decorated with @mcp.tool
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.FunctionDef):
|
||||
# Check if function has @mcp.tool decorator
|
||||
for decorator in node.decorator_list:
|
||||
if isinstance(decorator, ast.Call):
|
||||
if isinstance(decorator.func, ast.Attribute):
|
||||
if (
|
||||
decorator.func.attr == "tool"
|
||||
and isinstance(decorator.func.value, ast.Name)
|
||||
and decorator.func.value.id == "mcp"
|
||||
):
|
||||
# Extract description from decorator
|
||||
description = ""
|
||||
for keyword in decorator.keywords:
|
||||
if keyword.arg == "description":
|
||||
if isinstance(keyword.value, ast.Constant):
|
||||
description = keyword.value.value
|
||||
|
||||
# Extract docstring
|
||||
docstring = ast.get_docstring(node) or ""
|
||||
|
||||
# Extract function name and signature
|
||||
func_name = node.name
|
||||
signature = extract_function_signature(node)
|
||||
|
||||
return {
|
||||
"name": func_name,
|
||||
"signature": signature,
|
||||
"description": description.strip(),
|
||||
"docstring": docstring.strip(),
|
||||
"file": file_path.name,
|
||||
}
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error processing {file_path}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def format_tool_section(tool_info: Dict) -> str:
|
||||
"""Format a tool's documentation as a markdown section."""
|
||||
lines = []
|
||||
|
||||
# Tool header
|
||||
lines.append(f"## {tool_info['name']}")
|
||||
lines.append("")
|
||||
|
||||
# Short description from decorator
|
||||
if tool_info['description']:
|
||||
lines.append(f"**{tool_info['description']}**")
|
||||
lines.append("")
|
||||
|
||||
# Function signature
|
||||
lines.append("### Function Signature")
|
||||
lines.append("```python")
|
||||
lines.append(f"{tool_info['name']}{tool_info['signature']}")
|
||||
lines.append("```")
|
||||
lines.append("")
|
||||
|
||||
# Full docstring with examples
|
||||
if tool_info['docstring']:
|
||||
lines.append("### Documentation")
|
||||
lines.append("")
|
||||
|
||||
# Process docstring to maintain formatting
|
||||
docstring = tool_info['docstring']
|
||||
|
||||
# Split into sections
|
||||
sections = docstring.split('\n\n')
|
||||
in_code_block = False
|
||||
|
||||
for section in sections:
|
||||
# Check if this is a code example section
|
||||
if 'Examples:' in section or 'Example:' in section:
|
||||
lines.append(section)
|
||||
lines.append("")
|
||||
elif section.strip().startswith('```'):
|
||||
lines.append(section)
|
||||
lines.append("")
|
||||
else:
|
||||
# Regular text section
|
||||
lines.append(section)
|
||||
lines.append("")
|
||||
|
||||
lines.append("---")
|
||||
lines.append("")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def generate_table_of_contents(tools: List[Dict]) -> str:
|
||||
"""Generate a table of contents for all tools."""
|
||||
lines = ["## Table of Contents", ""]
|
||||
|
||||
# Group tools by category
|
||||
content_mgmt = []
|
||||
knowledge_graph = []
|
||||
search = []
|
||||
project_mgmt = []
|
||||
visualization = []
|
||||
other = []
|
||||
|
||||
for tool in tools:
|
||||
name = tool['name']
|
||||
link = f"[{name}](#{name.replace('_', '-')})"
|
||||
|
||||
# Categorize based on tool name
|
||||
if name in ['write_note', 'read_note', 'read_content', 'view_note', 'edit_note', 'move_note', 'delete_note']:
|
||||
content_mgmt.append(f"- {link}")
|
||||
elif name in ['build_context', 'recent_activity', 'list_directory']:
|
||||
knowledge_graph.append(f"- {link}")
|
||||
elif name in ['search_notes']:
|
||||
search.append(f"- {link}")
|
||||
elif name in ['list_memory_projects', 'create_memory_project', 'delete_project', 'get_current_project', 'sync_status']:
|
||||
project_mgmt.append(f"- {link}")
|
||||
elif name in ['canvas']:
|
||||
visualization.append(f"- {link}")
|
||||
else:
|
||||
other.append(f"- {link}")
|
||||
|
||||
if content_mgmt:
|
||||
lines.append("### Content Management")
|
||||
lines.extend(content_mgmt)
|
||||
lines.append("")
|
||||
|
||||
if knowledge_graph:
|
||||
lines.append("### Knowledge Graph Navigation")
|
||||
lines.extend(knowledge_graph)
|
||||
lines.append("")
|
||||
|
||||
if search:
|
||||
lines.append("### Search & Discovery")
|
||||
lines.extend(search)
|
||||
lines.append("")
|
||||
|
||||
if project_mgmt:
|
||||
lines.append("### Project Management")
|
||||
lines.extend(project_mgmt)
|
||||
lines.append("")
|
||||
|
||||
if visualization:
|
||||
lines.append("### Visualization")
|
||||
lines.extend(visualization)
|
||||
lines.append("")
|
||||
|
||||
if other:
|
||||
lines.append("### Other Tools")
|
||||
lines.extend(other)
|
||||
lines.append("")
|
||||
|
||||
lines.append("---")
|
||||
lines.append("")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to generate tool documentation."""
|
||||
# Get the project root
|
||||
script_dir = Path(__file__).parent
|
||||
project_root = script_dir.parent
|
||||
tools_dir = project_root / "src" / "basic_memory" / "mcp" / "tools"
|
||||
output_file = project_root / "docs" / "mcp-tool-usage.md"
|
||||
|
||||
print(f"Scanning tools directory: {tools_dir}")
|
||||
|
||||
# Extract tool information from all tool files
|
||||
tools = []
|
||||
for tool_file in sorted(tools_dir.glob("*.py")):
|
||||
# Skip __init__.py and utils.py
|
||||
if tool_file.name in ["__init__.py", "utils.py", "chatgpt_tools.py"]:
|
||||
continue
|
||||
|
||||
print(f"Processing: {tool_file.name}")
|
||||
tool_info = extract_tool_info(tool_file)
|
||||
if tool_info:
|
||||
tools.append(tool_info)
|
||||
print(f" Found tool: {tool_info['name']}")
|
||||
|
||||
# Sort tools alphabetically by name
|
||||
tools.sort(key=lambda x: x['name'])
|
||||
|
||||
print(f"\nGenerating documentation for {len(tools)} tools...")
|
||||
|
||||
# Generate the markdown document
|
||||
doc_lines = [
|
||||
"# Basic Memory MCP Tool Usage Guide",
|
||||
"",
|
||||
"This document provides comprehensive documentation and usage examples for all Basic Memory MCP tools.",
|
||||
"Use this as a reference when creating instructions for your LLM or integrating Basic Memory into your workflows.",
|
||||
"",
|
||||
f"**Total Tools:** {len(tools)}",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
]
|
||||
|
||||
# Add table of contents
|
||||
doc_lines.append(generate_table_of_contents(tools))
|
||||
|
||||
# Add individual tool sections
|
||||
for tool in tools:
|
||||
doc_lines.append(format_tool_section(tool))
|
||||
|
||||
# Add footer
|
||||
doc_lines.extend([
|
||||
"---",
|
||||
"",
|
||||
"## Additional Resources",
|
||||
"",
|
||||
"- [Basic Memory README](../README.md)",
|
||||
"- [CLAUDE.md Project Guide](../CLAUDE.md)",
|
||||
"- [MCP Server Implementation](../src/basic_memory/mcp/)",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
"*This documentation was automatically generated from the MCP tool source code.*",
|
||||
"*Last updated: (run `just generate-tool-docs` to regenerate)*",
|
||||
"",
|
||||
])
|
||||
|
||||
# Write the output file
|
||||
output_content = '\n'.join(doc_lines)
|
||||
output_file.write_text(output_content)
|
||||
|
||||
print(f"\n✓ Documentation generated: {output_file}")
|
||||
print(f" Total size: {len(output_content)} characters")
|
||||
print(f" Total lines: {len(doc_lines)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user