Skip to main content
Glama
JaxonDigital

Optimizely DXP MCP Server

by JaxonDigital

list_storage_containers

Discover available Azure blob storage containers in Optimizely DXP environments to identify logs, blobs, and websitelogs before downloading or generating access links.

Instructions

📦 List Azure blob storage containers for environment. REAL-TIME: 1-3s. Returns container names, types (logs, blobs, websitelogs), and creation dates. Use this to discover available containers before download_blobs() or generate_storage_sas_link() calls. Containers vary by environment and project configuration. Required: environment. Optional: project. Returns array of container details.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
environmentYes
limitNoMax results to return (1-100)
offsetNoPagination offset
projectNameNo
projectIdNo
apiKeyNo
apiSecretNo

Implementation Reference

  • Main handler function that executes the list_storage_containers tool logic. Handles argument resolution, self-hosted vs DXP, calls core listing function, and formats response.
    static async handleListStorageContainers(args: StorageArgs): Promise<any> {
        try {
            // Check if this is a self-hosted project
            if (args.connectionString || args.isSelfHosted) {
                const containers = await SelfHostedStorage.listContainers(args.connectionString!);
                return ResponseBuilder.success(this.formatSelfHostedContainers(containers));
            }
    
            // Resolve project configuration if credentials not provided
            let resolvedArgs = args;
            if (!args.apiKey || !args.apiSecret || !args.projectId) {
                const resolved = ProjectTools.resolveCredentials(args);
    
                // Check if the resolved project is self-hosted
                if (resolved.project?.isSelfHosted) {
                    const containers = await SelfHostedStorage.listContainers(resolved.project.connectionString as string);
                    return ResponseBuilder.success(this.formatSelfHostedContainers(containers));
                }
    
                if (!resolved.success || !resolved.credentials) {
                    return ResponseBuilder.invalidParams('Missing required parameters. Either provide apiKey/apiSecret/projectId or configure a project.');
                }
                resolvedArgs = {
                    ...args,
                    apiKey: resolved.credentials.apiKey || undefined,
                    apiSecret: resolved.credentials.apiSecret || undefined,
                    projectId: resolved.credentials.projectId || undefined,
                    projectName: resolved.project?.name
                };
            }
    
            // Default to Production if no environment specified
            if (!resolvedArgs.environment) {
                resolvedArgs.environment = 'Production';
            }
    
            const result = await this.listStorageContainers(resolvedArgs);
    
            // DXP-66: Check if result is structured response with data and message
            if (result && typeof result === 'object' && 'data' in result && 'message' in result) {
                return ResponseBuilder.successWithStructuredData(result.data, result.message);
            }
    
            // Fallback for legacy string responses
            return ResponseBuilder.success(result);
        } catch (error: any) {
            // console.error('List storage containers error:', error);
            return ResponseBuilder.internalError('Failed to list storage containers', error.message);
        }
    }
  • Core listing function called by handler. Uses DXPRestClient to fetch containers with pagination support.
    static async listStorageContainers(args: StorageArgs): Promise<StorageContainersResult | string> {
        // DXP-76-4: Extract pagination parameters
        const { limit = 20, offset = 0 } = args;
    
        // Extract authentication parameters
        const apiKey = args.apiKey!;
        const apiSecret = args.apiSecret!;
        const projectId = args.projectId!;
        const environment = args.environment!;
    
        // console.error(`Listing storage containers for ${environment}`);
    
        // DXP-102: Use REST API instead of PowerShell (3-10x faster, no PowerShell dependency)
        try {
            const result: StorageContainersResponse | string[] = await DXPRestClient.getStorageContainers(
                projectId,
                apiKey,
                apiSecret,
                environment,
                false, // writable parameter
                { apiUrl: args.apiUrl } // Support custom API URLs
            );
    
            // Get all containers
            let allContainers: string[];
            if (Array.isArray(result)) {
                allContainers = result;
            } else if (result && (result as any).storageContainers) {
                allContainers = (result as any).storageContainers;
            } else {
                allContainers = [];
            }
    
            // DXP-76-4: Apply pagination
            const total = allContainers.length;
            const paginatedContainers = allContainers.slice(offset, offset + limit);
    
            // Format response - REST API returns array of container names directly
            if (paginatedContainers.length > 0) {
                return this.formatStorageContainers(paginatedContainers, environment, {
                    total,
                    limit,
                    offset,
                    hasMore: (offset + limit) < total
                });
            } else if (allContainers.length === 0) {
                return this.formatStorageContainers([], environment, {
                    total: 0,
                    limit,
                    offset,
                    hasMore: false
                });
            } else {
                return this.formatStorageContainers(paginatedContainers, environment, {
                    total,
                    limit,
                    offset,
                    hasMore: false
                });
            }
    
            return ResponseBuilder.addFooter('No storage containers found');
    
        } catch (error: any) {
            // Handle REST API errors
            throw new Error(`Failed to list storage containers: ${error.message}`);
        }
    }
  • Input schema defining parameters for storage tools, including list_storage_containers (projectId, environment, limit, offset, etc.).
    interface StorageArgs {
        apiKey?: string;
        apiSecret?: string;
        projectId?: string;
        projectName?: string;
        environment?: string;
        containerName?: string;
        permissions?: string;
        expiryHours?: number;
        connectionString?: string;
        isSelfHosted?: boolean;
        apiUrl?: string;
        limit?: number;
        offset?: number;
    }
  • Output schema for structured response from list_storage_containers.
    interface StorageContainersResult {
        data: StorageContainersData;
        message: string;
    }
  • Helper function to format the list of storage containers with pagination, tips, and structured data for the tool response.
    static formatStorageContainers(data: StorageContainersResponse | string[], environment: string, pagination?: { total: number; limit: number; offset: number; hasMore: boolean }): StorageContainersResult {
        const { FORMATTING: { STATUS_ICONS } } = Config;
    
        // DXP-76-4: Add pagination info to header if provided
        const paginationInfo = pagination && pagination.total > pagination.limit ? ` (showing ${pagination.offset + 1}-${Math.min(pagination.offset + pagination.limit, pagination.total)} of ${pagination.total})` : '';
        let response = `${STATUS_ICONS.FOLDER} **Storage Containers - ${environment}**${paginationInfo}\n\n`;
    
        // DXP-66: Build structured data for automation tools
        let containers: string[] = [];
    
        if (data && typeof data === 'object' && 'storageContainers' in data && Array.isArray(data.storageContainers) && data.storageContainers.length > 0) {
            containers = data.storageContainers;
            response += '**Available Containers:**\n';
            data.storageContainers.forEach((container, index) => {
                const actualIndex = pagination ? pagination.offset + index : index;
                response += `${actualIndex + 1}. 📦 ${container}\n`;
            });
        } else if (Array.isArray(data) && data.length > 0) {
            containers = data;
            response += '**Available Containers:**\n';
            data.forEach((container, index) => {
                const actualIndex = pagination ? pagination.offset + index : index;
                response += `${actualIndex + 1}. 📦 ${container}\n`;
            });
        } else {
            response += 'No storage containers found.\n';
        }
    
        const tips = [
            'Use generate_storage_sas_link to get access URLs',
            'Containers store BLOBs and media files',
            'Each environment has its own containers'
        ];
    
        response += '\n' + ResponseBuilder.formatTips(tips);
    
        // DXP-66 + DXP-76-4: Return structured data with pagination metadata
        const structuredData: any = {
            environment: environment,
            containerCount: containers.length,
            containers: containers
        };
    
        if (pagination) {
            structuredData.pagination = pagination;
        }
    
        return {
            data: structuredData,
            message: ResponseBuilder.addFooter(response)
        };
    }

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