Skip to main content
Glama
krzko

Google Cloud MCP Server

by krzko

gcp-profiler-analyse-performance

Analyze Google Cloud Profiler data to identify performance bottlenecks and optimize application efficiency in cloud environments.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • MCP server.tool registration for the 'gcp-profiler-analyse-performance' tool, including title 'Analyse Profile Performance', description, inputSchema with Zod validation for profileType, target, pageSize, and the inline async handler function.
      "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: authenticates with Google Cloud, fetches profiles from the Cloud Profiler API using REST, filters by profileType and target, performs analysis using helper functions like analyseProfilePatterns, analyseProfileTimeDistribution, analyseDeploymentPatterns, generates performance insights and actionable recommendations, formats markdown output.
    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: profileType (optional ProfileType enum), target (optional string for deployment filter), 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)",
        ),
    },
  • analyseProfilePatterns helper: analyses list of profiles for summary stats, type distribution, recent activity, type-specific insights, and generates 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;
    }
  • analyseProfileTimeDistribution helper: groups profiles by time buckets (last 24h, week, older), provides timeline analysis.
    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