diff --git a/src/basic_memory/mcp/tools/write_note.py b/src/basic_memory/mcp/tools/write_note.py index 479595ef..5961c36f 100644 --- a/src/basic_memory/mcp/tools/write_note.py +++ b/src/basic_memory/mcp/tools/write_note.py @@ -63,7 +63,8 @@ async def write_note( title: The title of the note content: Markdown content for the note, can include observations and relations folder: Folder path relative to project root where the file should be saved. - Use forward slashes (/) as separators. Examples: "notes", "projects/2025", "research/ml" + Use forward slashes (/) as separators. Use "/" or "" to write to project root. + Examples: "notes", "projects/2025", "research/ml", "/" (root) project: Project name to write to. Optional - server will resolve using the hierarchy above. If unknown, use list_memory_projects() to discover available projects. @@ -124,6 +125,10 @@ async def write_note( # Get and validate the project (supports optional project parameter) active_project = await get_active_project(client, project, context) + # Normalize "/" to empty string for root folder (must happen before validation) + if folder == "/": + folder = "" + # Validate folder path to prevent path traversal attacks project_path = active_project.home if folder and not validate_project_path(folder, project_path): diff --git a/test-int/mcp/test_write_note_integration.py b/test-int/mcp/test_write_note_integration.py index 5ffcd0a6..88663ae7 100644 --- a/test-int/mcp/test_write_note_integration.py +++ b/test-int/mcp/test_write_note_integration.py @@ -397,6 +397,7 @@ async def test_write_note_file_path_os_path_join(mcp_server, test_project): "nested/folder/another-note", ), ("", "Root Note", "root-note.md", "root-note"), + ("/", "Root Slash Note", "root-slash-note.md", "root-slash-note"), ( "folder with spaces", "Note Title",