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)
        };
    }
Behavior4/5

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

With no annotations provided, the description carries full burden and does well by disclosing performance characteristics ('REAL-TIME: 1-3s'), return format ('Returns container names, types, and creation dates'), and that it 'Returns array of container details.' However, it doesn't mention pagination behavior (though offset/limit are in schema) or error conditions.

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 efficiently structured with key information front-loaded: emoji for visual cue, purpose statement, performance data, return format, usage guidance, and parameter requirements. Every sentence adds value with zero wasted words.

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?

For a tool with 7 parameters, no annotations, and no output schema, the description does well by covering purpose, usage, performance, and return format. However, it doesn't fully address all parameters or provide complete behavioral context for a listing operation with authentication parameters (apiKey, apiSecret).

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?

With only 29% schema description coverage, the description compensates by explaining the purpose of 'environment' and 'project' parameters. However, it doesn't address the other 5 parameters (limit, offset, projectName, projectId, apiKey, apiSecret) that appear in the schema but aren't mentioned in the description.

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 specific action ('List Azure blob storage containers'), resource ('containers'), and scope ('for environment'). It distinguishes from siblings by specifying container types (logs, blobs, websitelogs) and explicitly mentions related tools (download_blobs, generate_storage_sas_link).

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?

The description provides explicit guidance on when to use this tool ('to discover available containers before download_blobs() or generate_storage_sas_link() calls') and mentions that 'Containers vary by environment and project configuration.' It also specifies required and optional parameters directly in the description.

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