@@ -134,6 +134,18 @@ pub struct ReadSectionParams {
134134#[ derive( Debug , Deserialize , JsonSchema ) ]
135135pub struct HealthParams { }
136136
137+ #[ derive( Debug , Deserialize , JsonSchema ) ]
138+ pub struct MigratePreviewParams { }
139+
140+ #[ derive( Debug , Deserialize , JsonSchema ) ]
141+ pub struct MigrateApplyParams {
142+ /// Migration preview JSON (from migrate_preview).
143+ pub preview : serde_json:: Value ,
144+ }
145+
146+ #[ derive( Debug , Deserialize , JsonSchema ) ]
147+ pub struct MigrateUndoParams { }
148+
137149#[ derive( Debug , Deserialize , JsonSchema ) ]
138150pub struct EditParams {
139151 /// Target note: file path, basename, or #docid.
@@ -685,6 +697,42 @@ impl EngraphServer {
685697 to_json_result ( & result)
686698 }
687699
700+ #[ tool(
701+ name = "migrate_preview" ,
702+ description = "Generate PARA migration preview. Classifies all notes into Projects/Areas/Resources/Archive and returns proposed moves with confidence scores."
703+ ) ]
704+ async fn migrate_preview ( & self , _params : Parameters < MigratePreviewParams > ) -> Result < CallToolResult , McpError > {
705+ let store = self . store . lock ( ) . await ;
706+ let profile_ref = self . profile . as_ref ( ) . as_ref ( ) ;
707+ let preview = crate :: migrate:: generate_preview ( & store, & self . vault_path , profile_ref)
708+ . map_err ( |e| mcp_err ( & e) ) ?;
709+ to_json_result ( & preview)
710+ }
711+
712+ #[ tool(
713+ name = "migrate_apply" ,
714+ description = "Apply a PARA migration preview. Moves files to their classified PARA locations. Reversible via migrate_undo."
715+ ) ]
716+ async fn migrate_apply ( & self , params : Parameters < MigrateApplyParams > ) -> Result < CallToolResult , McpError > {
717+ let store = self . store . lock ( ) . await ;
718+ let preview: crate :: migrate:: MigrationPreview = serde_json:: from_value ( params. 0 . preview )
719+ . map_err ( |e| mcp_err ( & anyhow:: anyhow!( "Invalid preview JSON: {e}" ) ) ) ?;
720+ let result = crate :: migrate:: apply_preview ( & preview, & store, & self . vault_path )
721+ . map_err ( |e| mcp_err ( & e) ) ?;
722+ to_json_result ( & result)
723+ }
724+
725+ #[ tool(
726+ name = "migrate_undo" ,
727+ description = "Undo the most recent PARA migration, restoring all moved files to their original locations."
728+ ) ]
729+ async fn migrate_undo ( & self , _params : Parameters < MigrateUndoParams > ) -> Result < CallToolResult , McpError > {
730+ let store = self . store . lock ( ) . await ;
731+ let result = crate :: migrate:: undo_last ( & store, & self . vault_path )
732+ . map_err ( |e| mcp_err ( & e) ) ?;
733+ to_json_result ( & result)
734+ }
735+
688736 #[ tool(
689737 name = "delete" ,
690738 description = "Delete a note. Soft mode (default) moves it to the archive folder. Hard mode permanently removes it from disk and index."
@@ -725,7 +773,8 @@ impl rmcp::handler::server::ServerHandler for EngraphServer {
725773 Read: vault_map to orient, search to find, read/read_section for content, who/project for context bundles, health for vault diagnostics. \
726774 Write: create for new notes, append to add content, edit to modify a section, rewrite to replace body, \
727775 edit_frontmatter for tags/properties, update_metadata for bulk tag/alias replacement. \
728- Lifecycle: move_note to relocate, archive to soft-delete, unarchive to restore, delete for permanent removal.",
776+ Lifecycle: move_note to relocate, archive to soft-delete, unarchive to restore, delete for permanent removal. \
777+ Migration: migrate_preview to classify notes into PARA folders, migrate_apply to execute the migration, migrate_undo to revert.",
729778 )
730779 }
731780}
0 commit comments