delete_project
Permanently remove a project and all associated content, including knowledge files and TODOs, from the Knowledge MCP Server. Confirm project ID, back up data if needed, and ensure user approval before irreversible deletion.
Instructions
Permanently delete a project and all its content - USE WITH EXTREME CAUTION.
When to use this tool:
Project is completely obsolete
Cleaning up test or temporary projects
Project has been migrated elsewhere
Explicit user request to delete
Key features:
Removes entire project directory
Deletes from index
IRREVERSIBLE operation
Includes all knowledge files and TODOs
You should:
ALWAYS confirm with user before deletion
Verify project_id is correct
Consider backing up important content first
Understand this is permanent
Check if project has valuable knowledge files
Document reason for deletion
DO NOT use when:
Any doubt about deletion
Project might be needed later
Haven't backed up important content
User hasn't explicitly confirmed
⚠️ This action CANNOT be undone! Returns: {success: bool, project_id: str, message: str, error?: str}
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project identifier to delete |
Implementation Reference
- Primary asynchronous handler for delete_project tool execution. Deletes project directory using helper, commits changes, handles errors, and formats MCP response.async deleteProjectAsync(params: z.infer<typeof secureProjectIdSchema>): Promise<string> { const context = this.createContext('delete_project', { project_id: params }); try { const project_id = params; // Use the async utility function to delete the project await deleteProjectDirectoryAsync(this.storagePath, project_id); // Auto-commit the deletion await autoCommitAsync(this.storagePath, `Delete project: ${project_id}`); const result = { project_id, message: `Project '${project_id}' successfully deleted`, }; await this.logSuccessAsync('delete_project', { project_id }, context); return this.formatSuccessResponse(result); } catch (error) { const mcpError = error instanceof Error && error.message.includes('not found') ? new MCPError(MCPErrorCode.PROJECT_NOT_FOUND, `Project '${params}' not found`, { project_id: params, traceId: context.traceId, }) : new MCPError( MCPErrorCode.PROJECT_DELETE_FAILED, `Failed to delete project '${params}': ${error instanceof Error ? error.message : String(error)}`, { project_id: params, traceId: context.traceId, originalError: error, } ); await this.logErrorAsync('delete_project', { project_id: params }, mcpError, context); return this.formatErrorResponse(mcpError, context); } }
- src/knowledge-mcp/server.ts:186-206 (registration)MCP server registration of the delete_project tool, defining input schema, description, and handler wiring.server.registerTool( 'delete_project', { title: 'Delete Project', description: TOOL_DESCRIPTIONS.delete_project, inputSchema: { project_id: secureProjectIdSchema.describe('The project identifier to delete'), }, }, async ({ project_id }) => { const result = await projectHandler.deleteProjectAsync(project_id); return { content: [ { type: 'text', text: result, }, ], }; } );
- Zod schema defining secure validation for project_id input parameter used across project tools.export const secureProjectIdSchema = z .string() .min(1, 'Project ID cannot be empty') .max(100, 'Project ID too long') .refine( (val) => !val.includes('..') && !val.startsWith('.') && !val.endsWith('.'), 'Project ID cannot contain path traversal patterns' ) .refine( (val) => !/[/\\:*?"<>|\0]/.test(val), 'Project ID cannot contain filesystem reserved characters or null bytes' ) .refine((val) => val.trim() === val, 'Project ID cannot have leading/trailing spaces');
- src/knowledge-mcp/utils.ts:790-818 (helper)Core asynchronous utility function that physically deletes the project directory and removes entry from the project index.export async function deleteProjectDirectoryAsync( storagePath: string, projectId: string ): Promise<void> { const index = await readProjectIndexAsync(storagePath); // Check if project exists in index if (!(projectId in index)) { throw new Error(`Project '${projectId}' not found in index`); } const dirName = index[projectId]; const projectPath = join(storagePath, 'projects', dirName); // Delete directory if it exists try { await access(projectPath); await rm(projectPath, { recursive: true, force: true }); } catch (error) { // Directory doesn't exist, continue with index cleanup if (error && typeof error === 'object' && 'code' in error && error.code !== 'ENOENT') { throw error; } } // Remove from index const { [projectId]: _removed, ...newIndex } = index; await writeProjectIndexAsync(storagePath, newIndex); }