Skip to main content
Glama
containerAnalysis.tsโ€ข6.49 kB
import { getDatabase, getContainer } from '../db.js'; import { ToolResult, ContainerInfo, ContainerStats, DatabaseInfo } from './types.js'; /** * List all databases in the CosmosDB account */ export const mcp_list_databases = async (): Promise<ToolResult<DatabaseInfo[]>> => { console.log('Executing mcp_list_databases'); try { const database = getDatabase(); const client = database.client; const { resources: databases } = await client.databases.readAll().fetchAll(); const databasesInfo: DatabaseInfo[] = databases.map(db => ({ id: db.id, etag: db._etag, timestamp: new Date(db._ts * 1000) })); return { success: true, data: databasesInfo }; } catch (error: any) { console.error(`Error in mcp_list_databases: ${error.message}`); return { success: false, error: error.message }; } }; /** * List all containers in the database */ export const mcp_list_containers = async (): Promise<ToolResult<ContainerInfo[]>> => { console.log('Executing mcp_list_containers'); try { const database = getDatabase(); const { resources: containers } = await database.containers.readAll().fetchAll(); const containersInfo: ContainerInfo[] = containers.map((container: any) => ({ id: container.id, partitionKey: container.partitionKey ? { paths: container.partitionKey.paths || [], kind: container.partitionKey.kind } : undefined, indexingPolicy: container.indexingPolicy, etag: container._etag, timestamp: container._ts ? new Date(container._ts * 1000) : undefined })); return { success: true, data: containersInfo }; } catch (error: any) { console.error(`Error in mcp_list_containers: ${error.message}`); return { success: false, error: error.message }; } }; /** * Get detailed information about a specific container */ export const mcp_container_info = async (args: { container_id: string }): Promise<ToolResult<ContainerInfo & { throughputInfo?: any }>> => { const { container_id } = args; console.log('Executing mcp_container_info with:', args); try { const container = getContainer(container_id); // Read container definition const { resource: containerDef } = await container.read(); // Try to read throughput settings let throughputInfo; try { const offerResponse = await container.readOffer(); throughputInfo = offerResponse.resource; } catch (offerError) { // Throughput might not be defined for shared throughput containers console.log('Could not read container throughput (might use shared database throughput)'); } if (!containerDef) { throw new Error(`Container ${container_id} not found`); } const containerInfo: ContainerInfo & { throughputInfo?: any } = { id: containerDef.id, partitionKey: containerDef.partitionKey ? { paths: containerDef.partitionKey.paths || [], kind: containerDef.partitionKey.kind } : undefined, indexingPolicy: containerDef.indexingPolicy, etag: containerDef._etag, timestamp: containerDef._ts ? new Date(containerDef._ts * 1000) : undefined, throughputInfo }; return { success: true, data: containerInfo }; } catch (error: any) { console.error(`Error in mcp_container_info for container ${container_id}: ${error.message}`); return { success: false, error: error.message }; } }; /** * Get basic statistics about a container */ export const mcp_container_stats = async (args: { container_id: string; sample_size?: number }): Promise<ToolResult<ContainerStats>> => { const { container_id, sample_size = 1000 } = args; console.log('Executing mcp_container_stats with:', args); try { const container = getContainer(container_id); // Query to count total documents const countQuery = 'SELECT VALUE COUNT(1) FROM c'; const { resources: countResult } = await container.items.query(countQuery).fetchAll(); const documentCount = countResult[0] || 0; // Get partition key path for statistics const { resource: containerDef } = await container.read(); if (!containerDef || !containerDef.partitionKey || !containerDef.partitionKey.paths || containerDef.partitionKey.paths.length === 0) { throw new Error(`Container ${container_id} does not have a valid partition key defined`); } const partitionKeyPath = containerDef.partitionKey.paths[0]; // Sample documents to estimate size and analyze partitions const sampleQuery = `SELECT TOP ${sample_size} * FROM c`; const { resources: sampleDocs } = await container.items.query(sampleQuery).fetchAll(); // Calculate estimated size based on sample let totalSampleSize = 0; const partitionStats: Record<string, { count: number; size: number }> = {}; sampleDocs.forEach(doc => { const docSize = JSON.stringify(doc).length; totalSampleSize += docSize; // Get partition key value const partitionValue = getNestedProperty(doc, partitionKeyPath.substring(1)); // Remove leading '/' const partitionKey = String(partitionValue || 'undefined'); if (!partitionStats[partitionKey]) { partitionStats[partitionKey] = { count: 0, size: 0 }; } partitionStats[partitionKey].count++; partitionStats[partitionKey].size += docSize; }); // Estimate total size const avgDocSize = sampleDocs.length > 0 ? totalSampleSize / sampleDocs.length : 0; const estimatedSizeInKB = Math.round((documentCount * avgDocSize) / 1024); // Convert partition stats const partitionKeyStatistics = Object.entries(partitionStats).map(([key, stats]) => ({ partitionKeyValue: key, documentCount: Math.round((stats.count / sampleDocs.length) * documentCount), sizeInKB: Math.round(stats.size / 1024) })); const containerStats: ContainerStats = { documentCount, sizeInKB: estimatedSizeInKB, partitionKeyStatistics }; return { success: true, data: containerStats }; } catch (error: any) { console.error(`Error in mcp_container_stats for container ${container_id}: ${error.message}`); return { success: false, error: error.message }; } }; // Helper function to get nested property from object function getNestedProperty(obj: any, path: string): any { return path.split('/').reduce((current, key) => { return current && current[key] !== undefined ? current[key] : undefined; }, obj); }

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/hendrickcastro/MCPCosmosDB'

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