duplicate_project
Create a copy of an existing project with customizable options like tasks, documents, dates, and ownership.
Instructions
Create a copy of an existing project with customizable options
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| source_project_id | Yes | ID of the project to duplicate | |
| new_name | Yes | Name for the new project | |
| include_tasks | No | Whether to copy tasks | |
| include_documents | No | Whether to copy documents | |
| reset_dates | No | Whether to reset all dates to current | |
| new_owner_id | No | New owner for the duplicated project (optional) |
Implementation Reference
- src/tools/projects.ts:406-474 (handler)The main handler function that executes the duplicate_project tool logic. It validates input, fetches the source project, creates a new project, and copies tasks and documents if specified.export const duplicateProject = requireAuth(async (args: any) => { const { source_project_id, new_name, include_tasks, include_documents, reset_dates, new_owner_id } = DuplicateProjectSchema.parse(args) logger.info('Duplicating project', { source_project_id, new_name, include_tasks, include_documents }) // Get source project const sourceProject = await supabaseService.getProject(source_project_id) if (!sourceProject) { throw new Error('Source project not found') } const now = new Date().toISOString() // Create new project const newProject = await supabaseService.createProject({ name: new_name, description: `Copy of ${sourceProject.name}${sourceProject.description ? `: ${sourceProject.description}` : ''}`, status: 'active' // Removed owner_id, priority, visibility, metadata as they don't exist in the database schema }) const duplicateResults = { new_project: newProject, tasks_copied: 0, documents_copied: 0 } // Copy tasks if requested if (include_tasks) { const sourceTasks = await supabaseService.getTasks({ project_id: source_project_id }) for (const task of sourceTasks) { const newTask = { title: task.title, description: task.description, project_id: newProject.id, initiative_id: null, status: 'todo' as const, // Reset all tasks to todo priority: task.priority, due_date: reset_dates ? null : task.due_date, assignee_id: task.assignee_id // Removed started_at, completed_at as they don't exist in the database schema } await supabaseService.createTask(newTask) duplicateResults.tasks_copied++ } } // Copy documents if requested if (include_documents) { const sourceDocuments = await supabaseService.getDocuments({ project_id: source_project_id }) for (const doc of sourceDocuments) { const newDoc = { project_id: newProject.id, title: `${doc.title} (Copy)`, content: doc.content, document_type: doc.document_type // Removed metadata as it doesn't exist in the database schema } await supabaseService.createDocument(newDoc) duplicateResults.documents_copied++ } } return duplicateResults })
- src/tools/projects.ts:397-404 (schema)Zod schema defining the input parameters and validation rules for the duplicate_project tool.const DuplicateProjectSchema = z.object({ source_project_id: z.string().min(1), new_name: z.string().min(1).max(200), include_tasks: z.boolean().default(true), include_documents: z.boolean().default(true), reset_dates: z.boolean().default(true), new_owner_id: z.string().optional() })
- src/tools/projects.ts:359-395 (registration)MCPTool registration object defining the name, description, and input schema for the duplicate_project tool.export const duplicateProjectTool: MCPTool = { name: 'duplicate_project', description: 'Create a copy of an existing project with customizable options', inputSchema: { type: 'object', properties: { source_project_id: { type: 'string', description: 'ID of the project to duplicate' }, new_name: { type: 'string', description: 'Name for the new project' }, include_tasks: { type: 'boolean', default: true, description: 'Whether to copy tasks' }, include_documents: { type: 'boolean', default: true, description: 'Whether to copy documents' }, reset_dates: { type: 'boolean', default: true, description: 'Whether to reset all dates to current' }, new_owner_id: { type: 'string', description: 'New owner for the duplicated project (optional)' } }, required: ['source_project_id', 'new_name'] } }
- src/tools/projects.ts:778-788 (registration)Registration of the duplicateProject handler under the 'duplicate_project' key in the projectHandlers export.export const projectHandlers = { list_projects: listProjects, get_project: getProject, create_project: createProject, update_project: updateProject, get_project_context: getProjectContext, archive_project: archiveProject, duplicate_project: duplicateProject, get_project_timeline: getProjectTimeline, bulk_update_projects: bulkUpdateProjects }