gcp-error-reporting-get-group-details
Retrieve detailed error group information from Google Cloud Error Reporting to analyze and troubleshoot specific issues, enabling targeted resolution and improved system reliability.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- Handler function that authenticates with GCP using initGoogleAuth, fetches specific error group details via GET /projects/{projectId}/groups/{groupId}, lists recent error events via GET /projects/{projectId}/events?groupId={groupId}, formats comprehensive Markdown report with group info, event details (time, service, message, HTTP request, source location, user), and investigation recommendations.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, ); } },
- Input schema using Zod: 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"), },
- src/services/error-reporting/tools.ts:180-406 (registration)Tool registration via server.tool('gcp-error-reporting-get-group-details') with title 'Get Error Group Details', description, and inline inputSchema and handler.server.tool( "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, ); } }, );