Skip to main content
Glama
andyl25

Google Cloud MCP Server

by andyl25

list-metric-types

Retrieve available Google Cloud Monitoring metric types using search filters or expressions to identify relevant metrics for analysis.

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

  • Registration of the 'list-metric-types' tool with the MCP server, including inline schema and handler function.
    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 ); } } );
  • The handler function that executes the tool: fetches metric descriptors from Google Cloud Monitoring API, applies filtering, handles timeouts, and formats results as a markdown table.
    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 ); } } );
  • Zod input schema defining parameters: optional filter (search term or expression), pageSize (default 20), timeout (default 30s).
    { 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') },

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