Skip to main content
Glama
andyl25

Google Cloud MCP Server

by andyl25

list-metric-types

List available metric types in Google Cloud Monitoring using filters, set page size, and define request timeout for efficient data retrieval.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filterNoSimple search term (e.g., "spanner") or full filter expression (e.g., "metric.type = starts_with(\"spanner\")")
pageSizeNoMaximum number of metric types to return
timeoutNoTimeout in seconds for the request

Implementation Reference

  • The complete handler function for the 'list-metric-types' tool. It registers the tool with Zod input schema, fetches metric descriptors from Google Cloud Monitoring API using listMetricDescriptors, handles timeouts, client-side filtering for simple terms, and formats results as a markdown table with columns for type, display name, kind, value type, and description.
    server.tool( 'list-metric-types', { filter: z.string().optional().describe('Simple search term (e.g., "spanner") or full filter expression (e.g., "metric.type = starts_with(\\"spanner\\")")'), pageSize: z.number().min(1).max(100).default(20).describe('Maximum number of metric types to return'), timeout: z.number().min(5).max(60).default(30).describe('Timeout in seconds for the request') }, async ({ filter, pageSize, timeout }, context) => { try { const projectId = await getProjectId(); const client = getMonitoringClient(); // Format the filter if it's a simple string without operators let formattedFilter = filter; let useClientSideFiltering = false; if (filter && !filter.includes('=') && !filter.includes('>') && !filter.includes('<')) { // If it's just a simple term, we'll use client-side filtering // We don't set a filter for the API call to avoid syntax errors formattedFilter = undefined; useClientSideFiltering = true; } // Create a promise that rejects after the timeout const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new Error(`Request timed out after ${timeout} seconds`)); }, timeout * 1000); }); // Create the actual request promise const requestPromise = (async () => { const request: any = { name: `projects/${projectId}`, pageSize }; if (formattedFilter) { request.filter = formattedFilter; } return await client.listMetricDescriptors(request); })(); // Race the timeout against the actual request const [metricDescriptors] = await Promise.race([requestPromise, timeoutPromise]) as [any]; // Apply client-side filtering if needed let filteredDescriptors = metricDescriptors; if (useClientSideFiltering && filter) { const searchTerm = filter.toLowerCase(); filteredDescriptors = metricDescriptors.filter((descriptor: any) => { // Search in the type name if (descriptor.type && descriptor.type.toLowerCase().includes(searchTerm)) { return true; } // Search in the display name if (descriptor.displayName && descriptor.displayName.toLowerCase().includes(searchTerm)) { return true; } // Search in the description if (descriptor.description && descriptor.description.toLowerCase().includes(searchTerm)) { return true; } return false; }); } if (!filteredDescriptors || filteredDescriptors.length === 0) { return { content: [{ type: 'text', text: `# Available Metric Types\n\nProject: ${projectId}\n${filter ? `\nSearch term: "${filter}"` : ''}\n\nNo metric types found matching your search term. Try a different search term or increase the timeout.` }] }; } let markdown = `# Available Metric Types\n\nProject: ${projectId}\n${filter ? `\nSearch term: "${filter}"` : ''}\n${useClientSideFiltering ? `\n*Note: Filtering was performed client-side by searching for "${filter}" in metric type, display name, and description.*` : ''}\n\nFound ${filteredDescriptors.length} metric types${metricDescriptors.length !== filteredDescriptors.length ? ` (filtered from ${metricDescriptors.length} total)` : ''}.\n\n`; // Table header markdown += '| Metric Type | Display Name | Kind | Value Type | Description |\n'; markdown += '|-------------|--------------|------|------------|-------------|\n'; // Table rows - limit to first 50 to avoid excessive output const limitedDescriptors = filteredDescriptors.slice(0, 50); for (const descriptor of limitedDescriptors) { const description = (descriptor.description || '').replace(/\n/g, ' ').substring(0, 100); markdown += `| ${descriptor.type || ''} | ${descriptor.displayName || ''} | ${descriptor.metricKind || ''} | ${descriptor.valueType || ''} | ${description} |\n`; } if (filteredDescriptors.length > 50) { markdown += `\n*Note: Showing first 50 of ${filteredDescriptors.length} metric types. Use a more specific search term to narrow down results.*`; } return { content: [{ type: 'text', text: markdown }] }; } catch (error: unknown) { // Extract error message safely let errorMessage = 'Unknown error'; if (error instanceof Error) { errorMessage = error.message; } else if (typeof error === 'object' && error !== null) { errorMessage = String((error as any).message || JSON.stringify(error)); } else if (typeof error === 'string') { errorMessage = error; } // Check for timeout errors if (errorMessage.includes('timed out')) { throw new GcpMcpError( `Request timed out. Try using a filter to narrow down results or increase the timeout parameter.`, 'DEADLINE_EXCEEDED', 504 ); } // Handle other errors const errorCode = (error as any)?.code || 'UNKNOWN'; const statusCode = (error as any)?.statusCode || 500; throw new GcpMcpError( `Failed to list metric types: ${errorMessage}`, errorCode, statusCode ); } } );

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/andyl25/googlecloud-mcp'

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