Skip to main content
Glama
krzko

Google Cloud MCP Server

by krzko

gcp-error-reporting-get-group-details

Retrieve detailed information about error groups in Google Cloud Error Reporting to analyze and troubleshoot application issues.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The core handler function for the 'gcp-error-reporting-get-group-details' tool. It authenticates with Google Cloud, fetches detailed error group information and recent error events using the Error Reporting REST API, parses and formats the data into a comprehensive Markdown report including group metadata, event details (timestamps, service context, messages, HTTP requests, source locations), and suggested investigation steps.
    async ({ groupId, timeRange, pageSize }) => {
      try {
        const projectId = await getProjectId();
        // Initialize Google Auth client (same pattern as trace service)
        const auth = await initGoogleAuth(true);
        if (!auth) {
          throw new GcpMcpError(
            "Google Cloud authentication not available. Please configure authentication to access error reporting data.",
            "UNAUTHENTICATED",
            401,
          );
        }
        const client = await auth.getClient();
        const token = await client.getAccessToken();
    
        // Parse time range - ensure we have a valid timeRange value
        const actualTimeRange = timeRange || "24h";
        const actualPageSize = pageSize || 10;
    
        // Map time range to Google Cloud Error Reporting periods
        let period: string;
        switch (actualTimeRange) {
          case "1h":
            period = "PERIOD_1_HOUR";
            break;
          case "6h":
            period = "PERIOD_6_HOURS";
            break;
          case "24h":
          case "1d":
            period = "PERIOD_1_DAY";
            break;
          case "7d":
            period = "PERIOD_1_WEEK";
            break;
          case "30d":
            period = "PERIOD_30_DAYS";
            break;
          default:
            // Default to 1 day for event details
            period = "PERIOD_1_DAY";
            break;
        }
    
        // First, get the error group details using projects.groups/get
        // The group name format should be: projects/{projectId}/groups/{groupId}
        const groupName = `projects/${projectId}/groups/${groupId}`;
        const groupApiUrl = `https://clouderrorreporting.googleapis.com/v1beta1/${groupName}`;
    
        // Get group details
        const groupResponse = await fetch(groupApiUrl, {
          method: "GET",
          headers: {
            Authorization: `Bearer ${token.token}`,
            Accept: "application/json",
          },
        });
    
        if (!groupResponse.ok) {
          const errorText = await groupResponse.text();
          throw new GcpMcpError(
            `Failed to fetch error group details: ${errorText}`,
            "FAILED_PRECONDITION",
            groupResponse.status,
          );
        }
    
        const groupData = await groupResponse.json();
    
        // Build query parameters for events API
        // groupId should be the raw group identifier for the events API
        const params = new URLSearchParams({
          groupId: groupId,
          "timeRange.period": period,
          pageSize: actualPageSize.toString(),
        });
    
        // Make REST API call to list events
        const apiUrl = `https://clouderrorreporting.googleapis.com/v1beta1/projects/${projectId}/events?${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 error events: ${errorText}`,
            "FAILED_PRECONDITION",
            response.status,
          );
        }
    
        const data = await response.json();
        const errorEvents = data.errorEvents || [];
    
        // Start building content with group details
        let content = `# Error Group Details\n\n`;
    
        // Add group information
        content += `**Group ID:** ${groupId}\n`;
        content += `**Project:** ${projectId}\n`;
        content += `**Group Name:** ${groupData.name || "Unknown"}\n`;
        if (groupData.resolutionStatus) {
          content += `**Resolution Status:** ${groupData.resolutionStatus}\n`;
        }
        if (groupData.trackingIssues && groupData.trackingIssues.length > 0) {
          content += `**Tracking Issues:** ${groupData.trackingIssues.length} linked\n`;
        }
        content += `**Time Range:** ${actualTimeRange}\n\n`;
    
        if (!errorEvents || errorEvents.length === 0) {
          content += `## Recent Error Events\n\nNo error events found for this group in the specified time range.`;
          return {
            content: [
              {
                type: "text",
                text: content,
              },
            ],
          };
        }
    
        content += `## Recent Error Events (${errorEvents.length})\n\n`;
    
        errorEvents.forEach((event: any, index: number) => {
          content += `### Event ${index + 1}\n\n`;
          content += `**Time:** ${new Date(event.eventTime).toLocaleString()}\n`;
          content += `**Service:** ${event.serviceContext?.service || "Unknown"}`;
          if (event.serviceContext?.version) {
            content += ` (v${event.serviceContext.version})`;
          }
          content += `\n\n`;
          content += `**Message:** ${event.message}\n\n`;
    
          if (event.context?.httpRequest) {
            const req = event.context.httpRequest;
            content += `**HTTP Request:**\n`;
            if (req.method && req.url) {
              content += `- ${req.method} ${req.url}\n`;
            }
            if (req.responseStatusCode) {
              content += `- Status: ${req.responseStatusCode}\n`;
            }
            if (req.userAgent) {
              content += `- User Agent: ${req.userAgent}\n`;
            }
            if (req.remoteIp) {
              content += `- Remote IP: ${req.remoteIp}\n`;
            }
            content += `\n`;
          }
    
          if (event.context?.reportLocation) {
            const loc = event.context.reportLocation;
            content += `**Source Location:**\n`;
            if (loc.filePath) {
              content += `- File: ${loc.filePath}`;
              if (loc.lineNumber) {
                content += `:${loc.lineNumber}`;
              }
              content += `\n`;
            }
            if (loc.functionName) {
              content += `- Function: ${loc.functionName}\n`;
            }
            content += `\n`;
          }
    
          if (event.context?.user) {
            content += `**User:** ${event.context.user}\n\n`;
          }
    
          content += `---\n\n`;
        });
    
        // Add investigation suggestions
        content += `## Investigation Steps\n\n`;
        content += `1. **Check Logs:** Use Cloud Logging to find related log entries around the error times\n`;
        content += `2. **Monitor Metrics:** Review monitoring dashboards for correlated performance metrics\n`;
        content += `3. **Recent Changes:** Check recent deployments and configuration changes\n`;
        content += `4. **Pattern Analysis:** Look for patterns in user agents, IP addresses, or request parameters\n`;
        content += `5. **Trace Analysis:** If available, examine distributed traces for request flow\n\n`;
    
        return {
          content: [
            {
              type: "text",
              text: content,
            },
          ],
        };
      } catch (error: unknown) {
        const errorMessage =
          error instanceof Error ? error.message : "Unknown error";
        throw new GcpMcpError(
          `Failed to get error group details: ${errorMessage}`,
          "INTERNAL_ERROR",
          500,
        );
      }
    },
  • Zod-based input schema validation for the tool, defining parameters: groupId (required string), timeRange (optional string, default '24h'), pageSize (optional number 1-100, default 10).
    inputSchema: {
      groupId: z.string().describe("Error group ID to get details for"),
      timeRange: z
        .string()
        .optional()
        .default("24h")
        .describe('Time range to query events (e.g., "1h", "24h", "7d")'),
      pageSize: z
        .number()
        .min(1)
        .max(100)
        .default(10)
        .describe("Maximum number of error events to return"),
    },
  • Registration of the tool on the MCP server within the registerErrorReportingTools function, specifying name, metadata (title, description), input schema, and handler implementation.
      "gcp-error-reporting-get-group-details",
      {
        title: "Get Error Group Details",
        description:
          "Get detailed information about a specific error group including recent events",
        inputSchema: {
          groupId: z.string().describe("Error group ID to get details for"),
          timeRange: z
            .string()
            .optional()
            .default("24h")
            .describe('Time range to query events (e.g., "1h", "24h", "7d")'),
          pageSize: z
            .number()
            .min(1)
            .max(100)
            .default(10)
            .describe("Maximum number of error events to return"),
        },
      },
      async ({ groupId, timeRange, pageSize }) => {
        try {
          const projectId = await getProjectId();
          // Initialize Google Auth client (same pattern as trace service)
          const auth = await initGoogleAuth(true);
          if (!auth) {
            throw new GcpMcpError(
              "Google Cloud authentication not available. Please configure authentication to access error reporting data.",
              "UNAUTHENTICATED",
              401,
            );
          }
          const client = await auth.getClient();
          const token = await client.getAccessToken();
    
          // Parse time range - ensure we have a valid timeRange value
          const actualTimeRange = timeRange || "24h";
          const actualPageSize = pageSize || 10;
    
          // Map time range to Google Cloud Error Reporting periods
          let period: string;
          switch (actualTimeRange) {
            case "1h":
              period = "PERIOD_1_HOUR";
              break;
            case "6h":
              period = "PERIOD_6_HOURS";
              break;
            case "24h":
            case "1d":
              period = "PERIOD_1_DAY";
              break;
            case "7d":
              period = "PERIOD_1_WEEK";
              break;
            case "30d":
              period = "PERIOD_30_DAYS";
              break;
            default:
              // Default to 1 day for event details
              period = "PERIOD_1_DAY";
              break;
          }
    
          // First, get the error group details using projects.groups/get
          // The group name format should be: projects/{projectId}/groups/{groupId}
          const groupName = `projects/${projectId}/groups/${groupId}`;
          const groupApiUrl = `https://clouderrorreporting.googleapis.com/v1beta1/${groupName}`;
    
          // Get group details
          const groupResponse = await fetch(groupApiUrl, {
            method: "GET",
            headers: {
              Authorization: `Bearer ${token.token}`,
              Accept: "application/json",
            },
          });
    
          if (!groupResponse.ok) {
            const errorText = await groupResponse.text();
            throw new GcpMcpError(
              `Failed to fetch error group details: ${errorText}`,
              "FAILED_PRECONDITION",
              groupResponse.status,
            );
          }
    
          const groupData = await groupResponse.json();
    
          // Build query parameters for events API
          // groupId should be the raw group identifier for the events API
          const params = new URLSearchParams({
            groupId: groupId,
            "timeRange.period": period,
            pageSize: actualPageSize.toString(),
          });
    
          // Make REST API call to list events
          const apiUrl = `https://clouderrorreporting.googleapis.com/v1beta1/projects/${projectId}/events?${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 error events: ${errorText}`,
              "FAILED_PRECONDITION",
              response.status,
            );
          }
    
          const data = await response.json();
          const errorEvents = data.errorEvents || [];
    
          // Start building content with group details
          let content = `# Error Group Details\n\n`;
    
          // Add group information
          content += `**Group ID:** ${groupId}\n`;
          content += `**Project:** ${projectId}\n`;
          content += `**Group Name:** ${groupData.name || "Unknown"}\n`;
          if (groupData.resolutionStatus) {
            content += `**Resolution Status:** ${groupData.resolutionStatus}\n`;
          }
          if (groupData.trackingIssues && groupData.trackingIssues.length > 0) {
            content += `**Tracking Issues:** ${groupData.trackingIssues.length} linked\n`;
          }
          content += `**Time Range:** ${actualTimeRange}\n\n`;
    
          if (!errorEvents || errorEvents.length === 0) {
            content += `## Recent Error Events\n\nNo error events found for this group in the specified time range.`;
            return {
              content: [
                {
                  type: "text",
                  text: content,
                },
              ],
            };
          }
    
          content += `## Recent Error Events (${errorEvents.length})\n\n`;
    
          errorEvents.forEach((event: any, index: number) => {
            content += `### Event ${index + 1}\n\n`;
            content += `**Time:** ${new Date(event.eventTime).toLocaleString()}\n`;
            content += `**Service:** ${event.serviceContext?.service || "Unknown"}`;
            if (event.serviceContext?.version) {
              content += ` (v${event.serviceContext.version})`;
            }
            content += `\n\n`;
            content += `**Message:** ${event.message}\n\n`;
    
            if (event.context?.httpRequest) {
              const req = event.context.httpRequest;
              content += `**HTTP Request:**\n`;
              if (req.method && req.url) {
                content += `- ${req.method} ${req.url}\n`;
              }
              if (req.responseStatusCode) {
                content += `- Status: ${req.responseStatusCode}\n`;
              }
              if (req.userAgent) {
                content += `- User Agent: ${req.userAgent}\n`;
              }
              if (req.remoteIp) {
                content += `- Remote IP: ${req.remoteIp}\n`;
              }
              content += `\n`;
            }
    
            if (event.context?.reportLocation) {
              const loc = event.context.reportLocation;
              content += `**Source Location:**\n`;
              if (loc.filePath) {
                content += `- File: ${loc.filePath}`;
                if (loc.lineNumber) {
                  content += `:${loc.lineNumber}`;
                }
                content += `\n`;
              }
              if (loc.functionName) {
                content += `- Function: ${loc.functionName}\n`;
              }
              content += `\n`;
            }
    
            if (event.context?.user) {
              content += `**User:** ${event.context.user}\n\n`;
            }
    
            content += `---\n\n`;
          });
    
          // Add investigation suggestions
          content += `## Investigation Steps\n\n`;
          content += `1. **Check Logs:** Use Cloud Logging to find related log entries around the error times\n`;
          content += `2. **Monitor Metrics:** Review monitoring dashboards for correlated performance metrics\n`;
          content += `3. **Recent Changes:** Check recent deployments and configuration changes\n`;
          content += `4. **Pattern Analysis:** Look for patterns in user agents, IP addresses, or request parameters\n`;
          content += `5. **Trace Analysis:** If available, examine distributed traces for request flow\n\n`;
    
          return {
            content: [
              {
                type: "text",
                text: content,
              },
            ],
          };
        } catch (error: unknown) {
          const errorMessage =
            error instanceof Error ? error.message : "Unknown error";
          throw new GcpMcpError(
            `Failed to get error group details: ${errorMessage}`,
            "INTERNAL_ERROR",
            500,
          );
        }
      },
    );

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