UNPKG

@edjl/gcloud-mcp

Version:

Google Cloud Platform tools for MCP (Model Context Protocol)

169 lines 6.85 kB
import { z } from 'zod'; import { executeGCloudCommand, formatTimestamp } from '../../utils/gcloud.js'; const inputSchema = z.object({ filter: z.string().optional().describe('Log filter query (e.g., resource.type="k8s_container" AND severity>=ERROR)'), resource: z.string().optional().describe('Resource name to filter logs (e.g., k8s_container, gce_instance)'), logName: z.string().optional().describe('Specific log name to read'), severity: z.enum(['DEFAULT', 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY']).optional().describe('Minimum severity level'), since: z.string().optional().default('1h').describe('Time range (e.g., 1h, 2d, 2023-01-01T00:00:00Z)'), limit: z.number().optional().default(50).describe('Maximum number of log entries to return'), project: z.string().optional().describe('GCP project ID (uses current project if not specified)') }); const gcloudLogsReadTool = { name: 'logs_read', description: 'Read logs from Cloud Logging with various filters', category: 'logging', subcategory: 'logs', version: '1.0.0', inputSchema, handler: async (input) => { const params = inputSchema.parse(input); let command = 'gcloud logging read'; // Build filter const filters = []; if (params.filter) { filters.push(`(${params.filter})`); } if (params.resource) { filters.push(`resource.type="${params.resource}"`); } if (params.logName) { filters.push(`logName="${params.logName}"`); } if (params.severity) { filters.push(`severity>=${params.severity}`); } // Add timestamp filter if (params.since) { // Check if it's a relative time (e.g., 1h, 2d) or absolute if (params.since.match(/^\d+[hdm]$/)) { // Relative time const unit = params.since.slice(-1); const value = parseInt(params.since.slice(0, -1)); let timestamp = new Date(); if (unit === 'h') { timestamp.setHours(timestamp.getHours() - value); } else if (unit === 'd') { timestamp.setDate(timestamp.getDate() - value); } else if (unit === 'm') { timestamp.setMinutes(timestamp.getMinutes() - value); } filters.push(`timestamp>="${timestamp.toISOString()}"`); } else { // Absolute timestamp filters.push(`timestamp>="${params.since}"`); } } if (filters.length > 0) { const filterString = filters.join(' AND '); command += ` "${filterString}"`; } command += ` --limit=${params.limit}`; command += ' --format=json'; if (params.project) { command += ` --project=${params.project}`; } const result = await executeGCloudCommand(command); if (result.exitCode !== 0) { return { content: [{ type: 'text', text: `Error reading logs: ${result.stderr}` }], isError: true }; } let entries = []; try { entries = JSON.parse(result.stdout || '[]'); } catch { return { content: [{ type: 'text', text: 'No log entries found or invalid response format' }] }; } if (entries.length === 0) { return { content: [{ type: 'text', text: 'No log entries found matching the specified criteria' }] }; } let output = `Found ${entries.length} log entr${entries.length !== 1 ? 'ies' : 'y'}:\n`; output += '='.repeat(60) + '\n\n'; // Process entries (they come in reverse chronological order from gcloud) entries.forEach((entry, index) => { output += `[${index + 1}] ${formatTimestamp(entry.timestamp)} | ${entry.severity || 'DEFAULT'}\n`; // Resource information if (entry.resource) { output += ` Resource: ${entry.resource.type}`; if (entry.resource.labels) { const labelPairs = Object.entries(entry.resource.labels) .map(([k, v]) => `${k}=${v}`) .join(', '); output += ` (${labelPairs})`; } output += '\n'; } // Log name if (entry.logName) { const shortLogName = entry.logName.split('/').slice(-1)[0]; output += ` Log: ${shortLogName}\n`; } // Message content if (entry.textPayload) { output += ` Message: ${entry.textPayload}\n`; } else if (entry.jsonPayload) { output += ` JSON Payload:\n`; const jsonStr = JSON.stringify(entry.jsonPayload, null, 2); jsonStr.split('\n').forEach(line => { output += ` ${line}\n`; }); } else if (entry.protoPayload) { output += ` Proto Payload: ${entry.protoPayload['@type'] || 'Unknown type'}\n`; if (entry.protoPayload.methodName) { output += ` Method: ${entry.protoPayload.methodName}\n`; } } // Labels if (entry.labels && Object.keys(entry.labels).length > 0) { output += ` Labels: ${JSON.stringify(entry.labels)}\n`; } // Trace if (entry.trace) { output += ` Trace: ${entry.trace}\n`; } output += '\n'; }); // Summary by severity const severityCounts = {}; entries.forEach(entry => { const severity = entry.severity || 'DEFAULT'; severityCounts[severity] = (severityCounts[severity] || 0) + 1; }); output += 'Summary by Severity:\n'; output += '-'.repeat(30) + '\n'; Object.entries(severityCounts) .sort(([a], [b]) => a.localeCompare(b)) .forEach(([severity, count]) => { output += ` ${severity}: ${count}\n`; }); return { content: [{ type: 'text', text: output.trim() }] }; } }; export default gcloudLogsReadTool; //# sourceMappingURL=logs-read.js.map