Skip to main content
Glama
krzko

Google Cloud MCP Server

by krzko

Comprehensive Log Search

gcp-logging-search-comprehensive

Search Google Cloud logs across all payload types, fields, and metadata to find specific entries by term, time range, severity, or resource.

Instructions

Search across all log fields including textPayload, jsonPayload, protoPayload, labels, HTTP requests, and metadata. Provides maximum context.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
searchTermYesTerm to search for across all payload types and fields
timeRangeNoTime range to search (e.g., "1h", "24h", "7d")1h
severityNoMinimum severity level to filter by
resourceNoResource type to filter by (e.g., "cloud_function", "gke_container")
limitNoMaximum number of log entries to return

Implementation Reference

  • The main execution handler for 'gcp-logging-search-comprehensive'. Builds a sophisticated filter searching across textPayload, numerous jsonPayload fields (message, error, stack, HTTP details, etc.), protoPayload, labels, httpRequest fields, sourceLocation, and operation fields. Queries logs within time range, optional severity/resource filters, sorts by timestamp desc, and formats results.
    async ({ searchTerm, timeRange, severity, resource, limit }) => {
      try {
        const projectId = await getProjectId();
        const logging = getLoggingClient();
    
        const endTime = new Date();
        const startTime = parseRelativeTime(timeRange);
    
        // Build comprehensive search filter that searches across all payload types
        const filterParts = [
          `timestamp >= "${startTime.toISOString()}"`,
          `timestamp <= "${endTime.toISOString()}"`,
        ];
    
        // Add search term across multiple payload types and fields
        const searchParts = [
          `textPayload:("${searchTerm}")`,
          `jsonPayload.message:("${searchTerm}")`,
          `jsonPayload.msg:("${searchTerm}")`,
          `jsonPayload.error:("${searchTerm}")`,
          `jsonPayload.exception:("${searchTerm}")`,
          `jsonPayload.stack:("${searchTerm}")`,
          `jsonPayload.stackTrace:("${searchTerm}")`,
          `jsonPayload.description:("${searchTerm}")`,
          `jsonPayload.details:("${searchTerm}")`,
          `jsonPayload.reason:("${searchTerm}")`,
          `jsonPayload.code:("${searchTerm}")`,
          `jsonPayload.status:("${searchTerm}")`,
          `jsonPayload.method:("${searchTerm}")`,
          `jsonPayload.url:("${searchTerm}")`,
          `jsonPayload.path:("${searchTerm}")`,
          `jsonPayload.endpoint:("${searchTerm}")`,
          `jsonPayload.service:("${searchTerm}")`,
          `jsonPayload.operation:("${searchTerm}")`,
          `jsonPayload.function:("${searchTerm}")`,
          `jsonPayload.name:("${searchTerm}")`,
          `jsonPayload.type:("${searchTerm}")`,
          `jsonPayload.level:("${searchTerm}")`,
          `jsonPayload.category:("${searchTerm}")`,
          `jsonPayload.component:("${searchTerm}")`,
          `jsonPayload.module:("${searchTerm}")`,
          `jsonPayload.class:("${searchTerm}")`,
          `jsonPayload.thread:("${searchTerm}")`,
          `jsonPayload.user:("${searchTerm}")`,
          `jsonPayload.userId:("${searchTerm}")`,
          `jsonPayload.sessionId:("${searchTerm}")`,
          `jsonPayload.requestId:("${searchTerm}")`,
          `jsonPayload.traceId:("${searchTerm}")`,
          `jsonPayload.spanId:("${searchTerm}")`,
          `jsonPayload.host:("${searchTerm}")`,
          `jsonPayload.hostname:("${searchTerm}")`,
          `jsonPayload.ip:("${searchTerm}")`,
          `jsonPayload.port:("${searchTerm}")`,
          `protoPayload.methodName:("${searchTerm}")`,
          `protoPayload.serviceName:("${searchTerm}")`,
          `protoPayload.resourceName:("${searchTerm}")`,
          `labels.service:("${searchTerm}")`,
          `labels.version:("${searchTerm}")`,
          `labels.environment:("${searchTerm}")`,
          `labels.region:("${searchTerm}")`,
          `labels.zone:("${searchTerm}")`,
          `httpRequest.requestUrl:("${searchTerm}")`,
          `httpRequest.userAgent:("${searchTerm}")`,
          `httpRequest.remoteIp:("${searchTerm}")`,
          `httpRequest.referer:("${searchTerm}")`,
          `sourceLocation.file:("${searchTerm}")`,
          `sourceLocation.function:("${searchTerm}")`,
          `operation.id:("${searchTerm}")`,
          `operation.producer:("${searchTerm}")`,
        ];
    
        filterParts.push(`(${searchParts.join(" OR ")})`);
    
        // Add severity filter if specified
        if (severity) {
          filterParts.push(`severity >= ${severity}`);
        }
    
        // Add resource filter if specified
        if (resource) {
          filterParts.push(`resource.type = "${resource}"`);
        }
    
        const filter = filterParts.join(" AND ");
    
        const [entries] = await logging.getEntries({
          pageSize: limit,
          filter,
          orderBy: "timestamp desc",
        });
    
        if (!entries || entries.length === 0) {
          return {
            content: [
              {
                type: "text",
                text: `# Comprehensive Log Search Results\n\nProject: ${projectId}\nSearch Term: "${searchTerm}"\nTime Range: ${startTime.toISOString()} to ${endTime.toISOString()}\nSeverity: ${severity || "All levels"}\nResource: ${resource || "All resources"}\n\n**No matching log entries found.**\n\nThe search looked across:\n- Text payloads\n- JSON payload fields (message, error, exception, etc.)\n- Proto payload fields\n- Labels\n- HTTP request details\n- Source location\n- Operation details`,
              },
            ],
          };
        }
    
        const formattedLogs = entries
          .map((entry) => {
            try {
              return formatLogEntry(entry as unknown as LogEntry);
            } catch (err: unknown) {
              const errorMessage =
                err instanceof Error ? err.message : "Unknown error";
              return `## Error Formatting Log Entry\n\nAn error occurred while formatting a log entry: ${errorMessage}`;
            }
          })
          .join("\n\n---\n\n");
    
        return {
          content: [
            {
              type: "text",
              text: `# Comprehensive Log Search Results\n\nProject: ${projectId}\nSearch Term: "${searchTerm}"\nTime Range: ${startTime.toISOString()} to ${endTime.toISOString()}\nSeverity: ${severity || "All levels"}\nResource: ${resource || "All resources"}\nEntries Found: ${entries.length}\n\n**Search Coverage:**\nThis search looked across all payload types and fields including:\n- Text payloads\n- JSON payload fields (message, error, exception, stack traces, HTTP details, etc.)\n- Proto payload fields\n- Labels and metadata\n- HTTP request details\n- Source location information\n- Operation details\n\n---\n\n${formattedLogs}`,
            },
          ],
        };
      } catch (error: unknown) {
        const errorMessage =
          error instanceof Error ? error.message : "Unknown error";
    
        return {
          content: [
            {
              type: "text",
              text: `# Error in Comprehensive Log Search\n\nAn error occurred while searching logs: ${errorMessage}\n\nPlease check your search parameters and try again.`,
            },
          ],
          isError: true,
        };
      }
    },
  • The tool schema definition including title, description, and inputSchema with Zod validation for searchTerm, timeRange, severity enum, resource, and limit.
    {
      title: "Comprehensive Log Search",
      description:
        "Search across all log fields including textPayload, jsonPayload, protoPayload, labels, HTTP requests, and metadata. Provides maximum context.",
      inputSchema: {
        searchTerm: z
          .string()
          .describe("Term to search for across all payload types and fields"),
        timeRange: z
          .string()
          .default("1h")
          .describe('Time range to search (e.g., "1h", "24h", "7d")'),
        severity: z
          .enum([
            "DEFAULT",
            "DEBUG",
            "INFO",
            "NOTICE",
            "WARNING",
            "ERROR",
            "CRITICAL",
            "ALERT",
            "EMERGENCY",
          ])
          .optional()
          .describe("Minimum severity level to filter by"),
        resource: z
          .string()
          .optional()
          .describe(
            'Resource type to filter by (e.g., "cloud_function", "gke_container")',
          ),
        limit: z
          .number()
          .min(1)
          .max(500)
          .default(50)
          .describe("Maximum number of log entries to return"),
      },
    },
  • The server.registerTool call that registers the 'gcp-logging-search-comprehensive' tool with the MCP server.
    server.registerTool(
      "gcp-logging-search-comprehensive",
      {
        title: "Comprehensive Log Search",
        description:
          "Search across all log fields including textPayload, jsonPayload, protoPayload, labels, HTTP requests, and metadata. Provides maximum context.",
        inputSchema: {
          searchTerm: z
            .string()
            .describe("Term to search for across all payload types and fields"),
          timeRange: z
            .string()
            .default("1h")
            .describe('Time range to search (e.g., "1h", "24h", "7d")'),
          severity: z
            .enum([
              "DEFAULT",
              "DEBUG",
              "INFO",
              "NOTICE",
              "WARNING",
              "ERROR",
              "CRITICAL",
              "ALERT",
              "EMERGENCY",
            ])
            .optional()
            .describe("Minimum severity level to filter by"),
          resource: z
            .string()
            .optional()
            .describe(
              'Resource type to filter by (e.g., "cloud_function", "gke_container")',
            ),
          limit: z
            .number()
            .min(1)
            .max(500)
            .default(50)
            .describe("Maximum number of log entries to return"),
        },
      },
      async ({ searchTerm, timeRange, severity, resource, limit }) => {
        try {
          const projectId = await getProjectId();
          const logging = getLoggingClient();
    
          const endTime = new Date();
          const startTime = parseRelativeTime(timeRange);
    
          // Build comprehensive search filter that searches across all payload types
          const filterParts = [
            `timestamp >= "${startTime.toISOString()}"`,
            `timestamp <= "${endTime.toISOString()}"`,
          ];
    
          // Add search term across multiple payload types and fields
          const searchParts = [
            `textPayload:("${searchTerm}")`,
            `jsonPayload.message:("${searchTerm}")`,
            `jsonPayload.msg:("${searchTerm}")`,
            `jsonPayload.error:("${searchTerm}")`,
            `jsonPayload.exception:("${searchTerm}")`,
            `jsonPayload.stack:("${searchTerm}")`,
            `jsonPayload.stackTrace:("${searchTerm}")`,
            `jsonPayload.description:("${searchTerm}")`,
            `jsonPayload.details:("${searchTerm}")`,
            `jsonPayload.reason:("${searchTerm}")`,
            `jsonPayload.code:("${searchTerm}")`,
            `jsonPayload.status:("${searchTerm}")`,
            `jsonPayload.method:("${searchTerm}")`,
            `jsonPayload.url:("${searchTerm}")`,
            `jsonPayload.path:("${searchTerm}")`,
            `jsonPayload.endpoint:("${searchTerm}")`,
            `jsonPayload.service:("${searchTerm}")`,
            `jsonPayload.operation:("${searchTerm}")`,
            `jsonPayload.function:("${searchTerm}")`,
            `jsonPayload.name:("${searchTerm}")`,
            `jsonPayload.type:("${searchTerm}")`,
            `jsonPayload.level:("${searchTerm}")`,
            `jsonPayload.category:("${searchTerm}")`,
            `jsonPayload.component:("${searchTerm}")`,
            `jsonPayload.module:("${searchTerm}")`,
            `jsonPayload.class:("${searchTerm}")`,
            `jsonPayload.thread:("${searchTerm}")`,
            `jsonPayload.user:("${searchTerm}")`,
            `jsonPayload.userId:("${searchTerm}")`,
            `jsonPayload.sessionId:("${searchTerm}")`,
            `jsonPayload.requestId:("${searchTerm}")`,
            `jsonPayload.traceId:("${searchTerm}")`,
            `jsonPayload.spanId:("${searchTerm}")`,
            `jsonPayload.host:("${searchTerm}")`,
            `jsonPayload.hostname:("${searchTerm}")`,
            `jsonPayload.ip:("${searchTerm}")`,
            `jsonPayload.port:("${searchTerm}")`,
            `protoPayload.methodName:("${searchTerm}")`,
            `protoPayload.serviceName:("${searchTerm}")`,
            `protoPayload.resourceName:("${searchTerm}")`,
            `labels.service:("${searchTerm}")`,
            `labels.version:("${searchTerm}")`,
            `labels.environment:("${searchTerm}")`,
            `labels.region:("${searchTerm}")`,
            `labels.zone:("${searchTerm}")`,
            `httpRequest.requestUrl:("${searchTerm}")`,
            `httpRequest.userAgent:("${searchTerm}")`,
            `httpRequest.remoteIp:("${searchTerm}")`,
            `httpRequest.referer:("${searchTerm}")`,
            `sourceLocation.file:("${searchTerm}")`,
            `sourceLocation.function:("${searchTerm}")`,
            `operation.id:("${searchTerm}")`,
            `operation.producer:("${searchTerm}")`,
          ];
    
          filterParts.push(`(${searchParts.join(" OR ")})`);
    
          // Add severity filter if specified
          if (severity) {
            filterParts.push(`severity >= ${severity}`);
          }
    
          // Add resource filter if specified
          if (resource) {
            filterParts.push(`resource.type = "${resource}"`);
          }
    
          const filter = filterParts.join(" AND ");
    
          const [entries] = await logging.getEntries({
            pageSize: limit,
            filter,
            orderBy: "timestamp desc",
          });
    
          if (!entries || entries.length === 0) {
            return {
              content: [
                {
                  type: "text",
                  text: `# Comprehensive Log Search Results\n\nProject: ${projectId}\nSearch Term: "${searchTerm}"\nTime Range: ${startTime.toISOString()} to ${endTime.toISOString()}\nSeverity: ${severity || "All levels"}\nResource: ${resource || "All resources"}\n\n**No matching log entries found.**\n\nThe search looked across:\n- Text payloads\n- JSON payload fields (message, error, exception, etc.)\n- Proto payload fields\n- Labels\n- HTTP request details\n- Source location\n- Operation details`,
                },
              ],
            };
          }
    
          const formattedLogs = entries
            .map((entry) => {
              try {
                return formatLogEntry(entry as unknown as LogEntry);
              } catch (err: unknown) {
                const errorMessage =
                  err instanceof Error ? err.message : "Unknown error";
                return `## Error Formatting Log Entry\n\nAn error occurred while formatting a log entry: ${errorMessage}`;
              }
            })
            .join("\n\n---\n\n");
    
          return {
            content: [
              {
                type: "text",
                text: `# Comprehensive Log Search Results\n\nProject: ${projectId}\nSearch Term: "${searchTerm}"\nTime Range: ${startTime.toISOString()} to ${endTime.toISOString()}\nSeverity: ${severity || "All levels"}\nResource: ${resource || "All resources"}\nEntries Found: ${entries.length}\n\n**Search Coverage:**\nThis search looked across all payload types and fields including:\n- Text payloads\n- JSON payload fields (message, error, exception, stack traces, HTTP details, etc.)\n- Proto payload fields\n- Labels and metadata\n- HTTP request details\n- Source location information\n- Operation details\n\n---\n\n${formattedLogs}`,
              },
            ],
          };
        } catch (error: unknown) {
          const errorMessage =
            error instanceof Error ? error.message : "Unknown error";
    
          return {
            content: [
              {
                type: "text",
                text: `# Error in Comprehensive Log Search\n\nAn error occurred while searching logs: ${errorMessage}\n\nPlease check your search parameters and try again.`,
              },
            ],
            isError: true,
          };
        }
      },
    );
  • formatLogEntry helper function used to format each log entry into a comprehensive markdown display including timestamp, severity, resource, metadata, trace info, HTTP details, labels, and payloads.
    export function formatLogEntry(entry: LogEntry): string {
      // Safely format the timestamp
      let timestamp: string;
      try {
        if (!entry.timestamp) {
          timestamp = "No timestamp";
        } else {
          const date = new Date(entry.timestamp);
          timestamp = !isNaN(date.getTime())
            ? date.toISOString()
            : String(entry.timestamp);
        }
      } catch {
        timestamp = String(entry.timestamp || "Invalid timestamp");
      }
    
      const severity = entry.severity || "DEFAULT";
      const resourceType = entry.resource?.type || "unknown";
      const resourceLabels = entry.resource?.labels
        ? Object.entries(entry.resource.labels)
            .map(([k, v]) => `${k}=${v}`)
            .join(", ")
        : "";
    
      const resource = resourceLabels
        ? `${resourceType}(${resourceLabels})`
        : resourceType;
    
      // Start building the comprehensive log entry display
      let result = `## ${timestamp} | ${severity} | ${resource}\n\n`;
    
      // Basic metadata
      if (entry.logName) result += `**Log Name:** ${entry.logName}\n`;
      if (entry.insertId) result += `**Insert ID:** ${entry.insertId}\n`;
      if (entry.receiveTimestamp) {
        try {
          const receiveTime = new Date(entry.receiveTimestamp).toISOString();
          result += `**Receive Time:** ${receiveTime}\n`;
        } catch {
          result += `**Receive Time:** ${entry.receiveTimestamp}\n`;
        }
      }
    
      // Trace context information
      if (entry.trace) result += `**Trace:** ${entry.trace}\n`;
      if (entry.spanId) result += `**Span ID:** ${entry.spanId}\n`;
      if (entry.traceSampled !== undefined)
        result += `**Trace Sampled:** ${entry.traceSampled}\n`;
    
      // Source location if available
      if (entry.sourceLocation) {
        result += `**Source Location:**\n`;
        if (entry.sourceLocation.file)
          result += `  - File: ${entry.sourceLocation.file}\n`;
        if (entry.sourceLocation.line)
          result += `  - Line: ${entry.sourceLocation.line}\n`;
        if (entry.sourceLocation.function)
          result += `  - Function: ${entry.sourceLocation.function}\n`;
      }
    
      // HTTP request details if available
      if (entry.httpRequest) {
        result += `**HTTP Request:**\n`;
        if (entry.httpRequest.requestMethod)
          result += `  - Method: ${entry.httpRequest.requestMethod}\n`;
        if (entry.httpRequest.requestUrl)
          result += `  - URL: ${entry.httpRequest.requestUrl}\n`;
        if (entry.httpRequest.status)
          result += `  - Status: ${entry.httpRequest.status}\n`;
        if (entry.httpRequest.userAgent)
          result += `  - User Agent: ${entry.httpRequest.userAgent}\n`;
        if (entry.httpRequest.remoteIp)
          result += `  - Remote IP: ${entry.httpRequest.remoteIp}\n`;
        if (entry.httpRequest.latency)
          result += `  - Latency: ${entry.httpRequest.latency}\n`;
        if (entry.httpRequest.requestSize)
          result += `  - Request Size: ${entry.httpRequest.requestSize}\n`;
        if (entry.httpRequest.responseSize)
          result += `  - Response Size: ${entry.httpRequest.responseSize}\n`;
        if (entry.httpRequest.referer)
          result += `  - Referer: ${entry.httpRequest.referer}\n`;
        if (entry.httpRequest.protocol)
          result += `  - Protocol: ${entry.httpRequest.protocol}\n`;
        if (entry.httpRequest.cacheHit !== undefined)
          result += `  - Cache Hit: ${entry.httpRequest.cacheHit}\n`;
        if (entry.httpRequest.cacheLookup !== undefined)
          result += `  - Cache Lookup: ${entry.httpRequest.cacheLookup}\n`;
        if (entry.httpRequest.cacheValidatedWithOriginServer !== undefined) {
          result += `  - Cache Validated: ${entry.httpRequest.cacheValidatedWithOriginServer}\n`;
        }
        if (entry.httpRequest.cacheFillBytes)
          result += `  - Cache Fill Bytes: ${entry.httpRequest.cacheFillBytes}\n`;
      }
    
      // Operation details if available
      if (entry.operation) {
        result += `**Operation:**\n`;
        if (entry.operation.id) result += `  - ID: ${entry.operation.id}\n`;
        if (entry.operation.producer)
          result += `  - Producer: ${entry.operation.producer}\n`;
        if (entry.operation.first !== undefined)
          result += `  - First: ${entry.operation.first}\n`;
        if (entry.operation.last !== undefined)
          result += `  - Last: ${entry.operation.last}\n`;
      }
    
      // Labels if they exist
      if (entry.labels && Object.keys(entry.labels).length > 0) {
        try {
          result += `**Labels:**\n`;
          Object.entries(entry.labels).forEach(([key, value]) => {
            result += `  - ${key}: ${value}\n`;
          });
        } catch (error: unknown) {
          const errorMessage =
            error instanceof Error ? error.message : "Unknown error";
          result += `**Labels:** [Error formatting labels: ${errorMessage}]\n`;
        }
      }
    
      // Add any additional fields that might be present
      const knownFields = new Set([
        "timestamp",
        "severity",
        "resource",
        "logName",
        "textPayload",
        "jsonPayload",
        "protoPayload",
        "labels",
        "insertId",
        "trace",
        "spanId",
        "traceSampled",
        "sourceLocation",
        "httpRequest",
        "operation",
        "receiveTimestamp",
      ]);
    
      const additionalFields: Record<string, unknown> = {};
      Object.entries(entry).forEach(([key, value]) => {
        if (!knownFields.has(key) && value !== undefined && value !== null) {
          additionalFields[key] = value;
        }
      });
    
      if (Object.keys(additionalFields).length > 0) {
        result += `**Additional Fields:**\n`;
        try {
          result += `\`\`\`json\n${JSON.stringify(additionalFields, null, 2)}\n\`\`\`\n`;
        } catch (error: unknown) {
          const errorMessage =
            error instanceof Error ? error.message : "Unknown error";
          result += `[Error formatting additional fields: ${errorMessage}]\n`;
        }
      }
    
      // Format the main payload
      result += `\n**Payload:**\n`;
      try {
        if (entry.textPayload !== undefined && entry.textPayload !== null) {
          result += `\`\`\`\n${String(entry.textPayload)}\n\`\`\``;
        } else if (entry.jsonPayload) {
          result += `\`\`\`json\n${JSON.stringify(entry.jsonPayload, null, 2)}\n\`\`\``;
        } else if (entry.protoPayload) {
          result += `\`\`\`json\n${JSON.stringify(entry.protoPayload, null, 2)}\n\`\`\``;
        } else {
          // Check for any other payload-like fields
          const data = entry.data || entry.message || entry.msg;
          if (data) {
            if (typeof data === "string") {
              result += `\`\`\`\n${data}\n\`\`\``;
            } else {
              result += `\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``;
            }
          } else {
            result += `\`\`\`\n[No payload available]\n\`\`\``;
          }
        }
      } catch (error: unknown) {
        const errorMessage =
          error instanceof Error ? error.message : "Unknown error";
        result += `\`\`\`\n[Error formatting payload: ${errorMessage}]\n\`\`\``;
      }
    
      return result;
    }
  • getLoggingClient helper that initializes and returns the Google Cloud Logging client instance.
    export function getLoggingClient(): Logging {
      return new Logging({
        projectId: process.env.GOOGLE_CLOUD_PROJECT,
      });
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden but offers minimal behavioral disclosure. It mentions 'maximum context' but doesn't describe pagination, rate limits, authentication requirements, performance characteristics, or what 'comprehensive' entails operationally. For a search tool with 5 parameters and no annotations, this leaves significant gaps in understanding how the tool behaves.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in two sentences: the first specifies what fields are searched, the second characterizes the scope. It's appropriately sized without unnecessary elaboration. However, it could be slightly more front-loaded by immediately stating it's for comprehensive log searches rather than ending with 'maximum context'.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a search tool with 5 parameters, no annotations, and no output schema, the description is inadequate. It doesn't explain return format, pagination, error handling, or performance implications of 'comprehensive' searches. The lack of behavioral transparency and minimal parameter guidance leaves the agent with insufficient context to use this tool effectively beyond basic parameter passing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 5 parameters. The description adds marginal value by implying the searchTerm applies across 'all payload types and fields' (reinforcing schema's 'across all payload types and fields'), but doesn't provide additional syntax examples, format details, or constraints beyond what the schema already specifies. Baseline 3 is appropriate when schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches across all log fields including specific payload types and metadata, with 'maximum context' indicating comprehensive coverage. It distinguishes from sibling 'gcp-logging-query-logs' by emphasizing breadth rather than just querying logs. However, it doesn't explicitly contrast with other logging siblings like 'gcp-logging-query-time-range' or 'gcp-trace-find-from-logs'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'gcp-logging-query-logs' or 'gcp-logging-query-time-range', nor does it specify use cases where comprehensive search is preferred over more targeted queries. The phrase 'maximum context' implies broad searches but lacks explicit when/when-not criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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