diff --git a/server.py b/server.py index 9754f7e..4d157c9 100644 --- a/server.py +++ b/server.py @@ -530,6 +530,75 @@ def edit_document(vault_name: str, doc_path: str, content: str) -> dict[str, Any } +@mcp.tool() +def create_vault_directory(vault_name: str, dir_path: str) -> dict[str, Any]: + """FILESYSTEM TOOL (not memory) — Create a new directory in a vault on disk. + + Use before create_document when building out folder structures, or for + organizing notes into subdirectories. + + Args: + vault_name: Name of the vault. + dir_path: Relative path for the new directory (e.g. 'Session-12' or 'NPCs/Dragon-Cult'). + + Returns the created directory path. + """ + # Normalize: strip leading slash, handle backslashes + clean = dir_path.lstrip("/\\").replace("\\", "/") + target = _resolve_doc(vault_name, clean) + + if target.exists(): + if not target.is_dir(): + return {"error": f"Path exists but is not a directory: {dir_path}", "vault": vault_name} + return {"vault": vault_name, "path": str(target.relative_to(_vault_path(vault_name))).replace("\\", "/"), + "action": "exists", "note": "Directory already exists"} + + target.mkdir(parents=True, exist_ok=True) + + return { + "vault": vault_name, + "path": str(target.relative_to(_vault_path(vault_name))).replace("\\", "/"), + "action": "created", + } + + +@mcp.tool() +def move_document(vault_name: str, src_path: str, dest_path: str) -> dict[str, Any]: + """FILESYSTEM TOOL (not memory) — Move or rename a document within a vault. + + Moves a document from src_path to dest_path. Both paths are relative to the + vault root. Automatically creates parent directories at the destination if + they don't exist. + + Args: + vault_name: Name of the vault. + src_path: Current relative path of the document (e.g. 'Notes/draft.md'). + dest_path: Target relative path (e.g. 'Archive/draft.md' or 'Notes/final.md'). + + Returns the move result with both old and new paths. + """ + src = _resolve_doc(vault_name, src_path) + if not src.exists(): + return {"error": f"Source document does not exist: {src_path}", "vault": vault_name} + if not src.is_file(): + return {"error": f"Source is not a file: {src_path}", "vault": vault_name} + + dest = _resolve_doc(vault_name, dest_path) + if dest.exists(): + return {"error": f"Destination already exists: {dest_path}", "vault": vault_name} + + dest.parent.mkdir(parents=True, exist_ok=True) + src.rename(dest) + + vault = _vault_path(vault_name) + return { + "vault": vault_name, + "old_path": src_path.lstrip("/\\").replace("\\", "/"), + "new_path": str(dest.relative_to(vault)).replace("\\", "/"), + "action": "moved", + } + + # ── Entrypoint ──────────────────────────────────────────────────────────── def main():