Skip to main content
Glama
JaxonDigital

Optimizely DXP MCP Server

by JaxonDigital

download_cancel

Cancel active Optimizely DXP downloads immediately. Stop specific downloads by ID or halt all active transfers to manage deployment resources effectively.

Instructions

❌ Cancel active download(s) immediately. INSTANT: <1s. Call with downloadId to cancel specific download, or call without parameters to cancel all active downloads. Database downloads cannot be cancelled (Azure streaming limitation). Returns count of successfully cancelled downloads. Use download_list() to verify cancellation. Optional: downloadId. Returns cancelled count.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
downloadIdNoDownload ID to cancel. Omit to cancel all active downloads

Implementation Reference

  • Main handler function for the "download_cancel" MCP tool. Parses args to determine if cancelling specific downloadId or all downloads, delegates to private helper methods, handles errors.
    static async handleDownloadCancel(args?: DownloadCancelArgs): Promise<any> {
        const { downloadId } = args || {};
    
        try {
            // Cancel specific download
            if (downloadId) {
                return await this._cancelSingleDownload(downloadId);
            }
    
            // Cancel all downloads
            return await this._cancelAllDownloads();
    
        } catch (error: any) {
            OutputLogger.error(`Cancel download error: ${error}`);
            return ResponseBuilder.internalError('Failed to cancel download(s)', error.message);
        }
    }
  • TypeScript interface defining the input parameters for the download_cancel tool.
    interface DownloadCancelArgs {
        downloadId?: string;
    }
  • Private helper that cancels a single download. Checks if database download first (cannot cancel), then cancels log download using DownloadManager, returns formatted response.
    static async _cancelSingleDownload(downloadId: string): Promise<any> {
        // Check if it's a database download
        // DXP-178 FIX: Need .default for ES module default export
        const DatabaseSimpleTools = require('./database-simple-tools').default;
        // DXP-178 FIX: Use .backgroundDownloads.get() instead of non-existent .getDownloadStatus()
        const dbDownload = DatabaseSimpleTools.backgroundDownloads.get(downloadId);
    
        if (dbDownload) {
            return ResponseBuilder.error(
                `❌ **Cannot Cancel Database Download**\n\n` +
                `Database downloads use Azure Blob streaming and cannot be interrupted. ` +
                `The download will complete in the background.\n\n` +
                `**Download ID**: ${downloadId}\n` +
                `**Progress**: ${dbDownload.percent || 0}%\n\n` +
                `**Monitor progress:** \`download_status({ downloadId: "${downloadId}" })\``
            );
        }
    
        // Check if it's a log download
        const logDownload = downloadManager.getDownload(downloadId);
        if (!logDownload) {
            return ResponseBuilder.error(
                `Download ${downloadId} not found.\n\n` +
                `**View active downloads:** \`download_list({ status: "active" })\``
            );
        }
    
        // Cancel the log download
        const result: CancelResult = downloadManager.cancelDownload(downloadId);
    
        if (result.success) {
            const download = result.download;
            const elapsed = Math.floor((Date.now() - download.startTime) / 60000);
    
            const structuredData = {
                cancelled: [downloadId],
                skipped: [],
                failed: []
            };
    
            const message = `❌ **Download Cancelled**\n\n` +
                `**Download**: ${download.containerName} logs\n` +
                `**Runtime**: ${elapsed} minutes\n` +
                `**Progress**: ${download.progress}%\n\n` +
                `Partially downloaded files have been preserved.`;
    
            return ResponseBuilder.successWithStructuredData(structuredData, message);
        } else {
            return ResponseBuilder.error(`Failed to cancel: ${result.error}`);
        }
    }
  • Private helper that cancels all active log downloads using DownloadManager.cancelAllDownloads(), identifies un-cancellable database downloads, formats comprehensive response with structured data.
    static async _cancelAllDownloads(): Promise<any> {
        const logResults: CancelResult[] = downloadManager.cancelAllDownloads();
    
        // Find database downloads that can't be cancelled
        // DXP-178 FIX: Need .default for ES module default export
        const DatabaseSimpleTools = require('./database-simple-tools').default;
        const dbDownloads: SkippedDownload[] = [];
        for (const [id, download] of DatabaseSimpleTools.backgroundDownloads.entries()) {
            if (download.status === 'in_progress' || download.status === 'pending') {
                dbDownloads.push({
                    downloadId: id,
                    type: 'database',
                    reason: 'Database downloads cannot be cancelled'
                });
            }
        }
    
        const cancelled = logResults.filter(r => r.success).map(r => r.download!.key);
        const failed: FailedCancel[] = logResults.filter(r => !r.success).map(r => ({
            downloadId: r.download?.key || 'unknown',
            reason: r.error || 'Unknown error'
        }));
    
        if (cancelled.length === 0 && dbDownloads.length === 0 && failed.length === 0) {
            return ResponseBuilder.success('📭 No active downloads to cancel.');
        }
    
        let message = `❌ **Cancel All Downloads**\n\n`;
    
        if (cancelled.length > 0) {
            message += `**Cancelled log downloads** (${cancelled.length}):\n`;
            for (const id of cancelled) {
                message += `• ${id}\n`;
            }
            message += `\n`;
        }
    
        if (dbDownloads.length > 0) {
            message += `**Database downloads continuing** (${dbDownloads.length}):\n`;
            message += `These downloads cannot be cancelled and will complete in background.\n`;
            for (const db of dbDownloads) {
                message += `• ${db.downloadId}\n`;
            }
            message += `\n`;
        }
    
        if (failed.length > 0) {
            message += `**Failed to cancel** (${failed.length}):\n`;
            for (const f of failed) {
                message += `• ${f.downloadId}: ${f.reason}\n`;
            }
            message += `\n`;
        }
    
        const structuredData = {
            cancelled: cancelled,
            skipped: dbDownloads,
            failed: failed
        };
    
        return ResponseBuilder.successWithStructuredData(structuredData, message);
    }
  • Core implementation in DownloadManager that performs the actual cancellation: kills child process with SIGTERM/SIGKILL, updates status, moves to history, emits event.
    cancelDownload(key: string): CancelResult {
        const download = this.activeDownloads.get(key);
        if (!download) {
            return { success: false, error: `Download ${key} not found` };
        }
    
        try {
            if (download.childProcess && !download.childProcess.killed) {
                download.childProcess.kill('SIGTERM');
    
                // Force kill after 5 seconds if still running
                setTimeout(() => {
                    if (download.childProcess && !download.childProcess.killed) {
                        download.childProcess.kill('SIGKILL');
                    }
                }, 5000);
            }
    
            download.status = 'cancelled';
            download.endTime = Date.now();
    
            // Move to history
            this.downloadHistory.push(download);
            this.activeDownloads.delete(key);
    
            this.emit('downloadCancelled', download);
            OutputLogger.info(`❌ Cancelled download: ${key}`);
    
            return { success: true, download };
        } catch (error) {
            OutputLogger.error(`Failed to cancel download ${key}: ${error}`);
            return { success: false, error: (error as Error).message };
        }
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses key behavioral traits: immediate cancellation (<1s), returns count of successfully cancelled downloads, and notes a limitation (database downloads cannot be cancelled). However, it lacks details on error handling or permissions, which could be useful for a destructive operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the main action ('Cancel active download(s) immediately'), followed by key details in a logical order: timing, parameter usage, limitations, return value, and verification method. Every sentence adds necessary information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description does well by covering purpose, usage, behavior, and parameters. It could improve by specifying error cases or auth requirements, but it's largely complete for a tool with one optional parameter and clear operational context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents the downloadId parameter. The description adds value by explaining the optional nature (omit to cancel all) and linking it to the return value (cancelled count), but doesn't provide additional syntax or format details beyond what the schema implies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'cancel' and resource 'active download(s)', specifying immediate action. It distinguishes from sibling tools like download_list (for verification) and download_status (for status checking), making the purpose specific and differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance is provided: call with downloadId for specific cancellation or without parameters for all active downloads, and notes that database downloads cannot be cancelled due to Azure streaming limitation. It also references download_list() for verification, clearly indicating when and how to use this tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JaxonDigital/optimizely-dxp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server