Skip to main content
Glama
krzko

Google Cloud MCP Server

by krzko

gcp-profiler-analyse-performance

Analyze application performance on Google Cloud using profiler data to identify bottlenecks, optimize resource usage, and improve efficiency through actionable insights.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Registers the 'gcp-profiler-analyse-performance' tool with the MCP server using server.tool(). Includes title, description, input schema with Zod validation for profileType, target, pageSize, and the inline async handler function.
    server.tool( "gcp-profiler-analyse-performance", { title: "Analyse Profile Performance", description: "Analyse profiles to identify performance patterns, bottlenecks, and optimisation opportunities", inputSchema: { profileType: z .enum([ ProfileType.CPU, ProfileType.WALL, ProfileType.HEAP, ProfileType.THREADS, ProfileType.CONTENTION, ProfileType.PEAK_HEAP, ProfileType.HEAP_ALLOC, ]) .optional() .describe("Focus analysis on specific profile type"), target: z .string() .optional() .describe("Focus analysis on specific deployment target"), pageSize: z .number() .min(1) .max(1000) .default(100) .describe( "Number of profiles to analyse (more profiles = better insights)", ), }, }, async ({ profileType, target, pageSize }) => { try { const projectId = await getProjectId(); // Initialize Google Auth client (same pattern as error reporting) const auth = await initGoogleAuth(true); if (!auth) { throw new GcpMcpError( "Google Cloud authentication not available. Please configure authentication to access profiler data.", "UNAUTHENTICATED", 401, ); } const client = await auth.getClient(); const token = await client.getAccessToken(); // Parse parameters const actualPageSize = pageSize || 100; // Build query parameters for maximum data collection const params = new URLSearchParams({ pageSize: actualPageSize.toString(), }); // Make REST API call to list profiles const apiUrl = `https://cloudprofiler.googleapis.com/v2/projects/${projectId}/profiles?${params}`; const response = await fetch(apiUrl, { method: "GET", headers: { Authorization: `Bearer ${token.token}`, Accept: "application/json", }, }); if (!response.ok) { const errorText = await response.text(); throw new GcpMcpError( `Failed to fetch profiles for analysis: ${errorText}`, "FAILED_PRECONDITION", response.status, ); } const data: ListProfilesResponse = await response.json(); let profiles = data.profiles || []; // Apply filtering if specified if (profileType) { profiles = profiles.filter((p) => p.profileType === profileType); } if (target) { profiles = profiles.filter((p) => p.deployment?.target?.toLowerCase().includes(target.toLowerCase()), ); } if (!profiles || profiles.length === 0) { let filterText = "No profiles found for analysis"; if (profileType) filterText += ` with profile type: ${profileType}`; if (target) filterText += ` and target: ${target}`; return { content: [ { type: "text", text: `# Profile Performance Analysis\n\nProject: ${projectId}\n\n${filterText}.`, }, ], }; } // Generate comprehensive analysis let content = `# Profile Performance Analysis\n\nProject: ${projectId}\n`; if (profileType) content += `Focus: ${getProfileTypeDescription(profileType)}\n`; if (target) content += `Target: ${target}\n`; content += `Analysed: ${profiles.length} profiles\n\n`; // Get detailed analysis const analysis = analyseProfilePatterns(profiles); content += analysis; // Add performance insights specific to the analysis content += `\n## Performance Insights\n\n`; // Analyse profile collection patterns const timeDistribution = analyseProfileTimeDistribution(profiles); content += timeDistribution; // Analyse deployment patterns const deploymentAnalysis = analyseDeploymentPatterns(profiles); content += deploymentAnalysis; // Add actionable recommendations content += `\n## Actionable Recommendations\n\n`; content += getActionableRecommendations(profiles, profileType); return { content: [ { type: "text", text: content, }, ], }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; throw new GcpMcpError( `Failed to analyse profile performance: ${errorMessage}`, "INTERNAL_ERROR", 500, ); } }, );
  • The core handler function that implements the tool logic. Authenticates with Google Cloud, lists profiles from the Profiler API, applies filters, performs multi-faceted analysis (patterns, time distribution, deployments, recommendations), and returns a comprehensive Markdown report on performance insights.
    async ({ profileType, target, pageSize }) => { try { const projectId = await getProjectId(); // Initialize Google Auth client (same pattern as error reporting) const auth = await initGoogleAuth(true); if (!auth) { throw new GcpMcpError( "Google Cloud authentication not available. Please configure authentication to access profiler data.", "UNAUTHENTICATED", 401, ); } const client = await auth.getClient(); const token = await client.getAccessToken(); // Parse parameters const actualPageSize = pageSize || 100; // Build query parameters for maximum data collection const params = new URLSearchParams({ pageSize: actualPageSize.toString(), }); // Make REST API call to list profiles const apiUrl = `https://cloudprofiler.googleapis.com/v2/projects/${projectId}/profiles?${params}`; const response = await fetch(apiUrl, { method: "GET", headers: { Authorization: `Bearer ${token.token}`, Accept: "application/json", }, }); if (!response.ok) { const errorText = await response.text(); throw new GcpMcpError( `Failed to fetch profiles for analysis: ${errorText}`, "FAILED_PRECONDITION", response.status, ); } const data: ListProfilesResponse = await response.json(); let profiles = data.profiles || []; // Apply filtering if specified if (profileType) { profiles = profiles.filter((p) => p.profileType === profileType); } if (target) { profiles = profiles.filter((p) => p.deployment?.target?.toLowerCase().includes(target.toLowerCase()), ); } if (!profiles || profiles.length === 0) { let filterText = "No profiles found for analysis"; if (profileType) filterText += ` with profile type: ${profileType}`; if (target) filterText += ` and target: ${target}`; return { content: [ { type: "text", text: `# Profile Performance Analysis\n\nProject: ${projectId}\n\n${filterText}.`, }, ], }; } // Generate comprehensive analysis let content = `# Profile Performance Analysis\n\nProject: ${projectId}\n`; if (profileType) content += `Focus: ${getProfileTypeDescription(profileType)}\n`; if (target) content += `Target: ${target}\n`; content += `Analysed: ${profiles.length} profiles\n\n`; // Get detailed analysis const analysis = analyseProfilePatterns(profiles); content += analysis; // Add performance insights specific to the analysis content += `\n## Performance Insights\n\n`; // Analyse profile collection patterns const timeDistribution = analyseProfileTimeDistribution(profiles); content += timeDistribution; // Analyse deployment patterns const deploymentAnalysis = analyseDeploymentPatterns(profiles); content += deploymentAnalysis; // Add actionable recommendations content += `\n## Actionable Recommendations\n\n`; content += getActionableRecommendations(profiles, profileType); return { content: [ { type: "text", text: content, }, ], }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; throw new GcpMcpError( `Failed to analyse profile performance: ${errorMessage}`, "INTERNAL_ERROR", 500, ); } },
  • Input schema using Zod for validating tool parameters: profileType (optional ProfileType enum), target (optional string), pageSize (optional number, 1-1000, default 100).
    inputSchema: { profileType: z .enum([ ProfileType.CPU, ProfileType.WALL, ProfileType.HEAP, ProfileType.THREADS, ProfileType.CONTENTION, ProfileType.PEAK_HEAP, ProfileType.HEAP_ALLOC, ]) .optional() .describe("Focus analysis on specific profile type"), target: z .string() .optional() .describe("Focus analysis on specific deployment target"), pageSize: z .number() .min(1) .max(1000) .default(100) .describe( "Number of profiles to analyse (more profiles = better insights)", ), },
  • Key helper function called by the handler. Analyzes a list of profiles to produce detailed markdown analysis including statistics, distributions, recent activity, profile-type specific insights, and performance recommendations.
    export function analyseProfilePatterns(profiles: Profile[]): string { if (!profiles || profiles.length === 0) { return "No profiles found in the specified criteria."; } let analysis = `# Profile Analysis and Performance Insights\n\n`; // Profile summary statistics const totalProfiles = profiles.length; const profileTypes = [...new Set(profiles.map((p) => p.profileType))]; const targets = [ ...new Set(profiles.map((p) => p.deployment?.target).filter(Boolean)), ]; analysis += `## Summary\n\n`; analysis += `- **Total Profiles:** ${totalProfiles}\n`; analysis += `- **Profile Types:** ${profileTypes.length} (${profileTypes.join(", ")})\n`; analysis += `- **Targets:** ${targets.length} (${targets.join(", ")})\n\n`; // Profile type distribution const typeDistribution = profiles.reduce( (acc, profile) => { acc[profile.profileType] = (acc[profile.profileType] || 0) + 1; return acc; }, {} as Record<string, number>, ); analysis += `## Profile Type Distribution\n\n`; Object.entries(typeDistribution) .sort(([, a], [, b]) => b - a) .forEach(([type, count]) => { const percentage = Math.round((count / totalProfiles) * 100); analysis += `- **${getProfileTypeDescription(type)}:** ${count} profiles (${percentage}%)\n`; }); analysis += `\n`; // Recent activity analysis const recentProfiles = profiles .filter((p) => p.startTime) .sort( (a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime(), ) .slice(0, 5); if (recentProfiles.length > 0) { analysis += `## Recent Profile Activity\n\n`; recentProfiles.forEach((profile, index) => { const timeAgo = getTimeAgo(profile.startTime); analysis += `${index + 1}. **${profile.deployment?.target || "Unknown Target"}** - ${getProfileTypeDescription(profile.profileType)} (${timeAgo})\n`; }); analysis += `\n`; } // Performance analysis by profile type analysis += `## Performance Analysis by Profile Type\n\n`; profileTypes.forEach((type) => { const typeProfiles = profiles.filter((p) => p.profileType === type); analysis += `### ${getProfileTypeDescription(type)}\n\n`; analysis += getProfileTypeAnalysis(type, typeProfiles); analysis += `\n`; }); // Recommendations analysis += `## Recommendations\n\n`; analysis += getPerformanceRecommendations(profiles, typeDistribution); return analysis; }
  • Helper function used in handler for temporal analysis of profile collection: sorts by startTime, categorizes into recent/this week/older, reports counts and spans.
    function analyseProfileTimeDistribution(profiles: Profile[]): string { const profilesByTime = profiles .filter((p) => p.startTime) .sort( (a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime(), ); if (profilesByTime.length === 0) { return "No time-stamped profiles available for temporal analysis.\n\n"; } let analysis = "### Profile Collection Timeline\n\n"; // Group by time buckets (last 24 hours, last week, older) const now = new Date().getTime(); const oneDayAgo = now - 24 * 60 * 60 * 1000; const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1000; const recent = profilesByTime.filter( (p) => new Date(p.startTime).getTime() > oneDayAgo, ); const thisWeek = profilesByTime.filter((p) => { const time = new Date(p.startTime).getTime(); return time <= oneDayAgo && time > oneWeekAgo; }); const older = profilesByTime.filter( (p) => new Date(p.startTime).getTime() <= oneWeekAgo, ); analysis += `- **Last 24 hours:** ${recent.length} profiles\n`; analysis += `- **Last week:** ${thisWeek.length} profiles\n`; analysis += `- **Older:** ${older.length} profiles\n\n`; if (recent.length > 0) { const oldestRecent = new Date(recent[0].startTime).toLocaleString(); const newestRecent = new Date( recent[recent.length - 1].startTime, ).toLocaleString(); analysis += `Recent activity spans from ${oldestRecent} to ${newestRecent}\n\n`; } return analysis; }

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/krzko/google-cloud-mcp'

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